Last updated: April 26, 2026
SQL injection has been on the OWASP Top 10 since 2003. Frameworks have parameterised queries baked in. Every developer has been told about it. And yet, in 2026, we still find at least one SQLi on roughly 40% of Indian web pentest engagements. This article covers why it persists, the modern variants (blind, time-based, second-order, NoSQL injection), the right way to find them, and the defender-side controls that actually catch exploitation.
Why SQL injection refuses to die
Three structural reasons:
- Legacy code in maintenance mode. The application was written in 2014 in PHP / Java / .NET with string-concatenated queries. The team that wrote it left. The new team is told “do not touch the auth flow” because it works. Vulnerabilities that pre-date the org’s security awareness persist.
- Dynamic queries that look “safe.” Developers use parameterised queries for the obvious places (login forms) but build dynamic ORDER BY, LIMIT, table-name, or column-name strings via concatenation because parameterisation does not directly support them.
- NoSQL injection. MongoDB, DynamoDB, Elasticsearch — the “no SQL means no SQL injection” assumption is wrong. Each has its own injection class.
The variants you need to know in 2026
Classic in-band SQLi
The query reflects results into the response. Union-based and error-based injection use this:
http://target/product?id=1' UNION SELECT username,password FROM users-- -
Still found on legacy admin panels, internal tools that nobody pen-tested in years.
Blind boolean-based
The response differs based on whether the injected condition is true or false. Time-consuming to exploit manually, automated by sqlmap.
id=1 AND 1=1 -- normal page
id=1 AND 1=2 -- different page (blank, error, redirect)
Blind time-based
The application’s response time differs based on the injected condition. Useful when the response itself is identical.
id=1; IF (DB_NAME()='production') WAITFOR DELAY '0:0:5'-- -
Out-of-band
The injection triggers a network callback (DNS lookup, HTTP request) that the attacker observes externally. Useful in firewalled environments where direct response is unavailable.
id=1; EXEC master..xp_dirtree '\\\\<collaborator-domain>\\foo'
Second-order SQLi
The malicious payload is stored (in a profile field, a comment, a config setting). It does not trigger immediately. Later, an admin function reads it back and concatenates it into a query — exploitation happens at that second touch.
Found in admin reporting tools that pull user-controlled data into custom SQL. Often missed by automated scanners because the attack and trigger are temporally and contextually separated.
NoSQL injection (MongoDB)
// Vulnerable: { username: req.body.user, password: req.body.pass }
// Attacker sends:
{ "user": { "$ne": null }, "pass": { "$ne": null } }
// Matches any document where both fields are non-null = bypass
JavaScript-style query operators ($ne, $gt, $regex) work as injection vectors when the application accepts JSON without validation.
ORM injection
ORM-driven applications often build raw SQL via the ORM’s “raw” or “query” methods. Concatenating user input into these bypasses ORM safety.
How to find SQLi systematically
Practitioner workflow:
- Map every input. Every request parameter, every header (User-Agent, Referer, X-Forwarded-For), every cookie, every body field, every JSON path. SQLi can hit any of them.
- Test for canary characters.
',",;,--,/*. Watch for differential response — error message, blank page, 500 status, content change. - Test boolean and time variants for inputs that do not error visibly.
- Identify the SQL dialect from error messages (MySQL
You have an error in your SQL syntax, MSSQLUnclosed quotation mark, Postgressyntax error at or near, OracleORA-00933). - Use sqlmap for automation once you have located a vulnerable parameter.
sqlmap -u 'http://target/page?id=1' --batch --risk=3 --level=5. - Manual exploitation for second-order and complex cases sqlmap struggles with.
Burp’s Active Scanner and ZAP both find the obvious cases. They miss second-order and NoSQL routinely. Manual review is the differentiator.
Detection — what works for the defender
WAF rules catch obvious attacks:
- AWS WAF Managed Rules (AWSManagedRulesSQLiRuleSet)
- Cloudflare Managed Rules (OWASP Core Rule Set)
- ModSecurity with CRS
WAFs are not the answer to SQLi — they are bypassable through encoding and obfuscation. They are the noise filter. Real defence:
- Parameterised queries everywhere. Audit your codebase for string concatenation in query construction. Linters (Bandit for Python, Brakeman for Ruby, SonarQube for Java) catch many cases.
- Input validation by allowlist. If a parameter should be a positive integer, reject anything else — never sanitise, never blacklist.
- Stored procedures with parameter binding for critical paths. Layered defence.
- Database user with least privilege. The web-app DB user should not have
SELECT *on all tables. Break out per-purpose users (read-only for catalog, write for cart, etc.). - Database firewall (Imperva DB Firewall, Oracle DB Firewall, IBM Guardium) — analyses queries in real time, flags anomalies.
- Audit logging on the database — every query logged. SQLi attacks generate distinctive log patterns.
The detection rule that actually catches exploitation
SQLi attempts generate database error events that legitimate traffic does not. SIEM rule:
index=database_audit (eventCode IN (1064, 1146, 1305, 102, 156, 207, 16921))
| stats count by source_ip, _time, error_message
| where count > 10
Ten error events from a single source in a short window strongly indicates an attacker testing payloads. Tune by carving out known scanners.
How to find your next SQLi
For attackers:
- Test legacy admin panels — internal tools rarely get pen-tested. Search for CMS panels (
/admin,/manager,/cpanel,/dashboard). - Look for inputs that go to ORDER BY, LIMIT, TOP, or ROWNUM clauses — these are usually concatenated even in modern codebases.
- Test JSON / XML / GraphQL inputs — modern attacks shift here as form-based has hardened.
- Try second-order: register an account with a SQL payload in your name; check whether any admin or reporting page exposes the payload back into a query.
For defenders:
- Run static analysis (Semgrep, CodeQL) over your codebase looking for concatenation patterns near SQL execution functions.
- Audit query logs for the past 30 days; cluster by SQL signature; outliers are likely either bad code or attacks.
- Apply the principle of least privilege at the database user level.
Compliance angle
- OWASP Top 10 A03:2021 — Injection. Most compliance frameworks reference this directly.
- DPDP §8(5) — SQLi exposing personal data is a reasonable-security failure.
- SEBI CSCRF — application security testing is mandatory; SQLi is the canonical finding class.
- PCI-DSS Requirement 6.5.1 — addressing common vulnerabilities including injection.
The takeaway
SQL injection in 2026 is not interesting because it is novel. It is interesting because it persists. Every Indian-market application audit we do still finds it. The fix is decades-old advice — parameterised queries, input validation, least-privileged DB users — applied to legacy code that has accumulated entropy. The discipline is in the work, not the technique. If your team has not run a SQLi-focused audit on your top-3 customer-facing applications this year, schedule one. The findings will be your highest-leverage AppSec backlog.
Get a VAPT scoping call
Senior practitioner-led VAPT — not a checklist run by juniors. CVSS-scored findings, free retest, attestation letter. India's SMBs and SaaS teams.