No Output, No Problem – Blind SQLi from Red Team Perspective

This blog post provides a comprehensive guide to understanding and exploiting Blind SQL Injection vulnerabilities, tailored for beginners. It combines theoretical knowledge with practical, step-by-step techniques. We will cover both boolean-based and time-based methods, and demonstrate how to manually dump an entire database.

Introduction: The Silent Data Thief

In the world of web application security, SQL Injection (SQLi) has been a notorious vulnerability for decades. While many developers have learned to protect against classic injections where data is displayed directly, a more subtle and equally dangerous variant often slips through the cracks: Blind SQL Injection.

Unlike its “in-band” counterpart where an attacker can see the result of their malicious query in the webpage, a Blind SQL Injection is silent. The application does not return database errors or query results. However, “blind” does not mean “impossible.” It just means the attacker has to ask the database questions in a different way – true or false questions – and deduce the answers from the application’s behavior. This blog will guide you through this process, turning a seemingly mute application into a chatterbox that spills all its secrets .

What is Blind SQL Injection?

Blind SQL Injection occurs 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. This makes direct data retrieval impossible. However, an attacker can still exploit the vulnerability by observing indirect changes in the application’s behavior or response time .

There are two primary types of Blind SQL injection that we will focus on:

  1. Boolean-based Blind SQLi: The attacker sends SQL queries that force the application to return a different response (e.g., content missing, page loads normally) depending on whether the injected condition evaluates to true or false .
  2. Time-based Blind SQLi: The attacker sends SQL queries that force the database to wait for a specified period before responding if the condition is true. By measuring the response time, the attacker can determine if the condition was true or false .

The Theory: Asking the Database True/False Questions

The core concept behind exploitation is simple: we cannot retrieve data directly, so we will extract it one character at a time by asking a series of yes/no questions.

Imagine you are trying to guess a friend’s password. You can’t see it, but you have a magic box that tells you if your guess is correct. A blind injection works similarly.

  • The Question: Is the first character of the password ‘a’?
  • The Injection: We craft a SQL query that includes a condition. If the condition is true, the query runs normally. If false, it does nothing.

For example, consider a vulnerable website that uses a TrackingId cookie. The application might use a query like:

If we inject a condition, the query could become:

  • If the page loads normally, it means the condition was TRUE, so the administrator’s password starts with ‘a’.
  • If the page shows an error or missing content, the condition was FALSE, and we try the next letter, ‘b’ .

We repeat this process for the second character, third character, and so on, until the entire password is reconstructed.

Practical Exploitation: Step-by-Step Guide

Let’s walk through a practical scenario . We will target a vulnerable application that uses a TrackingId cookie for analytics. The application has a boolean-based blind SQL injection vulnerability.

Step 1: Confirming the Vulnerability

The first step is to prove that the parameter is vulnerable. We need to send two payloads and observe the difference in responses.

  1. Baseline Request: Send a request with a normal cookie.

    GET / HTTP/1.1
    Host: vulnerable-website.com
    Cookie: TrackingId=xyz123


    Response: The page loads with a “Welcome back” message.
  2. Test with a True Condition: Inject a condition that is always true. We will use a payload that concatenates a string with itself.

    GET / HTTP/1.1
    Host: vulnerable-website.com
    Cookie: TrackingId=xyz123' AND '1'='1


    Response: The page still loads with the “Welcome back” message. The database sees '1'='1' as true, so the query is valid.
  3. Test with a False Condition: Inject a condition that is always false.

    GET / HTTP/1.1
    Host: vulnerable-website.com
    Cookie: TrackingId=xyz123' AND '1'='2


    Response: The page loads, but the “Welcome back” message is missing. The database sees '1'='2' as false, so the query returns no data for that condition, altering the page content.

This difference in page content (presence vs. absence of a message) is our “boolean oracle.” We have confirmed a boolean-based blind SQL injection .

Step 2: Determining the Length of Data

Before we can extract data, we need to know how much data to extract. Let’s find the length of the administrator’s password.

We will use the LENGTH() function. The logic in our injected condition will be:

LENGTH(password) > 1 ? LENGTH(password) > 2 ? … until we get a false response.

We can automate this with a simple Python script. The goal is to find the number where the condition LENGTH(password) = [number] returns true.

Step 3: Extracting Data Character by Character

Now that we know the password length, we can extract it. We will use the SUBSTRING() function to isolate one character at a time and the ASCII() function to compare it to a numeric value. This allows us to test for characters without using quotes, which are often filtered.

The payload logic becomes:

ASCII(SUBSTRING((SELECT Password FROM Users WHERE Username='Administrator'), [position], 1)) = [ascii code]

We will modify our script to loop through each position (1 to length) and, for each position, loop through possible ASCII values (e.g., 48-122 for alphanumeric and special characters). If the condition is true, we see the “Welcome back” message and record the character .

This script will systematically ask the database, “Is the first character ‘a’? Is it ‘b’? Is it ‘c’?…” until it finds a match, then moves to the next character .

Advanced Techniques: Dumping All Databases and Contents

Extracting a single password is the first step. The real power is in dumping the entire database structure and contents. This involves following a systematic enumeration path. This process is slow, but effective, and can be fully automated.

The Enumeration Process

To dump the whole database, we need to query the information_schema database (in MySQL, PostgreSQL, MSSQL) which contains metadata about all other databases, tables, and columns. Our scripts will follow this logic :

  1. Get the Number of Databases: Use a query like: SELECT COUNT(*) FROM information_schema.schemata.
  2. Get the Length of Each Database Name: For the first database, get its name length.
  3. Extract Each Database Name Character by Character: SELECT SUBSTRING(schema_name, 1, 1) FROM information_schema.schemata LIMIT 0,1.
  4. For the Current Database, Get the Number of Tables: SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='database_name'.
  5. Get the Length of Each Table Name.
  6. Extract Each Table Name.
  7. For the Current Table, Get the Number of Columns: SELECT COUNT(*) FROM information_schema.columns WHERE table_name='table_name'.
  8. Get the Length and Names of Each Column.
  9. Extract the Data: Finally, for a given table and column, extract the actual data, row by row, character by character.
    • SELECT SUBSTRING(column_name, 1, 1) FROM table_name LIMIT 0,1.

This layered approach allows an attacker to map out the entire database schema and then steal all the data within it .

When ‘Wait’ is the Answer: Time-Based Blind SQLi

Sometimes, there is no visible difference in the page content—no “Welcome back” message, no missing text. In this case, we use time-based attacks.

We use SQL functions that pause execution, like SLEEP(5) in MySQL or pg_sleep(5) in PostgreSQL. We combine this with our conditional logic. If our condition is true, the database sleeps for 5 seconds, and our HTTP request takes 5 seconds longer. If false, it responds immediately .

Example Payload (MySQL):

xyz123' AND IF(SUBSTRING((SELECT Password FROM Users WHERE Username='Administrator'), 1, 1) = 'a', SLEEP(5), 0)--

  • If the first character is ‘a’, the response will be delayed by 5 seconds.
  • If it’s not ‘a’, the response is immediate.

We can adapt our Python script to measure response time instead of looking for a string in the content. This requires careful error handling to account for network latency, but the core logic remains the same .

Automation: From Manual to Scripted Exploits

As you’ve seen, manual exploitation is tedious. The examples above form the basis of powerful custom scripts. While tools like sqlmap are incredibly effective for this purpose , understanding the underlying logic is crucial, especially in environments like the OSCP exam where such tools are prohibited .

The scripts provided in this blog are conceptual starting points. A full-featured exploit would need to handle:

  • Session management (cookies, CSRF tokens) .
  • URL encoding of payloads.
  • Multi-threading to speed up the process.
  • Error handling and retries for time-based attacks.

How to Protect Your Applications

Understanding the attack is the first step to building a strong defense. Here are the golden rules to prevent SQL injection :

  • Use Parameterized Queries (Prepared Statements): This is the most effective defense. It ensures that user input is treated as data, not executable code. Separate the SQL logic from the user-supplied data.
  • Validate and Sanitize Input: Use allow-lists to only accept expected characters (e.g., only digits for an id parameter).
  • Apply the Principle of Least Privilege: The database account used by the web application should have the minimum permissions necessary. It should not be an admin or DBA account. This limits the damage from a successful injection.
  • Use Stored Procedures: While not a complete solution on their own, when used correctly, they can add a layer of abstraction and security.
  • Regular Security Testing: Use both automated scanners and manual penetration testing to find and fix vulnerabilities before attackers do.

Conclusion

Blind SQL Injection is a testament to the ingenuity of security testing. It shows that even when an application is not verbose with its errors, it can still be manipulated into revealing its deepest secrets through a series of cleverly crafted true/false questions. By understanding the underlying logic of boolean-based and time-based attacks, and by learning how to automate the extraction process, you have added a powerful and essential skill to your cybersecurity toolkit. Remember, with great power comes great responsibility – always ensure you have explicit permission to test the security of any application.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top