A03 — Injection Secure

1000-ft view: Injection occurs when untrusted input reaches an interpreter (SQL, HTML, etc.). This page shows secure patterns—parameterized queries, strict validation, and output encoding—across five scenarios: Login bypass, UNION search, Blind/Time-based probing, Second-order SQLi, and Stored XSS.

Uses the shared DB (same DSN) with module-scoped tables a03_*. Seed data lives in db/seed.sql. Compare with the Insecure version.

Attack 1 — SQL Login Bypass

prepared + password_verify

Secure idea: never concatenate credentials into SQL. Fetch by email with a prepared statement; verify with password_verify().

  1. Enter a seeded user’s email/password (see db/seed.sql).
  2. Submit — the endpoint uses prepared statements and constant-time-ish checks.

Attack 2 — UNION Search

LIKE ? with bound %q%

Secure idea: use name LIKE ? with a bound value (%q%). Return a fixed schema and suppress raw SQL errors.

  1. Search for a fragment (e.g., lap).
  2. The endpoint binds the wildcard; UNION payloads are neutralized.

Attack 3 — Blind/Time-based

integer bind + stable timing

Secure idea: coerce IDs to integers and bind them. Avoid dynamic concatenation and timing oracles.

  1. Enter a product ID.
  2. The secure endpoint binds ? = :id and returns a safe count.

Attack 4 — Second-order SQLi

validate on write + prepare on read

Secure idea: validate/normalize on input; always use prepared statements when reusing stored fields.

  1. Save your profile bio (requires login).
  2. Open the admin view — it uses bound parameters when joining on stored data.

Attack 5 — XSS (Stored + Reflected)

encode on output (+ optional allowlist)

Secure idea: store text as-is if you need auditability, but always encode on output (e.g., htmlspecialchars). For rich text, use a strict allowlist/sanitizer. Below, everything runs in SAFE mode (encoded output).

  1. Stored XSS (SAFE): post a comment. It’s encoded on display, so scripts won’t run.
  2. Reflected XSS (SAFE): reflect user input back to the page — encoded output prevents execution.
Reset Comments