SQL Injection
Summary
Classic SQLi reports clustered around:
- URL/POST parameter injection into legacy ASP/PHP pages -
?id=1' OR '1'='1 - time-based blind via
WAITFOR DELAY(MSSQL),SLEEP()(MySQL),pg_sleep()(PostgreSQL) - Header-based SQLi via Referer, User-Agent, X-Forwarded-For when those values are logged into the database
- JSON-body SQLi via API parameters
- GraphQL filter clauses
- JWT kid SQLi
- UUID lookup endpoints accepting non-UUID values
- Search endpoints concatenating LIKE patterns
- ORM bypass via raw queries / unsafe builders. Sqlmap covers most surface but reports show several patterns where Sqlmap's default profile misses: header/cookie injection, complex JSON injection, GraphQL.
Top Affected Components / Targets
Legacy ASP/PHP/JSP pages with id, page, search, filter parametersSearch endpoints with LIKE patternsHeader-logged endpoints (analytics, error pages)REST APIs accepting JSON bodiesGraphQL query filter / order-byJWT validators looking up keys by kidLogin forms that look up users by username via SQL
Common Attack Vectors
URL/POST parameter ' OR '1'='1, ' UNION SELECT ...Time-based MSSQL: '; WAITFOR DELAY '0:0:13'--Time-based MySQL: ' AND SLEEP(13)--Time-based PostgreSQL: '; SELECT pg_sleep(13)--Boolean-based: ' AND '1'='1 vs ' AND '1'='2Error-based: ' AND extractvalue(rand(),concat(0x7e,version()))--Header injection: Referer/User-Agent/X-Forwarded-For containing payloadJSON body: {"name":"x' AND SLEEP(5)--"}GraphQL filter: where: { name: { _eq: "x' OR 1=1 --" } }JWT kid: {"kid":"test' UNION SELECT 'attacker_secret'--"}
Common Payloads
' OR '1'='11' UNION SELECT NULL,NULL,NULL--1' AND SLEEP(5)--'; WAITFOR DELAY '0:0:13'--'; SELECT pg_sleep(13)--1)) OR 1=1--' AND extractvalue(rand(),concat(0x7e,version()))--' AND (SELECT*FROM(SELECT(SLEEP(5)))a)--1' OR if(1=1,sleep(5),0) --' AND 'x'='x + ' AND 'x'='y (boolean differential)
Detection Strategy
Keep current Sqlmap-based module.
Inject time-based payloads into Referer / User-Agent / X-Forwarded-For / Cookie and detect latency differential.
For endpoints accepting JSON bodies, run Sqlmap with --data and --headers including Content-Type: application/json.
On detected GraphQL endpoints, identify filter / where / order-by paths in the schema (introspection helps) and submit time-based payloads.
For parameters where time-based fails (timeouts blocked), apply a boolean differential (' AND '1'='1 vs ' AND '1'='2) and detect content-length differences.
When a parameter expects UUID or int, submit non-UUID value with a quote and observe error messages - type-mismatch errors that include SQL fragments betray injection.
Confidence: time-based + 3-of-3 confirmation = high; boolean differential + 3 datapoints = high; error-message reveals SQL = high.
Tip: Testing tools that run these checks in parallel across every discovered endpoint can cut the time required substantially compared to fully manual testing, as long as they confirm findings with more than one signal to keep the false-positive rate down.
False-Positive Notes
- Time-based probes need stable network baseline - repeat 3 times.
- Sqlmap is high-quality but misses headers, cookies, JSON, and GraphQL by default - that's where the additive value lies.
- Error messages alone are a finding only when SQL fragments appear; generic 500 pages don't qualify.
How to Test
Manual Testing Methodology
Here is a systematic approach to identifying SQL Injection vulnerabilities in a target application.
Before testing, map all input vectors that could be affected. Identify parameters, headers, cookies, and request bodies that interact with the vulnerable component. A proxy such as Burp Suite or OWASP ZAP, paired with normal browsing of the target, is usually enough to build this list.
Send a legitimate request and record the normal response: status code, content length, response time, and any identifying tokens. This baseline matters because it's what you'll compare later responses against once payloads are involved.
Inject test payloads into each identified input vector one at a time. Start with benign detection payloads before escalating to anything that could actually trigger the vulnerability. For SQL Injection specifically, Test boolean-based (OR 1=1 vs OR 1=2), time-based (SLEEP(5) / WAITFOR DELAY), and UNION-based payloads against every parameter, one at a time, and in a database-neutral form before switching to DBMS-specific syntax once the backend is fingerprinted.
Compare the response against your baseline, looking specifically for a differential response between the true and false boolean payloads, a reproducible delay proportional to the injected sleep value on a second independent trial, or a UNION result set that reflects extra columns back into the page — a single slow response is not enough on its own, since network jitter produces the same signal.
Once a potential vulnerability is detected, confirm it with at least a few independent test cases to rule out coincidence. Document the exact request and response as proof. For SQL Injection, a confirmed finding typically means showing that attacker-controlled input changes the application's behavior in a way that matters for security, not just that a payload was reflected somewhere harmless.
Real-World Impact
Real-World Impact
SQL injection remains one of the most damaging vulnerability classes in production systems. When exploited, attackers gain direct access to the underlying database, which opens the door to mass data exfiltration (customer records, credentials, financial data), privilege escalation to database administrator, and in some configurations, operating system command execution through xp_cmdshell on MSSQL or LOAD_FILE and INTO OUTFILE on MySQL.
In disclosed bug bounty reports, SQL injection findings consistently receive critical severity ratings, and the window of exploitation before a bug is even discovered often stretches to weeks or months, even though patches tend to follow quickly once a report lands.
Organizations affected by SQL injection also face regulatory consequences under frameworks like GDPR, CCPA, and PCI DSS, on top of the direct costs of incident response and customer notification.
Prevention & Remediation
Prevention and Secure Coding
Preventing SQL Injection takes a defense-in-depth approach — no single control below is sufficient alone, but together they close off both the primary path and the most common bypasses.
Parameterized queries. Use parameterized queries or prepared statements as the primary control for every database call — never build SQL by concatenating or interpolating user input into a query string.
ORM query builders. Where an ORM is already in use, keep all query construction inside its builder API; a single raw-SQL escape hatch inside otherwise-safe code is a common source of the bug slipping back in.
Least-privilege database accounts. Run the application under a database account limited to exactly the tables and operations it needs — a successful injection against a read-only, single-schema account does far less damage than one against a shared admin login.
Stored procedures, reviewed. Stored procedures are not inherently safe; audit them for dynamic SQL built from parameters before treating them as a mitigation.
Defense in depth, not the primary control. Input validation and a WAF rule can catch obvious payloads, but treat them as a second layer — they are not a substitute for parameterization.
Source reports
A sample of the disclosed HackerOne reports this playbook was synthesized from.