Beyond SELECT
So far the injections have read data through SELECT queries. But SQLi isn't limited to reads — it can modify data, chain whole new statements, and even lie dormant until triggered later. This chapter covers the write-side and the trickier delivery patterns, including the one that defeats input-time validation entirely. (Defensive framing — own systems / labs only.)
Injection Into Write Statements
Any statement built with user input is injectable, not just SELECT. An UPDATE or INSERT that concatenates input can be subverted to change other columns or rows:
The same applies to WHERE clauses on writes: an injectable UPDATE … WHERE id=$id with id = 5 OR 1=1 updates every row. A DELETE with the same flaw deletes the whole table. So injection into a write is an integrity and availability attack, not just confidentiality.
Stacked Queries: Running Entirely New Statements
Some database drivers allow multiple statements separated by a semicolon in one call. Where that's enabled, an attacker can append a completely separate command after the original — turning a read into a write, a drop, or anything else:
mysql_query/PHP, and many parameterized-query APIs run exactly one statement), which is why the infamous '; DROP TABLE doesn't always work. But others do allow stacking (often SQL Server, PostgreSQL, and MySQL with multi-statements enabled), so it's a real risk, not a myth. The reassuring part isn't "stacking is usually off" — it's that parameterized queries don't just block stacking, they prevent the injection that would attempt it. Never rely on a driver setting as your defence.
Authentication Bypass — the Write/Logic Variant
Chapter 2 showed login bypass via SELECT. Note it ties to the whole Auth course: injection can also create or elevate accounts (the role='admin' trick above), reset another user's password through an injectable update, or satisfy a privilege check — turning a query-construction bug into full account compromise with no credential. SQLi is frequently the first step in a breach, then pivots through these write capabilities.
Second-Order SQLi: The Payload That Waits
The subtlest and most important pattern in this chapter. Second-order (stored) SQLi splits the attack across two requests: the payload is safely stored first, then triggers later when some other code reads it back into a query unsafely.
The Unifying Point
Reads, writes, stacked statements, and second-order delivery look different, but they're all the same root cause from Chapter 1 — untrusted input parsed as SQL — at different statement types and via different timing. And they all collapse under the same fix: a parameterized query binds input as data regardless of whether the statement is a SELECT or an UPDATE, whether stacking is on or off, and whether the value arrived just now or was read from a table. One discipline, applied to every query, closes all of it (Chapter 7).
Hands-On Exercises
Show how an injectable UPDATE users SET nickname='$n' WHERE id=$id can be used to (a) escalate the attacker's own privileges and (b) modify every row. Explain why injection into writes is an integrity/availability attack, not just data theft.
Explain what stacked queries are and give an example that turns a SELECT into a destructive command. Then explain why '; DROP TABLE doesn't always work, and why "our driver blocks multiple statements" is a weak thing to rely on.
Explain second-order SQLi end to end: how a payload is stored safely in request 1 and fires in request 2. Explain precisely why input validation/sanitization fails to stop it, and state the correct principle for deciding what data is "trusted."
📄 View solutionChapter 6 Quick Reference
- SQLi isn't only reads — INSERT/UPDATE/DELETE are injectable too: alter other columns/rows, escalate privileges (
role='admin'), delete everything - Injection into writes is an integrity & availability attack (modify/destroy data), not just confidentiality
- Stacked queries — a
;appends a whole new statement ('; DROP TABLE users--); works only where the driver allows multi-statements '; DROP TABLEoften fails because many drivers/APIs run one statement — but some allow stacking; don't rely on the driver setting- SQLi ties to the Auth course: create/elevate accounts, reset others' passwords — query bug → account compromise
- Second-order SQLi — payload stored safely in request 1, fires when a different path reads it into a query in request 2
- Second-order defeats input-time validation — the data comes from your own DB; trust by origin (a user), not by where it currently sits
- All variants = one root cause; all close under parameterizing every query (SELECT and writes, reading user input and your own tables)
- Next chapter: the primary defence — parameterized queries / prepared statements, in full