Last updated
Vulnerability Severity Levels
- Critical — direct string concatenation with user input in WHERE, INSERT, UPDATE, DELETE
- High — ORM raw queries with concatenation, second-order injection patterns
- Medium — dynamic table/column names without whitelisting
- Low — LIKE clause without wildcard escaping
Defense Checklist
- Use parameterized queries for all user-supplied values
- Use whitelisting for dynamic table and column names
- Escape LIKE wildcards when user input is used in LIKE patterns
- Treat database-retrieved data as untrusted when using it in subsequent queries
- Apply input validation as an additional layer
- Use least-privilege database accounts (read-only where possible)
Examples
Example 1: String Concatenation (Most Common Vulnerability)
VULNERABLE code detected:
// JavaScript — VULNERABLE
const query = "SELECT * FROM users WHERE username = '" + req.body.username + "'";
// Python — VULNERABLE
query = "SELECT * FROM users WHERE email = '" + email + "'"
// PHP — VULNERABLE
$query = "SELECT * FROM products WHERE id = " . $_GET['id'];
// Java — VULNERABLE
String query = "SELECT * FROM orders WHERE user_id = " + userId;
Detection report:
VULNERABILITY DETECTED: SQL Injection (High Severity)
Location: Line 2
Pattern: String concatenation with user input in SQL query
Risk: Attacker can inject arbitrary SQL, bypassing authentication or extracting data
Attack example:
Input: ' OR '1'='1'--
Resulting query: SELECT * FROM users WHERE username = '' OR '1'='1'--'
Effect: Returns all users — authentication bypass
FIX: Use parameterized queries (see below)
Example 2: Safe Parameterized Query Alternatives
// Node.js + mysql2 — SAFE
const [rows] = await db.execute(
'SELECT * FROM users WHERE username = ?',
[req.body.username]
);
// Node.js + pg (PostgreSQL) — SAFE
const { rows } = await db.query(
'SELECT * FROM users WHERE email = $1',
[email]
);
// Python + psycopg2 — SAFE
cursor.execute(
'SELECT * FROM users WHERE email = %s',
(email,)
)
// PHP + PDO — SAFE
$stmt = $pdo->prepare('SELECT * FROM products WHERE id = ?');
$stmt->execute([$_GET['id']]);
// Java + JDBC — SAFE
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM orders WHERE user_id = ?"
);
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();
Example 3: ORM Raw Query Vulnerability
VULNERABLE — raw query with concatenation in an ORM:
# Django — VULNERABLE
users = User.objects.raw(
"SELECT * FROM users WHERE name = '" + name + "'"
)
# SQLAlchemy — VULNERABLE
result = db.execute(
text("SELECT * FROM users WHERE name = '" + name + "'")
)
SAFE alternatives:
# Django — SAFE
users = User.objects.raw(
"SELECT * FROM users WHERE name = %s",
[name]
)
# Django ORM — SAFE (preferred)
users = User.objects.filter(name=name)
# SQLAlchemy — SAFE
result = db.execute(
text("SELECT * FROM users WHERE name = :name"),
{"name": name}
)