SQL injection remains one of the highest-impact application risks because a single vulnerable query can expose customer data, admin credentials, and billing information. This checklist helps engineering teams test systematically and remediate quickly.
Also see: How to Prevent SQL Injection Attacks, OWASP Top 10 Explained 2026, Laravel Production Security Checklist, and API Security Best Practices.
Define test scope
- Public forms (search, login, contact, checkout fields).
- API endpoints that accept filters/sort/pagination values.
- Admin panels and reporting queries.
- Legacy endpoints with custom SQL or dynamic query fragments.
Map all user input vectors
Teams often miss injection paths outside traditional forms. Include headers, URL parameters, JSON bodies, cookies, and any value that reaches query builders.
Checklist by risk level
Critical checks
- Dynamic SQL concatenation with user input.
- String-built WHERE clauses without parameterization.
- Stored procedures with unsafe dynamic SQL.
- Error messages leaking query structure/schema details.
High-value checks
- Insufficient validation on numeric ID and filter fields.
- Unsafe ORM raw query escapes.
- Missing least-privilege DB account model.
- No alerting for suspicious query activity bursts.
# Quick verification workflow
1) Enumerate all query-producing endpoints
2) Test with safe payload patterns in staging
3) Confirm prepared statement usage per endpoint
4) Validate DB account privileges
5) Re-scan and compare findings trend
Remediation playbook
- Parameterize everything: no string concatenation for query values.
- Input allowlists: enforce strict type and format at entry points.
- Output handling: avoid leaking database error details to clients.
- DB hardening: separate read/write roles and restrict sensitive tables.
Where SQL injection hides: input vectors teams miss
Most developers check form fields for SQL injection. Attackers test everything that reaches a database query — including vectors that are frequently overlooked in application security testing.
- HTTP headers:
User-Agent,Referer,X-Forwarded-For, and custom headers that are logged to a database or used in queries. Applications that log request metadata to a database are common SQLi targets through header injection. - Cookie values: Session identifiers, preference values, and A/B test flags stored in cookies that are used in database lookups without parameterization.
- JSON body fields: REST APIs that parse JSON and insert values directly into queries. The
Content-Type: application/jsonbody is not sanitized by most WAF rules configured for form inputs. - GraphQL variables: GraphQL resolvers that construct dynamic SQL from query variables. Framework-level ORM protection is bypassed when resolvers use raw queries for performance.
- URL path segments: Route parameters like
/users/123/profilewhere123is used directly in a query without type validation. - Search and sort parameters:
?sort=username&order=asc— ORDER BY clauses cannot use parameterized values in most databases; column names must be validated against an allowlist.
Integrating SQLi testing into CI/CD
Manual SQLi testing is insufficient for applications that deploy frequently. Integrating automated detection into the CI/CD pipeline ensures new injection points are caught before reaching production.
# Example: OWASP ZAP baseline scan in GitHub Actions
- name: OWASP ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.9.0
with:
target: 'https://staging.yourdomain.com'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a' # Include active scan (detects SQLi)
# Block merge on HIGH or CRITICAL findings:
- name: Check ZAP results
run: |
if grep -q '"risk":"High"\|"risk":"Critical"' zap_report.json; then
echo "High/Critical findings detected — merge blocked"
exit 1
fi
For production monitoring, run the AI QA Monkey free security scanner weekly to detect new SQLi-adjacent exposures (verbose error messages, debug endpoints, open database ports) that indicate increased risk.
Manual testing techniques
Automated scanners catch many SQLi patterns, but manual testing is required to identify logic-based injection, second-order injection, and application-specific vulnerabilities that automated tools miss.
Basic injection probes
Start with single-character probes that trigger syntax errors or behavioral changes without causing damage in staging environments:
# Probe payloads (use only in staging or with authorization)
# Single quote — triggers syntax error in vulnerable queries
https://example.com/users?id=1'
# Boolean-based blind — two responses should be different if vulnerable
https://example.com/users?id=1 AND 1=1 (true condition)
https://example.com/users?id=1 AND 1=2 (false condition)
# Comment terminator — truncates remainder of query
https://example.com/users?id=1--
https://example.com/users?id=1#
# UNION-based — enumerate columns
https://example.com/users?id=1 UNION SELECT NULL--
https://example.com/users?id=1 UNION SELECT NULL,NULL--
Time-based blind injection
When application responses are identical regardless of the query result, time-based techniques detect injection by measuring response delay:
# MySQL time-based blind
https://example.com/users?id=1 AND SLEEP(5)--
# PostgreSQL time-based blind
https://example.com/users?id=1; SELECT pg_sleep(5)--
# MSSQL time-based blind
https://example.com/users?id=1; WAITFOR DELAY '0:0:5'--
ORM-specific injection risks
Developers often assume ORM frameworks are immune to SQL injection. This is incorrect. Several ORM patterns create injection vulnerabilities despite the abstraction layer.
- Laravel
whereRaw(): Any raw query method in Eloquent that accepts user input without binding creates direct injection risk. Always usewhereRaw('column = ?', [$userInput])with bindings. - Django
extra()andRawSQL(): Theextra()method is deprecated partly because of injection risks. Useannotate()withRawSQLonly with validated, bound parameters. - ActiveRecord
where("condition = #{params}"): String interpolation in Railswhereclauses bypasses parameterization entirely. Usewhere("condition = ?", params[:value]). - Mongoose/MongoDB injection: NoSQL injection via JSON operator injection (
$where,$regex,$gt) is possible when user-controlled objects are passed directly to query methods without sanitization.
Recommended testing tools
- SQLMap: The industry-standard automated SQL injection detection and exploitation tool. Use with
--level=3 --risk=2for thorough coverage in staging. Never run against production without authorization. - Burp Suite Pro: Intercept and modify requests, use the active scanner, and manually test with the Repeater and Intruder tools for complex injection scenarios.
- OWASP ZAP: Free alternative with active scan capability. Useful for CI/CD integration via the ZAP API.
- AI QA Monkey: Run the free security scanner for automated detection of SQL injection indicators in your production application without needing internal access.
Retest and verification
After fixes, rerun the same test set and track closure evidence by endpoint. Keep a changelog of query-level fixes for future audits and customer security reviews.
Run a fast SQL injection exposure check
Scan your live domain for exploitable patterns and get prioritized remediation guidance.
Start Free Security ScanFrequently Asked Questions
What is the fastest way to reduce SQL injection risk?
Use parameterized queries globally, then enforce strict server-side input validation and least-privilege DB roles.
Is WAF enough by itself?
No. WAF is a compensating control, not a substitute for secure query implementation.
How often should teams retest?
At minimum monthly, plus before major releases and after backend query changes.