Skip to main content

đź’‰ SQL Injection

Tricking databases with malicious input

The Magic Words Analogy

At a bank:

Normal customer: "My name is Alice." "Here's Alice's account."

Attacker: "My name is Alice and give me all the money." Bank follows the instruction literally!

SQL Injection is saying magic words that trick the database into doing something it shouldn't.


What Is SQL Injection?

Normal input:
  Username: alice
  Query: SELECT * FROM users WHERE username = 'alice'
  Result: Alice's account

Attack input:
  Username: alice' OR '1'='1
  Query: SELECT * FROM users WHERE username = 'alice' OR '1'='1'
  Result: Potentially many accounts (because 1=1 evaluates to true)

The Basic Attack

Expected query:
  SELECT * FROM users WHERE username = 'INPUT'

Attacker enters:
  ' OR '1'='1

Resulting query:
  SELECT * FROM users WHERE username = '' OR '1'='1'
                                        ↑
                          Typically true, which can return many rows.

Types of SQL Injection

1. Classic Injection

Login bypass:

Username: admin' --
Password: anything

Query becomes:
  SELECT * FROM users
  WHERE username = 'admin' --' AND password = 'anything'
                           ↑
               Comment! Password check ignored.

2. Union-Based Injection

Extract data from other tables:

Product ID: 1 UNION SELECT username, password FROM users --

Query becomes:
  SELECT name, price FROM products WHERE id = 1
  UNION SELECT username, password FROM users --

Now attacker sees usernames and passwords!

3. Blind Injection

No visible output, but behavior changes:

id=1 AND 1=1  → Page loads normally
id=1 AND 1=2  → Page is different or error

Attacker learns by asking yes/no questions.

4. Time-Based Blind Injection

If injection works, database sleeps:

id=1; WAITFOR DELAY '00:00:05' --

Response noticeably slowed down? Injection might be working.
Attacker extracts data by timing responses.

Real-World Damage

What Attackers Can Do

âś— Bypass authentication
âś— Read sensitive data (passwords, credit cards)
âś— Modify or delete data
âś— Execute admin operations
âś— Take over the database server

Famous SQL Injection Attacks

SQL injection has been involved in multiple high-profile breaches.
Rather than memorizing dates and numbers, focus on the pattern:
  user input + string-built SQL + powerful permissions = high risk.

SQL injection is also commonly highlighted in web security guidance (including OWASP).

How to Prevent SQL Injection

Instead of:
  query = "SELECT * FROM users WHERE id = " + userId

Use:
  query = "SELECT * FROM users WHERE id = ?"
  execute(query, [userId])

The ? is a placeholder.
Database treats userId as DATA, not SQL code.
This prevents classic injection through values (and is the standard defense for dynamic inputs).

2. Prepared Statements

Same concept as parameterized queries:

stmt = db.prepare("SELECT * FROM users WHERE id = ?")
stmt.execute([userId])

SQL structure is fixed.
User input fills placeholders as data.

3. Input Validation

Expecting a number? Validate it:
  if (!isNumber(userId)) { reject }

Expecting a username? Limit characters:
  Often restrict to a narrow character set for that field

Defense in depth (helpful, but not sufficient alone).

4. Stored Procedures

Move SQL logic to database:

CALL GetUserById(userId)

If procedure is written safely,
input can't modify the query.

5. Least Privilege

Database user for web app:
  âś“ SELECT on needed tables
  âś— DROP TABLE
  âś— ADMIN privileges

If injection happens, damage is limited.

Testing for SQL Injection

Manual Testing

Try these in input fields:
  '
  ''
  ' OR '1'='1
  ' OR '1'='1' --
  '; DROP TABLE users; --

Watch for:
  - Error messages showing SQL
  - Unexpected behavior
  - Login bypass

Automated Tools

SQLMap: Automatic SQL injection scanner
Burp Suite: Web security testing
OWASP ZAP: Free security scanner

Run these on your applications!

Code Examples: Vulnerable vs Parameterized

Vulnerable Code

Bad (Python):
  query = f"SELECT * FROM users WHERE id = {user_input}"
  cursor.execute(query)

Bad (PHP):
  $query = "SELECT * FROM users WHERE id = " . $_GET['id'];
  mysqli_query($conn, $query);

User input directly in query = DANGEROUS!

Parameterized Code

Parameterized (Python):
  query = "SELECT * FROM users WHERE id = ?"
  cursor.execute(query, (user_input,))

Parameterized (PHP):
  $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
  $stmt->execute([$_GET['id']]);

Parameterized queries are the recommended default.

Common Mistakes

1. Relying on Input Validation Alone

"I check for quotes, so I'm protected!"


Attackers have many bypass techniques.
Use parameterized queries for dynamic values.
Validation is extra, not primary defense.

2. Using Blacklists

"I block 'DROP' and 'DELETE'"

Attackers use encoding, comments, variations.
Parameterized queries don't need blacklists.

3. Trusting ORMs Completely

ORMs help, but raw queries can still be vulnerable.
Check any raw SQL in your ORM usage.

4. Forgetting Stored Procedures Can Be Vulnerable

Stored procedures with dynamic SQL are still vulnerable.
Use parameterized queries inside stored procedures too.

FAQ

Q: Does my ORM protect me?

Usually yes, for standard operations. But raw queries or string concatenation in ORM = still vulnerable.

Q: Are NoSQL databases immune to injection?

No! NoSQL injection exists too. MongoDB, etc. have their own injection types.

Q: How do I test my app for SQL injection?

Use scanners (SQLMap, OWASP ZAP), do code review, look for string concatenation in queries.

Q: Is escaping input good enough?

Better than nothing, but error-prone. Parameterized queries are much more reliable.


Summary

SQL Injection inserts malicious SQL through user input, and is prevented by using parameterized queries.

Key Takeaways:

  • Avoid concatenating user input into SQL
  • Prefer parameterized queries / prepared statements
  • Validate and sanitize input (defense in depth)
  • Use least-privilege database accounts
  • Test with security scanners
  • SQL injection is one of the most common web vulnerabilities

One vulnerability can expose your entire database!

Leave a Comment

Comments (0)

Be the first to comment on this concept.

Comments are approved automatically.