EXERCISE 3 — Rebutting "no output, so SQLi can't leak data" =========================================================== THE CLAIM: "Our login only returns success/failure and shows no errors or query results, so even if there's SQLi, it can't leak any data." THE REBUTTAL — BLIND SQLi LEAKS DATA WITH NO OUTPUT: - Whether the app DISPLAYS data is irrelevant to whether the query is INJECTABLE. If user input is concatenated into the SQL, an attacker can still inject conditions that the database evaluates. They don't need to SEE results — they only need to distinguish TRUE from FALSE. - The app becomes a BOOLEAN ORACLE: inject a condition about the data and observe a behavioural difference. Even a bare success/failure login is a perfect 1-bit oracle: username: admin' AND SUBSTRING(password,1,1) > 'm'-- -> "login success/looks valid" => the condition is TRUE -> "login failure" => FALSE By binary-searching each character's value (~7 requests/char), the attacker reconstructs the password — or any other column — one character at a time, using nothing but the success/failure signal the developer thinks is safe. - So "shows no data/errors" reduces UNION/error-based to BLIND; it does not stop exfiltration. The data still comes out. WHY TIME-BASED WORKS EVEN ON IDENTICAL RESPONSES: - Suppose the response is byte-for-byte IDENTICAL for true and false (no success/failure difference at all). Boolean's content oracle is gone — but the attacker MANUFACTURES a signal: ' AND IF(, SLEEP(5), 0)-- When the condition is true the DB pauses ~5s; when false it returns immediately. The answer is read from RESPONSE TIME, not page content. - Because this only requires the injected SQL to EXECUTE (not to affect the output), it works no matter how blank/uniform the response is. There is almost always SOME timing channel on an injectable query, which is why "the endpoint returns nothing useful" provides no real protection. WHY "SLOW" DOESN'T HELP: - Blind extraction is slow per character, but it's fully AUTOMATED: sqlmap issues the thousands of inference requests and reassembles the data automatically. A 32-char hash (~224 requests) is recovered in moments. The slowness inconveniences nobody serious. WHY ONLY PARAMETERIZATION ACTUALLY CLOSES IT: - Hiding output, suppressing errors, and normalizing responses are all CHANNEL-CLOSING measures. They just push the attacker from union -> error -> boolean -> time-based. The underlying injectable query remains, so some inferential channel persists (timing almost always does). - PARAMETERIZED QUERIES (Chapter 7) fix the CAUSE: the input is bound as data and never parsed as SQL. Then there is no attacker-controlled condition to evaluate — no TRUE/FALSE to infer and no SLEEP to time. The oracle disappears entirely, along with every SQLi type. CONCLUSION: "No visible output" does not mean "no data leak" — blind (boolean and especially time-based) SQLi exfiltrates data from a silent endpoint, and is automated and complete. The developer's reasoning is false; the only real fix is to stop the injection at the source with parameterized queries.