Using Dynamic Query Execution
Many databases allow SQL
queries to be executed dynamically, by passing a string containing an
SQL query into a database function which executes the query. If you have
discovered a valid SQL injection point, but find that the application's
input filters are blocking queries you want to inject, you may be able
to use dynamic execution to circumvent the filters.
Dynamic query execution works differently on different databases. On Microsoft SQL Server, you can use the EXEC function to execute a query in string form. For example:
EXEC('SELECT password FROM tblUsers')
In Oracle, you can use the EXECUTE IMMEDIATE command to execute a query in string form. For example:
DECLARE pw VARCHAR2(1000);
BEGIN
EXECUTE IMMEDIATE 'SELECT password FROM tblUsers' INTO pw;
DBMS_OUTPUT.PUT_LINE(pw);
END;
Databases
provide various means of manipulating strings, and the key to using
dynamic execution to defeat input filters is to use the string
manipulation functions to convert input that is allowed by the filters
into a string which contains your desired query.
In the simplest case, you
can use string concatenation to construct a string from smaller parts.
Different databases use different syntax for string concatenation. For
example, if the SQL keyword SELECT is blocked, you can construct it as follows:
Oracle: 'SEL'||'ECT'
MS-SQL: 'SEL'+'ECT'
MySQL: 'SEL' 'ECT'
Note that SQL Server
uses a + character for concatenation, whereas MySQL uses a space. If you
are submitting these characters in an HTTP request, you will need to
URL-encode them as %2b and %20, respectively.
Going further, you can construct individual characters using the CHAR function (CHR in Oracle) using their ASCII character code. For example, to construct the SELECT keyword on SQL Server, you can use:
CHAR(83)+CHAR(69)+CHAR(76)+CHAR(69)+CHAR(67)+CHAR(84)
Note that you can
construct strings in this way without using any quotation mark
characters. If you have an SQL injection entry point where quotation
marks are blocked, you can use the CHAR function to place strings (such as 'admin') into your exploits.
Other string manipulation functions may be useful as well. For example, Oracle includes the functions REVERSE, TRANSLATE, REPLACE, and SUBSTR.
Another way to
construct strings for dynamic execution on the SQL Server platform is to
instantiate a string from a single hexadecimal number which represents
the string's ASCII character codes. For example, the string
SELECT password FROM tblUsers
can be constructed and dynamically executed as follows:
DECLARE @query VARCHAR(100)
SELECT @query = 0x53454c4543542070617373776f72642046524f4d2074626c5573657273
EXEC(@query)
The mass SQL
injection attacks against Web applications that started in early 2008
employed this technique to reduce the chance of their exploit code being
blocked by input filters in the applications being attacked.
Using Null Bytes
Often, the input filters
which you need to bypass in order to exploit an SQL injection
vulnerability are implemented outside the application's own code, in
intrusion detection systems (IDSs) or WAFs. For performance reasons,
these components are typically written in native code
languages, such as C++. In this situation, you can often use null byte
attacks to circumvent input filters and smuggle your exploits into the
back-end application.
Null byte attacks work due
to the different ways that null bytes are handled in native and managed
code. In native code, the length of a string is determined by the
position of the first null byte from the start of the string—the null
byte effectively terminates the string. In managed code, on the other
hand, string objects comprise a character array (which may contain null
bytes) and a separate record of the string's length.
This difference means that
when the native filter processes your input, it may stop processing the
input when it encounters a null byte, because this denotes the end of
the string as far as the filter is concerned. If the input prior to the
null byte is benign, the filter will not block the input. However, when
the same input is processed by the application, in a managed code
context, the full input following the null byte will be processed,
allowing your exploit to be executed.
To perform a null byte
attack, you simply need to supply a URL-encoded null byte (%00) prior to
any characters that the filter is blocking. In the original example,
you may be able to circumvent native input filters using an attack
string such as the following:
%00' UNION SELECT password FROM tblUsers WHERE username='admin'--
Nesting Stripped Expressions
Some sanitizing
filters strip certain characters or expressions from user input, and
then process the remaining data in the usual way. If an expression that
is being stripped contains two or more characters, and the filter is not
applied recursively, you can normally defeat the filter by nesting the
banned expression inside itself.
For example, if the SQL keyword SELECT is being stripped from your input, you can use the following input to defeat the filter: