Finding SQL Injection
Author: HollyGraceful Published: 19 October 2020
SQL Injection is an old vulnerability; first published on Christmas Day 1998 in Phrack Magazine 54. The issue occurs where user supplied input is insecurely concatenated into an SQL query. It generally allows an attacker to perform any of the operations that the database user can execute – such as extracting, changing, or deleting database contents. Rarely, where the database user is highly privileged, this can allow for command execution through features such as the MSSQL xp_cmdshell system stored procedure.
Exploiting the issue manually is often trivial, but there are freely available public exploitation tools available – such as SQLmap.
How to Detect SQL Injection
SQL Injection can be found simply through code review, where a query is built through concatenation and that concatenation includes data that originates as user input. However, it can also be found through dynamic analysis. SQL Injection isn’t restricted to one input type, such as a GET request parameter, it could just as easily occur through a POST request, or from a user modifiable configuration. This issue is per-parameter, so each parameter must be tested in turn to ensure no vulnerabilities exist.
Where raw database error messages are shown by the target application, then SQL injection can be simple to find by simply supplying input likely to cause an error. Most commonly this can be quotation marks such as:
' " `
Generally these characters will cause an “unbalanced” number of quote marks, which will throw an error (these errors differ depending on the back-end database in use), such as:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1
Where raw database error messages are not returned, either due to being replaced by generic error messages or no error at all, detection and exploitation is still possible. A simple way is through Boolean queries which are intended to cause a visible change in the application response.
For example a query which causes a list of products to be displays could be modified through a Boolean query to return no products, thereby showing injection is possible. This is often possible with queries such as:
' AND 1=1 ' AND 1=2 or ' AND @@version=@@version ' AND @@version='foobar'
The two examples above are designed such that if the application returns output such as: “showing 117 products” for the first input and “showing 0 products” for the second input, this is an indication of injection.
The preceding quote mark should match the type used by the developer; if this is not known then attempting each type and checking the output differences would allow this to be determined. If the input is an integer, then a preceding quote mark will not be required. If the injection point is within a sub query then closing brackets may be required.
An alternative check is to use arithmetic evaluation, this is useful to find inputs that are vulnerable but protected by Web application Firewalls – which commonly block keywords such as “AND” or “OR” by default.
The intention is to supply an input, and then the equivalent input as an arithmetic equation – if the output is the same then it is likely vulnerable to SQL injection.
In the following example 1 is a valid input, but 2 is not a valid input – however when we supply 2-1 we are given output, due to the fact that SQL processes the 2-1 and treats it as equivalent to entering 1.
It’s also possible to find SQL injection vulnerabilities through causing database delays. The syntax differs depending on the database type, such as:
MySQL: sleep(5) MSSQL: WAITFOR DELAY '0:0:5' PostgreSQL: pg_sleep(5)
When the sleep(5) payload is supplied; the server response is delayed by at least five seconds, as shown by the “Waiting for” message displayed.
SQL Injection Exploitation
There are several methods for exploiting SQL Injection vulnerabilities depending on the context of the injection point, any potential filters and Web Application Firewalls (WAF) in place.