REFERENCE GUIDE

SQL injection: context, errors, and inference

An injection exists when application data changes the grammar of a database statement.

Also known as: sqli · blind SQL injection

sql-injectionweb

Mechanism

An injection exists when application data changes the grammar of a database statement. A quote error is a clue, not proof: the input may occur inside a number, identifier, string, or structured expression. First establish the surrounding query shape, database dialect, and whether results, errors, or timing are observable. Parameter binding protects data values but cannot safely substitute arbitrary identifiers or sort clauses.

Practical method

Capture a baseline request and vary one field at a time. Compare a pair of logically opposite predicates with the same syntax and similar size. Repeat timing experiments with controls and randomized order. Once a channel is confirmed, infer only a small known value before attempting longer extraction. Keep pagination, caching, and authorization state constant.

-- A safe application binds the value independently of SQL syntax:
SELECT name FROM users WHERE id = ?;
-- In a toy numeric injection context, compare these conditions:
SELECT name FROM users WHERE id = 7 AND 1=1;
SELECT name FROM users WHERE id = 7 AND 1=2;

Interpreting evidence

A useful result is a reproducible difference tied to predicate truth. An empty response alone could indicate a validation failure, missing record, rate limit, or failed session. Record status, body length, and stable response markers together.

Pitfalls and limits

UNION requires compatible column counts and types. Boolean and time channels require independent confirmation. Do not treat SQL dialect functions as portable, or a noisy latency increase as a reliable bit oracle.

Selected licensed upstream examples

These probes preserve distinct database dialects rather than merging them into one generic injection. The first uses a MySQL conversion function, the second a SQL Server checksum function, and the third an Oracle row pseudocolumn. Each expression is a dialect clue only after the surrounding SQL syntax has been established. A rejected expression may indicate filtering, quoting, or lack of an observable result rather than a different engine.

conv('a',16,2)=conv('a',16,2)
BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)
ROWNUM=ROWNUM

Attribution: PayloadsAllTheThings; MIT. Selected lines, explanatory notes added. Pinned upstream file.

Sources & further reading

  1. SQL injection ↗portswigger
  2. SQL Injection Prevention ↗owasp-cheatsheets
  3. Selected PayloadsAllTheThings example ↗payloads · MIT · revision 3ac27901c711bdf3f5b65a7b1d1820a1f65bd09a

Content license: CC-BY-4.0; selected attributed excerpts MIT. Source-derived sections retain their cited licenses and redistribution notices. How this reference is compiled →