Hello folks,
In this blog, we will understand one of the most identifiable and difficult types of SQL Injection vulnerability. It is Blind SQL Injection. We will learn about the same using PortSwigger platform. Let’s begin the blog and understand the meaning of blind SQL injection vulnerability.
Blind SQL injection vulnerabilities are those where we send a malicious SQL query to the server but we don’t receive any direct output in the response. In simple terms, even if the application is vulnerable to SQL injection and will execute our malicious SQL query but it will not provide any data within the response. But using various factors like conditional response, errors, or response time, we can still enumerate and fetch data from the SQL database.
In this blog, we will be covering how we can retrieve data from a database using conditional responses, conditional errors, and database errors.
Lab-1 Blind SQL injection with conditional responses
Conditional response means that the reply we get depends on the SQL query we use. If the query gives a true result, we might get a different response compared to when it gives a false result. We’ll look for these responses by using logical operators like AND in our SQL queries.
We can read the description of this lab and then click on the “Access the lab” button. This lab requires Burp Suite Professional for faster results.
To exploit SQL injection vulnerability, we require a parameter whose value interacts with an SQL query. In the lab description, it is mentioned that the TrackingID cookie parameter is vulnerable to SQL injection. So, we will target this parameter for which we need to refresh the home page. Now let’s switch to Burp Suite and under the HTTP history tab, we have to identify the request towards the “/” endpoint which contains the Cookie header. We need to take this request to Repeater.
On Repeater, we will add the following conditional statement to confirm whether the parameter is vulnerable to SQL injection or not:
‘ AND ‘a’=’a
Here “‘” is used to close the previous value of the cookie. AND is a logical operator that results true value when all the provided input values are true. “‘a’=’a” is used as a value which is always true.
After sending the request to the web server, we will find a “Welcome back” message in the response.
But if we try the following conditional statement, we will not receive a “Welcome back” message:
‘ AND ‘a’=’b
Here, “‘a’=’b” is used as a value which is always false.
This confirms that the application is vulnerable to blind SQL injection vulnerability using conditional responses.
Now to exploit this vulnerability, we can get the user credentials using the information provided in the lab’s description. Before targeting the password of the administrator user, we need to identify the length of the same. We can use the following payload to get the length of the administrator’s password:
‘ AND (SELECT length(password) FROM users WHERE username=’administrator’)> ‘1
When we send the above request, we will find a “Welcome back” message in the response because the length of the password is greater than 1 character.
Now let’s confirm the false condition by using the following payload:
‘ AND (SELECT length(password) FROM users WHERE username=’administrator’)> ‘10000
This time we will find that we didn’t receive any “Welcome back” message which confirms that the length of the password is not greater than 10000 hence, the condition is false.
Now to get the exact length of the password, we need to send this request to the Intruder, and under the Positions tab, we have to select the number (10000) and also, replace the “>” symbol with “=”.
Now we have to click on the Payloads tab. Select “Numbers” in Payload type and mention numbers as follows:
From: 1
To: 50
Step: 1
Finally, we have to click on the Options tab, and under the “Grep – Match” section, click on Clear to remove all the present expressions. Now add a “Welcome back” message. Now click on the “Start Attack” button.
Let’s wait for a few seconds and after that, we can sort the results by clicking on the “Welcome back” column. We will find a single request with the “Welcome back” mentioned in the response. So we can confirm that the length of the password is 20.
After getting the length of the password, we need to find the exact password for which we can use the following payload:
‘ AND (SELECT substring(password,1,1) FROM users WHERE username=’administrator’)> ‘m
Here we used the substring() function which helps to work with sub-strings. Always remember that we will be targeting each character of the password. Substring functions require 3 input values; first is the name of the column that we are targeting or any string on which this function will work, second is a numeric value that specifies the place of character and third is also a numeric value that specifies how many characters we have to consider at a time.
If the first character of the password is greater than m then we will find the “Welcome back” message otherwise not. Also, we can use the following statement to check the vice versa:
‘ AND (SELECT substring(password,1,1) FROM users WHERE username=’administrator’)< ‘m
Now, after confirming we need to send the request to Intruder where we can brute-force each character to get the password. On Intruder under the Positions tab, we need to select the second input value of the substring() function as well as the “m” character. Also, we need to change the “<” or “>” symbol to “=”. Change the attack type to “Cluster Bomb”.
Now go to the Payloads tab and for the first position, we require “Numbers” as the payload type where we will mention numbers as follows:
From: 1
To: 20
Step: 1
For the second payload, we require “Bruteforcer” as payload type where the number of minimum and maximum characters should be 1. Finally, we have to click on the Options tab, and under the “Grep – Match” section, click on Clear to remove all the present expressions. Now add a “Welcome back” message. Now click on the “Start Attack” button.
Let’s wait for a few seconds and after that, we can sort the results by clicking on the “Welcome back” column. We will find each character of the administrator’s password which we can sort by selecting all the results where we have a “Welcome back” message in the response and highlighting them by right-clicking on the request and choosing a unique color. Then we need to click on the filter and select “Show only highlighted items”. We will find that now we only have each character of the password.
Now we can write the password and try to log in as administrator user by visiting the “/login” page. We will find that the lab is solved.
Lab-2 Blind SQL injection with conditional errors
Some applications don’t show any conditional response, so in such situations, we have to identify conditional errors which means that the reply we receive can contain errors depending on the condition provided by us. The error will confirm that the condition is true or false.
We can read the description of this lab and then click on the “Access the lab” button. This lab requires Burp Suite Professional for faster results.
To exploit SQL injection vulnerability, we require a parameter whose value interacts with an SQL query. In the lab description, it is mentioned that the TrackingID cookie parameter is vulnerable to SQL injection. So, we will target this parameter for which we need to refresh the home page. Now let’s switch to Burp Suite and under the HTTP history tab, we have to identify the request towards the “/” endpoint which contains the Cookie header. We need to take this request to Repeater.
On Repeater, we will provide a single quote (‘) just after the TrackingID cookie value which will force the application to generate an error. To resolve this error we can add another single quote (‘) character. This confirms that the cookie parameter is vulnerable to conditional error-based blind SQL injection.
Now we need to use string concatenation characters to add two or more strings for which we can refer to the SQL Injection cheat sheet provided by PortSwigger. Let’s try with “||” characters which works in the case of Oracle and PostgreSQL as follows:
‘||’
We will find a 200 status code which confirms that there is no error message. Now we have to provide a SQL statement through which we can get the length of the administrator’s password. We can use the following query for the same.
‘||(SELECT CASE WHEN (length(password)>1) THEN 1/0 ELSE null END FROM users WHERE username=’administrator’)||’
Here we used a CASE statement where we provided a condition (length(password)>1). If this condition is true then the “THEN” statement will execute otherwise “ELSE” statement will be executed. In the “THEN” statement, we have provided “1/0” which is a infinite value and will generate an error. In the “ELSE” statement, we have provided “null” which will do nothing when executed.
In this case, we will get an error value because the length of the administrator’s password should be greater than 1. We can also check the reverse condition by increasing the length to 10000 using the following query:
‘||(SELECT CASE WHEN (length(password)>10000) THEN 1/0 ELSE null END FROM users WHERE username=’administrator’)||’
This time we will get a 200 status code response because the provided condition is false.
Now to get the exact length of the password, we need to send this request to the Intruder, and under the Positions tab, we have to select the number (10000) and also, replace the “>” symbol with “=”. Click on the Payloads tab and select “Numbers” in the Payload type and mention numbers as follows:
From: 1
To: 50
Step: 1
Let’s click on the “Start Attack” button and wait for a few seconds after which we can sort the results by clicking on the “Status” column. We will find a single request where we have a 500 status code. So we can confirm that the length of the password is 20.
After getting the length of the password, we need to find the exact password for which we can use the following payload:
‘||(SELECT CASE WHEN (substr(password,1,1)> ‘m’) THEN 1/0 ELSE null END FROM users WHERE username=’administrator’)||’
We used substr() function because when we tried with the substring() function we didn’t get anything because this is an Oracle database. We can refer to the SQL Injection cheat sheet for the same.
If the first character of the password is greater than m then we will find the 500 status code or error message otherwise not. Also, we can use the following statement to check the vice versa:
‘||(SELECT CASE WHEN (substr(password,1,1)< ‘m’) THEN 1/0 ELSE null END FROM users WHERE username=’administrator’)||’
Now, after confirming we need to send the request to Intruder where we can brute-force each character to get the password. On Intruder under the Positions tab, we need to select the second input value of substr() function as well as the ‘m’ character. Also, we need to change the “<” or “>” symbol to “=” as well as change the attack type to “Cluster Bomb”.
Now go to the Payloads tab and for the first position, we require “Numbers” as the payload type where we will mention numbers as follows:
From: 1
To: 20
Step: 1
For the second payload, we require “Bruteforcer” as payload type where the number of minimum and maximum characters should be 1. Now click on the “Start Attack” button.
Let’s wait for a few seconds and after that, we can sort the results by clicking on the “Status” column. We will find each character of the administrator’s password which we can sort by selecting all the results where we have 500 status code messages in the response and highlighting them by right-clicking on the request and choosing a unique color. Then we need to click on the filter and select “Show only highlighted items”. We will find that now we only have each character of the password.
Now we can write the password and try to log in as administrator user by visiting the “/login” page. We will find that the lab is solved.
Lab-3 Visible error-based SQL injection
Some vulnerable web applications show the data via verbose error messages. This error can provide the actual data that the attacker wants to access from the database. In this scenario, we will try to use the CAST() function which converts a data type to another data type.
We can read the description of this lab and then click on the “Access the lab” button. This lab can be performed using Burp Suite Community Edition.
To exploit SQL injection vulnerability, we require a parameter whose value interacts with an SQL query. In the lab description, it is mentioned that the TrackingID cookie parameter is vulnerable to SQL injection. So, we will target this parameter for which we need to refresh the home page. Now let’s switch to Burp Suite and under the HTTP history tab, we have to identify the request towards the “/” endpoint which contains the Cookie header. We need to take this request to Repeater.
On Repeater, we will provide a single quote (‘) just after the TrackingID cookie value which will force the application to generate an error. To resolve this error we can add another single quote (‘) character. This confirms that the cookie parameter is vulnerable to conditional error-based blind SQL injection.
Now we need to use string concatenation characters to add two or more strings for which we can refer to the SQL Injection cheat sheet. Let’s try with “||” characters which works in the case of Oracle and PostgreSQL as follows:
‘||’
We will find a 200 status code which confirms that there is no error message. Now we have to create a malicious SQL statement so that we can password of administrator user using verbose error messages. Let’s use the following payload:
‘||(CAST((SELECT password FROM users WHERE username=’administrator’) AS INT))||’
Here we are using the CAST() function which changes the data type of any input to another. In this case, we know that the data type of the password is varchar and if we try to convert it to integer using CAST(), it will generate an error for us which will contain the string whose data type it was trying to convert.
After running the above statement, we will find an error. If we read out the error then we will find the statement is stripped out because of the character limit applied at the server side.
So we can remove the cookie value and make some modifications in the query as follows:
‘||(CAST((SELECT ‘CyberiumX’) AS INT))||’
This time we will find the same string (CyberiumX) in the error message.
Now we have to provide a statement that is short in length. We can use the following query to get the first username available in the database table:
‘||(CAST((SELECT username FROM users LIMIT 1 ) AS INT))||’
Here we user LIMIT keyword which means that it will restrict the results to only first entry. This will give us the administrator username in the error message. Now we know that if we do the same thing we can get the password of the administrator user using the following statement:
‘||(CAST((SELECT password FROM users LIMIT 1 ) AS INT))||’
Finally, we will find the password and try to log in as administrator user by visiting the “/login” page. We will find that the lab is solved.
In this blog, we covered some basic concepts of Blind SQL Injection vulnerability to retrieve data from the database using conditional response, conditions errors, and verbose error messages. In the upcoming blogs, we will cover some other ways to exploit Blind SQL Injection vulnerability.
You can check out our other web application penetration testing blogs on our website.
Happy Pentesting!
Team CyberiumX