Injection
Log in Join

Lesson 4 · Reading · 35 min

Blind SQL injection

Often the application runs your injected query but never shows its results, no error, no data on the page, just a query happening quietly in the background. You cannot UNION data onto a page that prints nothing. So you extract it a different way: by asking the database yes/no questions and reading the answer in how the page behaves. This is blind SQL injection.

Blind SQLi: no data returns, so you ask true/false questions and read the tell

Why "blind"

The injection is real, your input reaches the query and changes its logic, but the output is invisible. Maybe the page just says "search complete", or the query feeds a decision you cannot see (a login that only says "yes" or "no", a filter that changes whether any results show). You are working in the dark, so instead of asking the database to hand you data, you ask it a question whose answer is true or false, and you find a tell: something observable that differs between true and false. Then you spell out the secret one bit at a time.

Boolean-based: read the content

The first kind of tell is the page content. You inject a condition and compare:

?id=42 AND 1=1--     →  page looks NORMAL   (condition true)
?id=42 AND 1=2--     →  page looks DIFFERENT (condition false)

If "true" gives the normal page and "false" gives a changed one (fewer results, a "not found", a different length), you have a boolean oracle: the page tells you whether any condition you write is true. Now replace 1=1 with a question about the data:

?id=42 AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--

If the page comes back "normal", the first character of admin's password is a. If "different", it is not, try b, c, and so on. Character by character, position by position, you reconstruct the whole value. It is slow by hand and instant with automation, but the principle is just: turn each unknown into a true/false question.

Time-based: read the clock

Sometimes the page looks identical whether your condition is true or false. Then you make the database itself create an observable difference: a delay. Most engines have a sleep function, and you tell the query to pause only when your condition is true:

?id=42 AND IF( (SUBSTRING(password,1,1)='a'), SLEEP(5), 0)--

Now the tell is time: if the response takes five seconds, the condition was true; if it returns instantly, false. This works even when nothing about the page's content ever changes, which is why time-based blind injection is the fallback that almost always works. (Syntax varies: MySQL SLEEP(), PostgreSQL pg_sleep(), SQL Server WAITFOR DELAY.)

This is exactly what automation is for

Extracting a 60-character hash at one HTTP request per character-guess is thousands of requests. Doing it by hand teaches you the mechanism; doing it for real means sqlmap, the standard tool. You point it at the injectable parameter and it detects the injection, works out the engine, chooses boolean or time-based extraction, and dumps the data for you:

sqlmap -u 'https://target/item?id=42' -p id --dbs
sqlmap -u 'https://target/item?id=42' -p id -D shop -T users --dump

Understand the manual technique first so you can confirm sqlmap's findings, tune it when it stalls, and explain in a report exactly what it did. A tool you cannot explain is a tool you cannot defend in a triage conversation.

Filter and WAF bypass

Blind injection often shows up on endpoints protected by input filters or a web application firewall that blocks obvious payloads. When SLEEP or UNION is filtered, testers reach for evasions: alternate keywords, comments inside keywords (SEL/**/ECT), case changes, encoding, or logically equivalent constructs. This is a craft of its own; know that a blocked payload is not a safe endpoint, only a filtered one, and that filters are routinely bypassed. When a straightforward probe is rejected, the question becomes "how is the filter deciding, and what does it miss?"

The honesty gate

Blind extraction is still extraction: prove the vulnerability, not the whole database. On a real target, demonstrate with a single confirmed fact, the database version, or that one specific true/false question resolves correctly, which proves you can read arbitrary data, and stop. Do not run sqlmap's full --dump against real users' data on a live system; the boolean oracle, shown once, is the proof. On this lab, extract freely.

Your labs

CraftBrew Loyalty sort-order blind injection hides the injection in a sort parameter and gives you no data on the page, a textbook blind case where you read the tell rather than the output. Aegis Claims legacy API filter bypass adds the other half of real-world blind work: a filter stands between you and the query, and you have to get a working payload past it. Together they cover extracting data when the page shows nothing and when something is actively trying to stop you.

Where this goes next

That completes SQL injection: finding it, UNION extraction, and blind extraction past filters. The next three lessons switch interpreters, from the database to the browser, with cross-site scripting, where your input becomes a script that runs in someone else's session. We start with the reflected variety.

This lesson has 3 labs to try what you just read.