Blind SQL Injection — Boolean-Based Cookie Injection¶
| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Vulnerability | Blind SQL Injection — Boolean-Based |
| Difficulty | Practitioner |
| Injection Point | TrackingId cookie |
| Goal | Extract the administrator password character by character |
Phase 1 — Reconnaissance¶
We land on a shopping center page. The vulnerability is in the TrackingId cookie, which is processed by a SQL query on every request.
Intercepting traffic with Burp Suite and adding a ' to the cookie causes the Welcome back message to disappear:
Adding a true condition brings it back:
Cookie: TrackingId=Yqq23v96zi21TLnf' or 1=1 -- -;
This confirms boolean-based blind injection — the page responds differently depending on whether the injected condition evaluates to true or false. There is no data returned in the response body; the only signal is the presence or absence of "Welcome back".
Phase 2 — Attack Path¶
Step 1 — Confirm Subquery Execution¶
Before querying the users table, confirming that subqueries inside the condition are evaluated:
TrackingId=Yqq23v96zi21TLnf' and (select 'x') = 'x' -- -;
"Welcome back" appeared — subqueries are being evaluated inside the condition.
Step 2 — Confirm the Target User Exists¶
Querying the users table for the administrator row. If the row exists the subquery returns 'x', the condition is true, and "Welcome back" appears:
TrackingId=Yqq23v96zi21TLnf' and (select 'x' from users where username = 'administrator') = 'x' -- -;
"Welcome back" appeared — administrator exists. Confirming a non-existent user returns no "Welcome back":
TrackingId=Yqq23v96zi21TLnf' and (select 'x' from users where username = 'KasaneTeto') = 'x' -- -;
"Welcome back" absent — the row doesn't exist. The behavioral difference is confirmed and reliable.
Step 3 — Determine Password Length¶
Incrementing the length value until "Welcome back" appears:
TrackingId=Yqq23v96zi21TLnf' and (select 'x' from users where username = 'administrator' and length(password) = 20) = 'x' -- -;
"Welcome back" appeared at length(password) = 20 — the password is 20 characters long.
Step 4 — Extract Password Character by Character¶
With the length known, each character is extracted individually using SUBSTRING(string, position, length). For each position (1 to 20), every character in a-z + 0-9 is tested until "Welcome back" appears:
TrackingId=Yqq23v96zi21TLnf' and (select substring(password,§1§,1) from users where username = 'administrator') = '§x§' -- -;
Using Burp Intruder with a Cluster Bomb attack — two payload sets running all combinations:
- Payload 1 (position): numbers 1 to 20
- Payload 2 (character):
a-zlowercase +0-9
Setting up a Grep Extract rule to match the Welcome back text in the response, which marks the correct character for each position:
Attack results — sorting by position reveals the full password:
2zdd1o9cfwst94ohwvzn
Alternative — Python Automation¶
The same extraction can be automated with a Python script, avoiding the Burp Intruder rate limits and providing real-time progress output via pwntools log bars. The script iterates through every character position (1 to 20) and for each position tries every character in a-z + 0-9. For each combination it sends a GET request with a crafted TrackingId cookie containing the SUBSTRING payload. If the response body contains Welcome back, the character is confirmed, appended to the recovered password, and the script moves to the next position.
Conclusion¶
- Adding
'to theTrackingIdcookie caused "Welcome back" to disappear;or 1=1 -- -restored it — confirming boolean-based blind injection. - Subquery evaluation was confirmed with
and (select 'x') = 'x'; user existence was confirmed with a subquery against theuserstable. length(password) = 20returned "Welcome back" — establishing the password length for the extraction loop.- Cluster Bomb Intruder attack with
SUBSTRINGacross positions 1–20 and charseta-z+0-9recovered each character; the Grep Extract rule on "Welcome back" identified correct characters. Full password:2zdd1o9cfwst94ohwvzn.
Key Concepts¶
Blind SQLi — no output, only behavior — unlike UNION attacks where data appears in the response body, blind SQLi has no visible output. The only signal is a behavioral difference: a message present or absent, a redirect vs. no redirect, or a response time difference. Every piece of information must be inferred from that single bit of feedback.
Boolean-based vs. time-based blind — both are blind, but the signal differs. Boolean-based relies on application behavior (message present/absent); time-based relies on response delay using SLEEP() or WAITFOR DELAY. Boolean-based is preferred when a behavioral difference is reliably observable — it is faster and less dependent on network latency.
SUBSTRING(string, position, length) — the core extraction primitive — extracting one character at a time and comparing it against a known charset is the standard blind extraction loop. For a 20-character password with 36 possible characters, the worst case is 720 requests (20 × 36); Intruder or a script makes this practical.
Cluster Bomb vs. Sniper in Intruder — Sniper cycles one payload set through all marked positions; Cluster Bomb runs all combinations of multiple payload sets simultaneously. For positional brute-force with two independent variables (position and character), Cluster Bomb is the correct mode.
Why automate — manual character-by-character testing is impractical for passwords longer than a few characters. Burp Intruder handles it visually; a Python script is faster, avoids Community Edition rate limiting, and can be adapted to different targets and charsets without reconfiguration.