Infinity8 Labs is now Breachvane Labs.

SQL injection (SQLi)

SQLi

User input is built into a database query as code instead of being passed as data, letting an attacker read, change or delete data and sometimes take over the database server.

Also known as
Blind SQL injection · Error-based SQL injection · Second-order SQL injection
Typical severity · High to Critical
Last updated
On this page: What it is
  1. 1 · What it is
  2. 2 · Why it matters
  3. 3 · Examples
  4. 4 · How to fix it
  5. 5 · How to test for it
  6. References
  7. Related

What it is#

SQL injection occurs when an application builds a SQL statement by joining strings, and part of that string comes from an attacker. Characters like ', -- and ; change the structure of the query, so the database executes logic the developer never wrote.

Common variants:

  • In-band (error-based or UNION-based): results or database errors come back in the response.
  • Blind (boolean or time-based): nothing is shown directly, but the attacker infers data from response differences or delays.
  • Second-order: input is stored safely, then later concatenated into a different query, often in a background job or report.

Why it matters#

  • Read any data the application's database account can reach: customer records, password hashes, API tokens.
  • Bypass authentication by making a login query always return true.
  • Modify or delete data, including audit logs.
  • On some platforms and configurations, read files, call stored procedures or run operating system commands, turning a web bug into server compromise.
Typical severity

High to critical. Unauthenticated SQL injection on an internet-facing application is commonly CVSS 3.1 9.8. Actual severity depends on context: who is affected, what data or actions are reachable, and existing controls.

Examples#

✕ Vulnerablepython
# Vulnerable: string formatting builds the query
cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
✓ Fixedpython
# Fixed: parameter binding (psycopg / DB-API)
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
✕ Vulnerablejava
// Vulnerable: concatenation in JDBC
String q = "SELECT * FROM orders WHERE id = " + request.getParameter("id");
ResultSet rs = stmt.executeQuery(q);
✓ Fixedjava
// Fixed: PreparedStatement
PreparedStatement ps = conn.prepareStatement("SELECT * FROM orders WHERE id = ?");
ps.setLong(1, Long.parseLong(request.getParameter("id")));

A tester confirming the issue typically sends a single quote and looks for a database error, or compares responses to id=5 AND 1=1 versus id=5 AND 1=2.

How to fix it#

1. Use parameterized queries everywhere. The query structure is sent separately from the values, so input can never become code.

✓ See fixed example 1 in Examples ↑

✓ See fixed example 2 in Examples ↑

✓ Fixedjavascript
// Fixed: node-postgres
await pool.query('SELECT * FROM orders WHERE id = $1', [req.params.id]);

2. Use ORM features safely. ORMs parameterize by default, but raw-query helpers (raw(), $queryRawUnsafe, extra(), string-built where clauses) bring the risk back.

3. Allow-list identifiers. Table names, column names and sort directions can't be bound as parameters. Map user choices to fixed values:

Examplepython
SORTS = {"name": "name", "created": "created_at"}
order_by = SORTS.get(request.args.get("sort"), "created_at")

4. Least privilege. Give the application's database account only the permissions it needs; never use a superuser or sa account. Disable features like xp_cmdshell.

5. Don't leak errors. Return generic errors to users and log details server-side.

How to test for it#

  • Inventory every input that reaches a query, including headers, cookies, JSON bodies, sort/filter parameters and stored values reused later.
  • Probe with syntax-breaking characters and boolean or time-based conditions; compare responses.
  • Use tools such as sqlmap carefully and only within an authorized scope, with non-destructive options.
  • Review code for string-built queries and unsafe ORM calls; add a static analysis rule to block them.
  • After fixing, retest each parameter and add regression tests.

References#

Permalinkwww.breachvanelabs.com/library/sql-injection/JSON
Found this in Breachvane? Your finding links here for background. Evidence, affected assets and retest status are in your Breachvane ↗ (opens in a new tab) workspace. Need help fixing it? Talk to us (opens in a new tab).