Exploiting Blind SQL Injection with Conditional Responses Without sqlmap
When studying for the OSCP, you’ll learn that tools like sqlmap are prohibited during the exam.
In this post, I’ll demonstrate how I exploited the Soccer machine on Hack The Box (HTB) using Blind SQL Injection with conditional responses.
To effectively exploit this type of vulnerability, you need to break the process into smaller tasks to make it more manageable.
Understanding Conditional Responses
In the case of Conditional Responses, the behavior of the page depends on whether the SQL query executes successfully. If your payload doesn’t break the query, the page behaves as normal; otherwise, you’ll notice a difference in the response.
For example, sending a payload like OR 1=1--
makes the SQL query evaluate to true
. If you’re attempting to log in to an admin account, the query might look like this:
SELECT * FROM users WHERE username='admin' AND password='password';
As an attacker, you don’t know the admin’s password. By typing this payload in the username field:
admin' OR 1=1--
…you modify the query to:
SELECT * FROM users WHERE username='admin' OR 1=1-- AND password='';
This payload comments out the rest of the query, causing it to return everything related to the admin account.
That was just a quick recap of the concept.
Exploiting the Vulnerability
In my case, there was an id
parameter vulnerable to SQL injection. By sending a non-existent ID like 0
combined with OR 1=1--
, the server responded with "Ticket Exists," even though the ticket didn’t exist.
Now, to fully exploit the database, we need to systematically enumerate its contents:
Step 1: Get the Length of the Database Name
First, determine the length of the database name. For example, if the database name is mux0x
, its length is 5.
The MySQL payload for checking the length is:
(SELECT LENGTH(database())) = <number>
Write a script in your preferred language to automate this process. Since this is a conditional response SQL injection, check for the response “Ticket Exists” to determine if the guessed length is correct.
Step 2: Enumerate the Database Name
Once you know the database length, enumerate its name character by character. The payload for this is:
(SELECT ascii(substring(database(), <index>, 1))) = ascii('<character>')
Here’s an example of running this query in a MySQL server:
mysql> SELECT (SELECT ascii(substring(database(), 1, 1))) = ascii('m');
+----------------------------------------------------------+
| (SELECT ascii(substring(database(), 1, 1))) = ascii('m') |
+----------------------------------------------------------+
| 1 |
+----------------------------------------------------------+
1 row in set (0.00 sec)
The result 1
indicates that the first character is m
.
Repeat this process for all characters in the database name based on its length (determined in Step 1).
Step 3: Enumerate the Number of Tables
After identifying the database name, determine the number of tables within the database.
Step 4: Enumerate Table Names
For each table, determine its name length and then extract the full name character by character.
Step 5: Enumerate Column Information
For each table, enumerate:
- The number of columns.
- The length of each column name.
- The column names.
Step 6: Extract Data
Finally, extract the data from each column. You can start by retrieving the first value of each column or target specific information based on your objectives.
Final Thoughts
This method demonstrates how to simplify Blind SQL Injection. Initially, it might seem daunting, but breaking it into manageable steps makes the process much easier.
This post only covered one type of Blind SQL Injection. There are more techniques I’ll explain in future posts, insha’Allah.