Skip to Main Content

Breadcrumb

Connor and Chris will both be at AI World from October 12 to October 17 , the premier Oracle conference of 2025. If you're in Vegas, please come say Hi or pop into our sessions

Question and Answer

Tom Kyte

Thanks for the question, Serge.

Asked: February 27, 2005 - 8:10 pm UTC

Last updated: March 26, 2010 - 1:42 pm UTC

Version: 9.2.0.4

Viewed 1000+ times

You Asked

Tom,

Workink now on security issues on our project, I carefully read previous "asktom" questions and articles regarding SQL Injection but I didn't find something similar to the situation bellow:

I have applied as much as possible static SQL on our PL/SQL code and also bind variables in 99% of the cases where dynamic SQL is used.
However under the given design and requirements there still is a portion which worries me: couple of PL/SQL function/procedures have one of the input arguments in a form of a whole block of WHERE clause, as in following pseudocode example:

TYPE refCursor IS REF CURSOR;

create or replace function (arg1 IN VARCHAR2,
arg2 IN VARCHAR2,
v_where IN VARCHAR2)
RETURN refCursor
IS

sql_stmt VARCHAR2(4000);
c refCursor;

begin
if v_where is null then
sql_stmt := 'SELECT ... FROM table1 WHERE field1 = :1
AND field2 = :2 ';
open c for sql_stmt using arg1, arg2;

else
sql_stmt := 'SELECT ... FROM table1 WHERE field1 = :1
AND field2 = :2
/* And here could be the problem !!! */
AND ' || v_where;

open c for sql_stmt using arg1, arg2;

end if;

return c;
end;

The v_where argument can be any field/condition (of course any other than field1 and field2) in any number and any unpredictable combination, so don't ask me to redesign the application to do these things in another way 'cause is out of my posibilities.

Therefore I had to concatenate it, potentially dangerous for SQL injection.
Now, the function, as we can see, only returns a cursor to java, it doesn't have neither EXECUTE IMMEDIATE inside, nor 'SELECT INTO ... WHERE ... '.

Is this function (or procedure like this) exposed to SQL Injection or not ?
I tried to build some hacking scenarios but I couldn't.
In my opinion it is not exposed.

Thank you for your help.

and Tom said...


think about:

v_where => ' 1=1 UNION ALL select .... from some_table_i_should_not_see'


if the person providing the contents of v_where is an end user, this is the most egregious form of SQL Injection possible.

Basically, I can see almost any table the owner of this function can see...


You would need to see how this input is produced to see whether this can happen or not.

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Function calls can be as dangerous, or more so, than a SELECT

Gary, February 28, 2005 - 12:59 am UTC

Even if you scanned the clause for the SELECT keyword
it still allows function calls which can be a loophole.

While you can put the code in a specific schema that only has grants to limited tables and application packages, there is the danger from standard Oracle packages with grants to public (either existing ones, or ones that might come in future versions).

A simple but unlikely example is if you've been untidy with closing DBMS_SQL dynamic sqls, calls to DBMS_SQL.EXECUTE with some random numbers could have some nasty side-effects.

Tom Kyte
February 28, 2005 - 7:41 am UTC

this sql injection thing is harder than it looks at first. I wrote what I thought was a pretty simple routine in that same article:

</code> https://www.oracle.com/technetwork/issue-archive/2005/05-jan/o15asktom-084959.html <code>

after submitting it to code review to about 400,000+ people -- it was pointed out that it had a sql injection issue.

In a routine like the above, unless you totally trust the source passing the string in to you -- it would be a scary proposition. You would have to virtually parse the v_where clause to make sure it contains "good stuff"


(and of course the lack of bind variables is pretty disappointing too)

Alexander, March 23, 2010 - 11:54 am UTC

Here's one person who doesn't need to google "sql injection"

http://gizmodo.com/5498412/sql-injection-license-plate-hopes-to-foil-euro-traffic-cameras
Tom Kyte
March 23, 2010 - 12:57 pm UTC

I saw that :)

How to avoid SQL Injection ?

Krzysztof Wlasiuk, March 25, 2010 - 8:57 am UTC

Some time ago I had similar problem.
Solved by passing two arrays of strings - condition and bind value.

Example:
CONDITION           BINDVALUE
------------------------------------------------------------------
'and DEPTID=to_number(:DID)'      '122323'
'and CLIENT_NAME like :CNAME||'%'     'Tom'
'and REVISION_DATE<=to_date(:RD,''yyyy-mm-dd'')' '2009-04-23'


Then concatenate main query with conditions, using DBMS_SQL bind all values and run SQL :)

This will be safe only when BINDVALUE is coming from untrusted source, CONDITION must be constructed by 'trusted' code.

Tom - is my solution valid or I miss somthing ?
Tom Kyte
March 26, 2010 - 1:42 pm UTC



Your code is still subject to sql injection because of the condition bit. anyone that mucks with that table, that plsql array, whatever - can and will inject you.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library