SQL injection was first documented in 1998. Nearly three decades later, it remains one of the most impactful web vulnerabilities in existence. Every few years someone declares it dead — and every few years, a massive breach proves them wrong.
In 2025 alone, SQL injection was responsible for multiple high-profile data breaches affecting millions of users. Here's why it persists and how it's evolving.
Still Everywhere
33%
of Web App Audits
#3
OWASP Injection Rank
$4.5M
Avg SQLi Breach Cost
28 yrs
And Still Going
As we covered in our OWASP Top 10 analysis, injection vulnerabilities remain a top-3 concern. SQL injection is the most common and most damaging subtype.
Classic SQLi: Still Finding It
The textbook version — inserting SQL into a query string — still shows up because:
- Legacy code — Applications with codebases spanning 10+ years still have raw SQL queries
- Stored procedures — Dynamic SQL inside stored procedures bypasses ORM protections
- Raw queries in ORMs — Every ORM has an escape hatch (
.raw(),$queryRaw,execute()) and developers use them - String interpolation in logs/searches — Full-text search, reporting queries, and audit logging often build SQL dynamically
Identify injection point
Parameter in search, filter, sort, or any feature that queries the database dynamically
Confirm injection
Single quote (') causes a 500 error. 1 OR 1=1 returns all records. Sleep-based payloads confirm blind injection.
Extract data
UNION SELECT to read other tables. Subqueries to extract schema information. Stacked queries for data modification.
Escalate
Read password hashes, access admin accounts, write files to disk, or execute OS commands (xp_cmdshell, INTO OUTFILE).
Modern SQLi: The New Vectors
Second-Order SQL Injection
Second-Order SQLi
The pattern
User input is safely stored in the database (properly escaped on insert). Later, that stored value is read from the database and used in a different query without escaping — because developers trust data from their own database.
Example
Registration: username "admin'--" is safely stored. Password reset: the username is read from the database and used in a query: SELECT * FROM users WHERE username = '{stored_username}'. The stored payload now executes.
Why it's missed
Automated scanners inject and check the immediate response. Second-order SQLi requires the payload to trigger in a different feature entirely — most scanners never correlate the two.
NoSQL Injection
With MongoDB, Redis, and other NoSQL databases increasingly common:
JSON operator injection
Instead of SQL syntax, inject MongoDB query operators: {"username": {"$ne": ""}, "password": {"$ne": ""}} — matches any document where both fields are non-empty, bypassing authentication.
JavaScript injection
MongoDB's $where clause accepts JavaScript: {"$where": "this.password.length > 0"} — or worse, arbitrary code execution via server-side JavaScript.
Regex DoS
MongoDB's $regex operator accepts user-supplied patterns. A crafted regex like /^(a+)+$/ causes catastrophic backtracking, creating a denial-of-service.
ORM-Specific Injection
ORMs aren't bulletproof:
ORM Injection Vectors
Raw query methods
Every ORM provides .raw(), .execute(), or similar. When developers need complex queries that the ORM can't express, they drop to raw SQL — and often forget to parameterize.
Dynamic column/table names
ORMs parameterize values but usually can't parameterize column names, table names, or ORDER BY directions. These are often interpolated directly from user input.
Batch operations
Bulk insert, update, or upsert operations sometimes bypass the ORM's normal parameterization. Edge cases in batch size handling can create injection points.
Filter/sort parameters
API endpoints that accept arbitrary filter conditions (field, operator, value) often translate directly to ORM query builders without validating allowed fields or operators.
GraphQL + SQLi
GraphQL's flexible query language creates new injection surfaces. As we'll cover in our GraphQL security post, dynamically resolving nested fields often generates dynamic SQL under the hood.
WAFs Don't Solve It
As we detailed in WAF Bypass Techniques, WAFs are easily bypassed for SQL injection:
WAF Bypasses for SQLi
- •Encoding: %53%45%4C%45%43%54 instead of SELECT
- •Comments: SEL/**/ECT, S%00ELECT
- •Alternative syntax: CHAR(), CONCAT(), hex encoding
- •HTTP parameter pollution to split payloads
What Actually Works
- •Parameterized queries (prepared statements)
- •ORM with strict mode (no raw queries allowed)
- •Input validation (allowlist, not blocklist)
- •Least-privilege database accounts
The Defense Stack
Parameterize
Use parameterized queries for ALL database interactions — no exceptions, no "just this once"
Validate
Allowlist valid values for column names, sort directions, and filter operators — never interpolate user input into query structure
Least Privilege
Database accounts should have minimum required permissions — no DROP, no FILE, no GRANT
Test
Automated SQLi scanning on every deployment plus manual testing for second-order and ORM-specific injection
💡The One Rule
If you follow one rule, follow this: never concatenate user input into SQL strings. Use parameterized queries for values. Use allowlists for structural elements (column names, table names, sort directions). This eliminates SQL injection entirely.
How We Find SQLi
Our Web Security Auditor uses multi-layered SQLi detection:
- Every parameter tested — Form fields, URL parameters, headers, JSON bodies, cookies — with payloads specific to the detected database type
- Blind detection — Time-based, boolean-based, and error-based detection for injection points that don't return visible output
- Second-order correlation — AI tracks stored values and tests for their reappearance in other queries
- Human expert testing — Our expert review catches ORM-specific injection, stored procedure vulnerabilities, and complex multi-step SQLi chains
As we emphasized in API Security: The Blind Spots Most Teams Miss, API endpoints are the most common location for modern SQL injection — filter parameters, search endpoints, and sort controls are frequently vulnerable.
Is your application safe from SQL injection — including the modern variants? Our Web Security Auditor tests every input against every injection technique, and our expert review catches second-order and ORM-specific SQLi that automated tools miss. Get started.