Problem: Manual Security Testing Misses Critical Vulnerabilities
Your application passed code review, but you don't have time for comprehensive penetration testing. Manual OWASP Top 10 checks take hours and miss edge cases that attackers exploit daily.
You'll learn:
- Use AI to generate realistic attack payloads for each OWASP vulnerability
- Automate detection of injection flaws, broken auth, and XSS
- Build a repeatable security test suite that runs in CI/CD
Time: 30 min | Level: Advanced
Why This Matters
The 2024-2025 OWASP Top 10 includes new risks like insecure design and SSRF. AI models excel at:
- Generating contextual attack payloads that bypass basic filters
- Finding logic flaws humans overlook
- Testing thousands of input combinations in seconds
Common symptoms of inadequate testing:
- SQL injection in "safe" parameterized queries with ORM bypasses
- XSS in markdown renderers or rich text editors
- Authentication bypasses through race conditions
- Exposed sensitive data in API responses
Solution
Step 1: Set Up AI-Powered Testing Tools
# Install security testing framework
pip install --break-system-packages aiohttp pytest pytest-asyncio
# Install AI security toolkit
pip install --break-system-packages openai anthropic langchain
# Install OWASP ZAP automation framework
docker pull zaproxy/zap-stable
Expected: All packages install without conflicts. Docker pulls ZAP image (~500MB).
Step 2: Create AI Payload Generator
# security_test_agent.py
import anthropic
import json
from typing import List, Dict
class OWASPTestGenerator:
def __init__(self, api_key: str):
self.client = anthropic.Anthropic(api_key=api_key)
def generate_attack_payloads(
self,
vulnerability_type: str,
target_context: Dict[str, str]
) -> List[str]:
"""
Generate contextual attack payloads for specific OWASP vulnerabilities.
Args:
vulnerability_type: One of 'sqli', 'xss', 'auth', 'injection', 'ssrf'
target_context: Dict with 'input_type', 'validation', 'framework'
Returns:
List of attack payloads to test
"""
prompt = f"""Generate 10 security test payloads for {vulnerability_type}.
Target context:
- Input type: {target_context.get('input_type', 'text')}
- Validation: {target_context.get('validation', 'none')}
- Framework: {target_context.get('framework', 'generic')}
Requirements:
1. Bypass common filters (regex, WAF rules)
2. Include edge cases (Unicode, encoding tricks)
3. Test logic flaws, not just injection
4. Return ONLY valid JSON array of strings
Example format: ["payload1", "payload2", ...]
"""
response = self.client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2000,
messages=[{"role": "user", "content": prompt}]
)
# Parse AI response as JSON
payloads_json = response.content[0].text
# Remove markdown code fences if present
if "```json" in payloads_json:
payloads_json = payloads_json.split("```json")[1].split("```")[0]
elif "```" in payloads_json:
payloads_json = payloads_json.split("```")[1].split("```")[0]
return json.loads(payloads_json.strip())
# Usage
generator = OWASPTestGenerator(api_key="your-api-key")
# A01:2021 – Broken Access Control
auth_payloads = generator.generate_attack_payloads(
vulnerability_type="auth",
target_context={
"input_type": "JWT token",
"validation": "signature check",
"framework": "Express.js + jsonwebtoken"
}
)
Why this works: Claude understands security contexts and generates payloads that exploit specific framework weaknesses, not just generic attacks.
Step 3: Test SQL Injection (A03:2021)
# test_sql_injection.py
import pytest
import aiohttp
import asyncio
from security_test_agent import OWASPTestGenerator
class TestSQLInjection:
@pytest.fixture
def payloads(self):
"""AI-generated SQLi payloads"""
generator = OWASPTestGenerator(api_key="your-key")
return generator.generate_attack_payloads(
vulnerability_type="sqli",
target_context={
"input_type": "search parameter",
"validation": "alphanumeric only",
"framework": "PostgreSQL with Sequelize ORM"
}
)
@pytest.mark.asyncio
async def test_search_sqli(self, payloads):
"""Test search endpoint for SQL injection"""
async with aiohttp.ClientSession() as session:
vulnerable = []
for payload in payloads:
async with session.get(
"http://localhost:3000/api/search",
params={"q": payload}
) as resp:
text = await resp.text()
# Check for SQLi indicators
if any(indicator in text.lower() for indicator in [
"sql syntax",
"postgres",
"pg::",
"column",
"relation",
"unexpected end"
]):
vulnerable.append({
"payload": payload,
"response": text[:200],
"status": resp.status
})
assert len(vulnerable) == 0, \
f"SQL injection found: {json.dumps(vulnerable, indent=2)}"
Expected: Tests fail if SQLi vulnerabilities exist, with exact payload and response.
If it fails:
- Error: "assert len(vulnerable) == 0": Fix the SQL injection before deploying
- Timeout errors: Add
timeout=aiohttp.ClientTimeout(total=10)to session - False positives: Refine error message detection in indicators list
Step 4: Test XSS (A03:2021 – Injection)
# test_xss.py
class TestXSS:
@pytest.fixture
def xss_payloads(self):
"""AI-generated XSS payloads for React apps"""
generator = OWASPTestGenerator(api_key="your-key")
return generator.generate_attack_payloads(
vulnerability_type="xss",
target_context={
"input_type": "comment field",
"validation": "DOMPurify sanitization",
"framework": "React 18 with dangerouslySetInnerHTML"
}
)
@pytest.mark.asyncio
async def test_comment_xss(self, xss_payloads):
"""Test if comments are properly sanitized"""
async with aiohttp.ClientSession() as session:
for payload in xss_payloads:
# Submit comment
async with session.post(
"http://localhost:3000/api/comments",
json={"content": payload, "post_id": 1}
) as resp:
comment_id = (await resp.json())["id"]
# Retrieve and check rendering
async with session.get(
f"http://localhost:3000/api/comments/{comment_id}"
) as resp:
data = await resp.json()
rendered = data["content"]
# Check if script tags or event handlers survived
dangerous_patterns = [
"<script",
"onerror=",
"onload=",
"javascript:",
"eval(",
"onclick="
]
if any(p in rendered.lower() for p in dangerous_patterns):
pytest.fail(
f"XSS vulnerability: {payload} -> {rendered}"
)
Why this approach works: Tests the actual rendered output, not just backend validation. Catches client-side XSS that server-side checks miss.
Step 5: Integrate with ZAP for Comprehensive Scanning
# automated_zap_scan.py
import subprocess
import json
import time
def run_zap_with_ai_context(target_url: str, ai_payloads: Dict[str, List[str]]):
"""
Run OWASP ZAP with AI-generated payloads for context-aware scanning.
"""
# Start ZAP daemon
zap_process = subprocess.Popen([
"docker", "run", "-u", "zap", "-p", "8080:8080",
"-i", "zaproxy/zap-stable",
"zap.sh", "-daemon", "-config", "api.disablekey=true"
])
time.sleep(15) # Wait for ZAP to start
try:
# Import AI-generated payloads
for vuln_type, payloads in ai_payloads.items():
for payload in payloads:
# Add to ZAP fuzzer
subprocess.run([
"curl", "-X", "POST",
f"http://localhost:8080/JSON/fuzzer/action/addPayload/",
"-d", f"category={vuln_type}&payload={payload}"
], check=True)
# Run active scan
subprocess.run([
"curl",
f"http://localhost:8080/JSON/ascan/action/scan/?url={target_url}"
], check=True)
# Wait for scan completion
while True:
result = subprocess.run([
"curl",
"http://localhost:8080/JSON/ascan/view/status/"
], capture_output=True, text=True)
status = json.loads(result.stdout)["status"]
if status == "100":
break
time.sleep(5)
# Get results
alerts = subprocess.run([
"curl",
"http://localhost:8080/JSON/core/view/alerts/"
], capture_output=True, text=True)
return json.loads(alerts.stdout)["alerts"]
finally:
zap_process.terminate()
# Usage
generator = OWASPTestGenerator(api_key="your-key")
all_payloads = {
"sqli": generator.generate_attack_payloads("sqli", {...}),
"xss": generator.generate_attack_payloads("xss", {...}),
"ssrf": generator.generate_attack_payloads("ssrf", {...})
}
vulnerabilities = run_zap_with_ai_context(
target_url="http://localhost:3000",
ai_payloads=all_payloads
)
print(f"Found {len(vulnerabilities)} vulnerabilities")
Step 6: Create CI/CD Integration
# .github/workflows/security-scan.yml
name: AI-Powered Security Scan
on:
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * 1' # Weekly Monday 2 AM
jobs:
owasp-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start application
run: |
docker compose up -d
sleep 10
- name: Run AI security tests
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
pip install -r requirements-security.txt
pytest tests/security/ -v --junitxml=results.xml
- name: Upload results
if: failure()
uses: actions/upload-artifact@v4
with:
name: security-test-results
path: results.xml
- name: Fail on vulnerabilities
if: failure()
run: exit 1
Expected: PR checks fail if any security tests detect vulnerabilities.
Verification
Test the Full Suite
# Run all security tests
pytest tests/security/ -v --tb=short
# Generate HTML report
pytest tests/security/ --html=security-report.html
# Test specific OWASP category
pytest tests/security/test_sql_injection.py -v
You should see:
tests/security/test_sql_injection.py::test_search_sqli PASSED
tests/security/test_xss.py::test_comment_xss PASSED
tests/security/test_auth.py::test_jwt_bypass PASSED
============ 15 passed in 24.3s ============
If tests fail: Review the failure output for exact payloads that succeeded. Fix the vulnerability before merging.
Complete OWASP Top 10 Coverage
Additional Test Cases
# test_auth_bypass.py
class TestBrokenAuthentication:
"""A07:2021 – Identification and Authentication Failures"""
@pytest.mark.asyncio
async def test_jwt_algorithm_confusion(self):
"""Test if JWT accepts 'none' algorithm"""
import jwt
# AI generates JWT manipulation payloads
generator = OWASPTestGenerator(api_key="key")
jwt_attacks = generator.generate_attack_payloads(
"auth",
{"input_type": "JWT", "validation": "HS256"}
)
for attack_jwt in jwt_attacks:
async with aiohttp.ClientSession() as session:
async with session.get(
"http://localhost:3000/api/profile",
headers={"Authorization": f"Bearer {attack_jwt}"}
) as resp:
assert resp.status == 401, \
f"JWT bypass with: {attack_jwt}"
# test_ssrf.py
class TestSSRF:
"""A10:2021 – Server-Side Request Forgery"""
@pytest.mark.asyncio
async def test_url_fetch_ssrf(self):
"""Test if URL fetcher accesses internal resources"""
ssrf_payloads = [
"http://169.254.169.254/latest/meta-data/", # AWS metadata
"http://localhost:8080/admin",
"http://[::1]:6379/", # Redis
"file:///etc/passwd",
"http://metadata.google.internal/" # GCP metadata
]
async with aiohttp.ClientSession() as session:
for payload in ssrf_payloads:
async with session.post(
"http://localhost:3000/api/fetch-url",
json={"url": payload}
) as resp:
text = await resp.text()
# Check if internal resource was accessed
forbidden_indicators = [
"ami-id",
"root:x:0",
"admin panel",
"redis_version"
]
if any(ind in text for ind in forbidden_indicators):
pytest.fail(f"SSRF vulnerability: {payload}")
What You Learned
- AI generates contextual attack payloads that bypass basic filters and target specific frameworks
- Automated security testing catches regressions that code review misses
- Combining AI payload generation with ZAP provides comprehensive OWASP coverage
- Running security tests in CI/CD prevents vulnerable code from reaching production
Limitations:
- AI may generate false positives requiring manual review
- Zero-day vulnerabilities not in training data won't be tested
- Logic flaws (A04:2021 Insecure Design) still need manual threat modeling
- Rate limiting and WAF detection may interfere with tests
When NOT to use this:
- Compliance audits requiring certified pen testing
- Highly regulated industries needing manual verification
- Production systems (use staging/test environments only)
Resources
OWASP References:
AI Security Tools:
Testing Frameworks:
Tested on Python 3.12, OWASP ZAP 2.14, Claude Sonnet 4, Ubuntu 24.04 LTS
Legal Notice: Only test applications you own or have written permission to test. Unauthorized security testing is illegal in most jurisdictions.