SQL Injection Detection
Detect potential SQL injection vulnerabilities
The first step towards achieving a successful SQL injection attack is to detect vulnerabilities. Of course, some tools can automate the process, but it’s better to understand how detection can be done manually. In addition, there are some situations where only manual testing will allow in-depth analysis.
Interfering with Query
The only way to know if an input source is potentially vulnerable is to trigger anomalies in the tested webpage or application. In order to do this, the attacker must submit input values that are likely to be incorrectly handled. This technique (named fuzzing) will not yet confirm that an SQL injection flaw is present, but it will help finding what needs further testing.
Testing Strings
To create anomalies in the tested script you need to submit input values prone to generate an invalid SQL syntax. Some key testing strings will allow you to achieve this. Those include special characters that should have been filtered by the application. Here are a few examples from the SQL injection testing strings article.
Test strings to detect SQL injection (1 per line).
xyz'
xyz')
1 OR
1)
Detection Example
Before jumping in the core of the subject let’s take a look at a simple example.
The query is built without sanitizing parameters.
$query = "SELECT title, content FROM posts WHERE page='".$_GET['page']."'";
Test string submitted by the attacker (value of page parameter).
xyz')
Query generated. Notice that the injected quote closes the string (color can be confusing here)!
SELECT title, content FROM posts WHERE page='xyz')'
As expected, the page returned an error.
Error returned after injection attempt.
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')'' at line 1.
In this example it is pretty obvious that there is a security flaw. However, in some cases it is much more difficult to tell. When generic errors or HTTP errors are returned, it becomes hard to know if the suspicious data was intercepted by server-side validation or if the code handled an error generated by the query. For this reason, it is necessary to push tests a bit further.
Confirm Detection
Inference testing is a good technique to confirm that a potential flaw is really vulnerable. Simply put, testing SQL injection by inference will allow the attacker to reconstruct information by analysing the application’s response to different requests. In this case, the tester will craft special SQL segments to make sure he really has control over the query.
Two different tests will be required. The first one will submit input containing a valid parameter followed by a true condition. The second will contain the same parameter followed by a false condition. If the script is vulnerable, the result page of both tests should be different. Moreover, the application's response will habitually be exactly the same with or without the true condition. Let’s recap this technique with the following example.
True Condition Injection
Within a few tries, the attacker finds a way to add a condition without generating an invalid query. The injected parameter and the resulting query are shown below.
Parameter submitted by the attacker (dogs parameter returns a valid page).
dogs' AND 'a'='a
Query generated. Warning : Color can be confusing!
SELECT title, content FROM posts WHERE page='dogs' AND 'a'='a'
The result (or response) does not differ from when the valid parameter is used without condition.
False Condition Injection
For the second test, the attacker uses the same logic.
Parameter submitted by the attacker (dogs parameter returns a valid page).
dogs' AND 'a'='b
Query generated.
SELECT title, content FROM posts WHERE page='dogs' AND 'a'='b'
This time, the page indicates that no such article exists. The detection is successful!
Common alternative to conditions
A common way to achieve the same result without conditions is using equivalent parameters. For example, instead of using a true condition, one could use string concatenation to recreate the original parameter value "dogs". This example will make it more concrete.
User input (Using string concatenation - MySQL syntax).
do' 'gs
Query generated.
SELECT title, content FROM posts WHERE topic='do' 'gs'
The previous query is equivalent to this one.
SELECT title, content FROM posts WHERE topic='dogs'
As you probably guess, similar principle can be applied to numeric parameters. You will have to be careful when testing those however. For more information take a look at the article about equivalent parameters (available soon).
Query Complexity
The impact of query complexity on the detection process needs a special mention. Examples provided in this article are quite basic and do not present issues a tester might face while trying to detect vulnerabilities in real scenarios. Given a case where the parameter is injected in a sub query or in a complex condition, an SQL injection flaw can become much harder to find. It is still possible but the tester will need a rough idea of the query's structure to achieve an attack.