SQL Injection Detection
SQL injection detection confirms whether user-supplied input is interpreted by a backend database. The goal here is to prove the condition exists and identify the injection type: not to extract data. Confirmed injection moves to SQL injection exploitation.
- Error-based detection injects a single quote and watches for database error messages in the response.
- Boolean-blind detection compares response sizes between true (1=1) and false (1=2) conditions.
- Time-based blind detection injects SLEEP or WAITFOR DELAY and measures the response delay.
- POST and header injection tests login forms, cookies, and headers like X-Forwarded-For.
- sqlmap automated detection scans multiple parameters and injection types with one command.
Target any parameter that likely hits a database: id, user, search, category, order, sort, page, filter. Parameters discovered during parameter crawling are your starting list.
Error-Based Detection
Inject a single quote and watch for database error messages in the response. An error proves the input reaches a SQL query without sanitization:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
A MySQL syntax error is a confirmed injection point. Note the database type from the error message: it determines the payload syntax for exploitation. ORA- prefix means Oracle, pg_ means PostgreSQL.
Boolean-Based Blind Detection
When errors are suppressed, compare responses between a true and false condition. Different response sizes or content confirm blind SQLi:
4823
612
Different response sizes for true versus false conditions confirms boolean-blind SQLi. The true condition returns the normal page while the false condition returns a shorter or empty page.
Time-Based Blind Detection
When no response difference is visible, inject a sleep and measure the delay. This works even when the application returns identical responses for all inputs:
real 0m5.123s
A 5-second delay matching the SLEEP parameter confirms time-based blind SQLi. SLEEP is MySQL syntax. WAITFOR DELAY is MSSQL. pg_sleep(5) is PostgreSQL. Try all three if the database type is unknown.
POST Parameter and Header Injection
SQLi is not limited to GET parameters. Test POST bodies, cookies, and HTTP headers:
Automated Detection with sqlmap
sqlmap automates all detection types. Use it for quick confirmation across multiple parameters:
Important
This tool is prohibited in the OSCP exam. Do not use during exam environments.
Explain command
| --batch | Non-interactive mode, use default answers for all prompts. |
| --level=3 | Test depth: includes cookie, User-Agent, and Referer injection points. |
| --risk=2 | Risk level: includes time-based and heavy OR-based payloads. |
Authentication Bypass Payloads
Login forms are a common SQL injection target because the backend query compares submitted credentials directly against the database. If the WHERE clause uses user input without parameterization, a payload can make the condition always true and bypass authentication entirely.
' OR 1=1--
' OR '1'='1
admin'--
' OR 1=1#
" OR 1=1--
admin" OR "1"="1
') OR ('1'='1
admin')--
The comment character at the end of a payload is critical because it truncates the rest of the original query. Database-specific comment variants:
--(with a trailing space) works on MySQL, MSSQL, and PostgreSQL#is MySQL-specific/*works as a block comment on MySQL, MSSQL, and PostgreSQL
Try all three when the backend database is unknown. A payload that works with # but not -- confirms MySQL.
Test each field independently: inject in the username field with an arbitrary password first, then try a valid username with the payload in the password field. Some applications validate one field before constructing the query with the other.
< HTTP/1.1 302 Found < Location: /dashboard
A 302 redirect to a dashboard or admin panel confirms the bypass. Check the response body for authenticated content such as session tokens or user details.
Raw Hash Bypass (PHP Loose Comparison)
When a PHP application stores password hashes and compares them with == instead of ===, certain MD5 hashes starting with 0e followed by only digits are interpreted as zero in scientific notation. Two different strings whose MD5 hashes both match 0e[0-9]+ compare as equal under loose comparison.
240610708 -> MD5: 0e462097431906509019562988736854
QNKCDZO -> MD5: 0e830400451993494058024219903391
aabg7XSs -> MD5: 0e087386482136013740957780965295
aabC9RqS -> MD5: 0e041022518165728065344349536299
If the login form hashes the submitted input and compares it loosely against the stored hash, submitting one of these strings as the password for a user whose hash also starts with 0e bypasses authentication. This is PHP-specific and only applies when comparison uses == on the hash strings.
References
-
Automated SQL injection detection and exploitation tool
-
PortSwigger: SQL InjectionTOOL: PortSwigger: SQL Injection, portswigger.net/web-security/sql-injection (opens in new tab)
Detection methodology and injection type reference