Introduction
SQL injection attacks have been well known for a long time and many people think that developers should have fixed these issues years ago, but doing web application pentests almost all the time, we have a slightly different view. Many SQL injection problems potentially remain undetecteddue to a lack of proper test methodology, so we would like to share our approach and experience and help others in identifying these issues.
SQL injection vulnerabilities arise when untrusted input is incorporated into a SQL query within the source code and they are not limited to web applications. Every server application that processes SQL queries can be vulnerable to this kind of attack and should be tested. SQL injection vulnerabilities can be grouped into the following types:
1. Error-based SQL injection: When testing for the vulnerability the server responds with a database error message like “syntax error”
2. Blind SQL injection: During the test the server either doesn’t reveal any error message at all or responds with a customized standard error message respectively just a change in the response behaviour like showing another web page. As long as one can notice a different behaviour of the application, we call this “Partially Blind SQL Injection”, in case no changes in the response are detected we talk about “Totally Blind SQL Injection”.
3. Client Side SQL injection:SQL injection vulnerabilities are not limited to server applications. Clients that store sensitive data in a local database can be vulnerable to SQL injection attacks as well, when untrusted input is processed. Also HTML5 implements concepts for client side databases like WebSQL (this specification is deprecated) and “Indexed Database API” to work with local databases within the web browser.
As already mentioned a proper test methodology can help to improve the rate of findings, e.g. Bruce Schneiers Attack Tree Model comes to mind as helpful for summarizing the important steps to discover all SQL injection vulnerabilities within an application. Picture 1 shows a very basic attack tree for uncovering SQL injection.
Detecting SQL Injection
As described above, SQL injection vulnerabilities exist in different types. Each of these types requires different attack strings and detection mechanisms, and usually a high degree of manual testing for an extensive detection.
To detect SQL injections, you have to test with some simple signatures like a single apostrophe ('
), two single apostrophes (''
), arithmetic expressions or database specific procedures.
Error prone vulnerabilities which react with an error message on a single apostrophe are very simple to detect. The best way to verify a successful injection is inserting a single apostrophe which leads to an error message. Afterwards insert two single apostrophes, if the second injection doesn’t return any error messages, it is very likely that a SQL injection vulnerability was found. In Oracle databases you would insert for example “test'
” in a search box and you get an error message returned. After inserting “te'||'st
” you get all search results matching for the string test. If the database expects that an integer is supplied, apostrophes always result in an invalid query, no matter if they would be used with string concatenation or not. In such a case you could use some arithmetic calculations to verify that they were evaluated by the database. If the id 47 and 58-11
results in the same response, it is very possible that they both produced 47 as a result of a calucation by the database.
In Blind SQL injections you could use the same techniques, but you won’t get any error messages telling you what happened on the database. Instead you may have to use boolean expressions to manipulate the results. For example inserting a “' OR ''='
” should lead to a result, whereas “' AND 'x'='
” doesn’t return anything (or only a very short response like no datasets found).
Because Totally Blind SQL injections normally wouldn’t affect the response in any way, you have to detect them by measuring the response time depending on the test signature. On Oracle databases a request with “'||utl_http.request('http://192.168.66.77/')||'
” should take much more time to return as “'||'
“. If the response time is nearly the same, you should try other IP addresses or hostnames. A MySQL database supports a SLEEP command since version 5.0.12. If a you have to wait for a response 20 seconds after you had injected “' UNION SELECT SLEEP(20)--
” you would automatically know that you have found a vulnerability and that the used database is a MySQL database with version 5.0.12 or higher.
Some times you will notice that the application (or some intermediate component) filters for characters like an apostrophe or an equal sign. In such a case you should try different encodings and combinations of encodings to bypass such filtering. If you communicate over HTTP with the server, URL encoded strings can be helpful. Try “%27
” instead of “'
“or several iterations like “%2527
“, “%252527
“, .. (“%25
” is the URL encoded value of the percent sign). Especially on numeric comparisons you could use the lower or greater sign instead of the equal sign. An “OR 4<8
” should also be evaluated to true like the standard signatures “OR 1=1
” (which sometimes is filtered).
Choosing the right tool chain is crucial for detecting and exploiting SQL injections. For example the basic requirement for all injections is the complete control over the input values. A fat client or Ajax application which is communicating with a server may have some validation mechanisms, but the server itself accepts all input strings. In such a case it’s important to send the requests using a proxy or something similar, which allows to send every modified value. One of the more powerful tools is the BurpSuite web proxy from Portswigger. The BurpSuite acts as a proxy between the web browser and the web server, logging all requests and responses. In addition to an automated scanner it includes a repeater and a kind of automated repeater (called intruder). With the repeater you are able to send any inputs without restrictions on the client side. The intruder allows to iterate over multiple attack strings and compare the results.
In general every tool can be used which does not prevent you from sending malicious data. Automated tools like scanners or injection frameworks like sqlmap or sqlninja can help to find so called low hanging fruits, but they will never provide the same results as extensive manual testing.
To be continued …
Have a great day and enjoy trying it for yourself 🙂
Michael, Timo and Frank from the Appsec Team
i’m not good in English, but i really want to comment for thanking you so much. This is a great post.