The Types of SQLi
All SQLi shares the root cause (Chapter 1) and the three moves (Chapter 2), but injections are classified by how the attacker gets the answer back. That channel depends on what the app shows you: query results? errors? nothing at all? The type dictates the technique — so the first thing a tester establishes is which type they're dealing with.
The Three Families
| Type | How data returns | Use when… |
|---|---|---|
| In-band | through the app's own response (results or errors) | the app shows query output or DB errors |
| Blind (inferential) | inferred from app behaviour (true/false, timing) | no output and no errors are shown |
| Out-of-band (OOB) | via a separate channel (DNS/HTTP from the DB) | no in-band feedback, but the DB can make network requests |
In-Band SQLi (the easy case)
The data comes back through the same channel you injected — the app's normal response. Two sub-types:
Error-Based
The app displays database error messages, and the attacker crafts input that makes the DB leak data inside an error (e.g. forcing a type-conversion error that includes a queried value). Verbose errors can reveal table names, column types, query structure, and even extracted values:
Union-Based
The most powerful in-band technique: UNION SELECT appends the results of a second query onto the original, so data from other tables appears right in the app's normal output (a product listing, search results). This is the workhorse of data extraction and gets its own chapter (Chapter 4).
Blind SQLi (no visible output)
When the app shows no query results and no errors, you're flying blind — but the injection still works; you just can't see the answer directly. Instead you ask the database true/false questions and read the answer from the app's behaviour. Two sub-types:
- Boolean-based — inject a condition and watch whether the page changes.
' AND 1=1--(page loads normally) vs' AND 1=2--(page differs / no results). By substituting real conditions (' AND SUBSTRING(password,1,1)='a'--), you extract data one character at a time from the true/false signal. - Time-based — when even the page response is identical for true and false, you make the database pause on "true":
' AND IF(condition, SLEEP(5), 0)--. A 5-second delay means the condition was true. You read data through the response time.
Blind extraction is slow (one bit/character per request) but completely effective — and trivially automated (Chapter 5 + sqlmap in Chapter 10). It's covered in depth next chapter-but-one.
Out-of-Band SQLi (a separate channel)
Sometimes there's no usable in-band output and no reliable behavioural/timing difference. If the database can make outbound network requests, the attacker exfiltrates data through a different channel — typically by making the DB perform a DNS or HTTP lookup to a domain they control, with the stolen data encoded in the request:
OOB is the fallback when in-band and blind are impractical (or to speed up exfiltration), and it depends on database features and network egress being available. It's less common but worth knowing exists.
Why the Type Doesn't Change the Fix
Note the through-line: error-based, union-based, boolean-blind, time-blind, and out-of-band are all the same vulnerability — an injectable query — read through different channels. Defenders sometimes try to close the channel (hide errors, normalize responses), which only forces the attacker to a different type. The fix targets the cause, not the readout: parameterized queries (Chapter 7) prevent the injection from happening at all, so there's nothing to read back through any channel.
Hands-On Exercises
Classify each scenario as in-band, blind, or out-of-band, and name the sub-type: (a) the app prints "SQL error near…" with table names; (b) a search page shows extra rows from another table after a UNION; (c) the page looks identical but takes 5s longer with a SLEEP payload; (d) the DB makes a DNS lookup to your domain. Justify each with "how does the data get back?"
Explain why hiding database error messages is good practice but not a fix for SQLi. Describe exactly what it changes for the attacker (which type they switch to) and why the underlying vulnerability is unchanged.
📄 View solutionExplain how boolean-based and time-based blind SQLi each extract a single character of a password, given no visible output. Then explain why blind SQLi is slower than union-based but equally effective, and why neither channel-closing defence stops the underlying injection.
📄 View solutionChapter 3 Quick Reference
- SQLi is classified by how the answer gets back — ask "can I see the data, and how?"
- In-band — data returns via the app's own response; sub-types: error-based (data leaked in errors) & union-based (appended results)
- Blind — no visible output; infer from behaviour: boolean-based (page changes on true/false) & time-based (
SLEEPdelay on true) - Out-of-band — exfiltrate via a separate channel (DB makes a DNS/HTTP request to attacker domain with data encoded in it)
- Blind extracts data one character at a time — slower than union, but fully effective and automatable
- Verbose DB errors leak schema/version/structure — show generic errors, log details — but this only downgrades to blind
- All types are the same vulnerability read through different channels — closing a channel just forces another type
- The fix targets the cause: parameterized queries (Chapter 7) prevent the injection entirely — nothing to read back anywhere
- Next chapter: union-based data extraction in depth — column counts, types, and reading the schema