Initial commit
This commit is contained in:
444
skills/appsec/dast-zap/SKILL.md
Normal file
444
skills/appsec/dast-zap/SKILL.md
Normal file
@@ -0,0 +1,444 @@
|
||||
---
|
||||
name: dast-zap
|
||||
description: >
|
||||
Dynamic application security testing (DAST) using OWASP ZAP (Zed Attack Proxy) with passive and active scanning,
|
||||
API testing, and OWASP Top 10 vulnerability detection. Use when: (1) Performing runtime security testing of web
|
||||
applications and APIs, (2) Detecting vulnerabilities like XSS, SQL injection, and authentication flaws in deployed
|
||||
applications, (3) Automating security scans in CI/CD pipelines with Docker containers, (4) Conducting authenticated
|
||||
testing with session management, (5) Generating security reports with OWASP and CWE mappings for compliance.
|
||||
version: 0.1.0
|
||||
maintainer: SirAppSec
|
||||
category: appsec
|
||||
tags: [dast, zap, web-security, owasp, vulnerability-scanning, api-testing, penetration-testing]
|
||||
frameworks: [OWASP, CWE]
|
||||
dependencies:
|
||||
tools: [docker]
|
||||
optional: [python3, java]
|
||||
references:
|
||||
- https://www.zaproxy.org/docs/
|
||||
- https://www.zaproxy.org/docs/docker/
|
||||
- https://www.zaproxy.org/docs/desktop/start/features/
|
||||
---
|
||||
|
||||
# DAST with OWASP ZAP
|
||||
|
||||
## Overview
|
||||
|
||||
OWASP ZAP (Zed Attack Proxy) is an open-source DAST tool that acts as a manipulator-in-the-middle proxy to intercept,
|
||||
inspect, and test web application traffic for security vulnerabilities. ZAP provides automated passive and active
|
||||
scanning, API testing capabilities, and seamless CI/CD integration for runtime security testing.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Baseline Scan (Docker)
|
||||
|
||||
Run a quick passive security scan:
|
||||
|
||||
```bash
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py -t https://target-app.com -r baseline-report.html
|
||||
```
|
||||
|
||||
### Full Active Scan (Docker)
|
||||
|
||||
Perform comprehensive active vulnerability testing:
|
||||
|
||||
```bash
|
||||
docker run -t zaproxy/zap-stable zap-full-scan.py -t https://target-app.com -r full-scan-report.html
|
||||
```
|
||||
|
||||
### API Scan with OpenAPI Spec
|
||||
|
||||
Test APIs using OpenAPI/Swagger specification:
|
||||
|
||||
```bash
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.target.com \
|
||||
-f openapi \
|
||||
-d /zap/wrk/openapi-spec.yaml \
|
||||
-r /zap/wrk/api-report.html
|
||||
```
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Step 1: Define Scan Scope and Target
|
||||
|
||||
Identify the target application URL and define scope:
|
||||
|
||||
```bash
|
||||
# Set target URL
|
||||
TARGET_URL="https://target-app.com"
|
||||
|
||||
# For authenticated scans, prepare authentication context
|
||||
# See references/authentication_guide.md for detailed setup
|
||||
```
|
||||
|
||||
**Scope Considerations:**
|
||||
- Exclude third-party domains and CDN URLs
|
||||
- Include all application subdomains and API endpoints
|
||||
- Respect scope limitations in penetration testing engagements
|
||||
|
||||
### Step 2: Run Passive Scanning
|
||||
|
||||
Execute passive scanning to analyze traffic without active attacks:
|
||||
|
||||
```bash
|
||||
# Baseline scan performs spidering + passive scanning
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py \
|
||||
-t $TARGET_URL \
|
||||
-r baseline-report.html \
|
||||
-J baseline-report.json
|
||||
```
|
||||
|
||||
**What Passive Scanning Detects:**
|
||||
- Missing security headers (CSP, HSTS, X-Frame-Options)
|
||||
- Information disclosure in responses
|
||||
- Cookie security issues (HttpOnly, Secure flags)
|
||||
- Basic authentication weaknesses
|
||||
- Application fingerprinting data
|
||||
|
||||
### Step 3: Execute Active Scanning
|
||||
|
||||
Perform active vulnerability testing (requires authorization):
|
||||
|
||||
```bash
|
||||
# Full scan includes spidering + passive + active scanning
|
||||
docker run -t zaproxy/zap-stable zap-full-scan.py \
|
||||
-t $TARGET_URL \
|
||||
-r full-scan-report.html \
|
||||
-J full-scan-report.json \
|
||||
-z "-config api.addrs.addr.name=.* -config api.addrs.addr.regex=true"
|
||||
```
|
||||
|
||||
**Active Scanning Coverage:**
|
||||
- SQL Injection (SQLi)
|
||||
- Cross-Site Scripting (XSS)
|
||||
- Path Traversal
|
||||
- Command Injection
|
||||
- XML External Entity (XXE)
|
||||
- Server-Side Request Forgery (SSRF)
|
||||
- Security Misconfigurations
|
||||
|
||||
**WARNING:** Active scanning performs real attacks. Only run against applications you have explicit authorization to test.
|
||||
|
||||
### Step 4: Test APIs with Specifications
|
||||
|
||||
Scan REST, GraphQL, and SOAP APIs:
|
||||
|
||||
```bash
|
||||
# OpenAPI/Swagger API scan
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.target.com \
|
||||
-f openapi \
|
||||
-d /zap/wrk/openapi.yaml \
|
||||
-r /zap/wrk/api-report.html
|
||||
|
||||
# GraphQL API scan
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.target.com/graphql \
|
||||
-f graphql \
|
||||
-d /zap/wrk/schema.graphql \
|
||||
-r /zap/wrk/graphql-report.html
|
||||
```
|
||||
|
||||
Consult `references/api_testing_guide.md` for advanced API testing patterns including authentication and rate limiting.
|
||||
|
||||
### Step 5: Handle Authentication
|
||||
|
||||
For testing authenticated application areas:
|
||||
|
||||
```bash
|
||||
# Use bundled script for authentication setup
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target $TARGET_URL \
|
||||
--auth-type form \
|
||||
--login-url https://target-app.com/login \
|
||||
--username testuser \
|
||||
--password-env ZAP_AUTH_PASSWORD \
|
||||
--output auth-scan-report.html
|
||||
```
|
||||
|
||||
Authentication methods supported:
|
||||
- Form-based authentication
|
||||
- HTTP Basic/Digest authentication
|
||||
- OAuth 2.0 flows
|
||||
- API key/token authentication
|
||||
- Script-based custom authentication
|
||||
|
||||
See `references/authentication_guide.md` for detailed authentication configuration.
|
||||
|
||||
### Step 6: Analyze Results and Generate Reports
|
||||
|
||||
Review findings by risk level:
|
||||
|
||||
```bash
|
||||
# Generate multiple report formats
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-full-scan.py \
|
||||
-t $TARGET_URL \
|
||||
-r /zap/wrk/report.html \
|
||||
-J /zap/wrk/report.json \
|
||||
-x /zap/wrk/report.xml
|
||||
```
|
||||
|
||||
**Risk Levels:**
|
||||
- **High**: Critical vulnerabilities requiring immediate remediation (SQLi, RCE, authentication bypass)
|
||||
- **Medium**: Significant security weaknesses (XSS, CSRF, sensitive data exposure)
|
||||
- **Low**: Security concerns with lower exploitability (information disclosure, minor misconfigurations)
|
||||
- **Informational**: Security best practices and observations
|
||||
|
||||
Map findings to OWASP Top 10 using `references/owasp_mapping.md`.
|
||||
|
||||
## Automation & CI/CD Integration
|
||||
|
||||
### GitHub Actions Integration
|
||||
|
||||
Add ZAP scanning to GitHub workflows:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/zap-scan.yml
|
||||
name: ZAP Security Scan
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
zap_scan:
|
||||
runs-on: ubuntu-latest
|
||||
name: OWASP ZAP Baseline Scan
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: ZAP Baseline Scan
|
||||
uses: zaproxy/action-baseline@v0.7.0
|
||||
with:
|
||||
target: 'https://staging.target-app.com'
|
||||
rules_file_name: '.zap/rules.tsv'
|
||||
cmd_options: '-a'
|
||||
```
|
||||
|
||||
### Docker Automation Framework
|
||||
|
||||
Use YAML-based automation for advanced workflows:
|
||||
|
||||
```bash
|
||||
# Create automation config (see assets/zap_automation.yaml)
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable \
|
||||
zap.sh -cmd -autorun /zap/wrk/zap_automation.yaml
|
||||
```
|
||||
|
||||
The bundled `assets/zap_automation.yaml` template includes:
|
||||
- Environment configuration
|
||||
- Spider and AJAX spider settings
|
||||
- Passive and active scan policies
|
||||
- Authentication configuration
|
||||
- Report generation
|
||||
|
||||
### CI/CD Best Practices
|
||||
|
||||
- Use **baseline scans** for every commit/PR (low false positives)
|
||||
- Run **full scans** on staging environments before production deployment
|
||||
- Configure **API scans** for microservices and REST endpoints
|
||||
- Set **failure thresholds** to break builds on high-severity findings
|
||||
- Generate **SARIF reports** for GitHub Security tab integration
|
||||
|
||||
See `scripts/ci_integration.sh` for complete CI/CD integration examples.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Authorization**: Always obtain written authorization before scanning production systems or third-party applications
|
||||
- **Rate Limiting**: Configure scan speed to avoid overwhelming target applications or triggering DDoS protections
|
||||
- **Sensitive Data**: Never include production credentials in scan configurations; use environment variables or secrets management
|
||||
- **Scan Timing**: Run active scans during maintenance windows or against dedicated testing environments
|
||||
- **Legal Compliance**: Adhere to computer fraud and abuse laws; unauthorized scanning may be illegal
|
||||
- **Audit Logging**: Log all scan executions, targets, findings, and remediation actions for compliance audits
|
||||
- **Data Retention**: Sanitize scan reports before sharing; they may contain sensitive application data
|
||||
- **False Positives**: Manually verify findings before raising security incidents; DAST tools generate false positives
|
||||
|
||||
## Bundled Resources
|
||||
|
||||
### Scripts (`scripts/`)
|
||||
|
||||
- `zap_baseline_scan.sh` - Automated baseline scanning with configurable targets and reporting
|
||||
- `zap_full_scan.sh` - Comprehensive active scanning with exclusion rules
|
||||
- `zap_api_scan.py` - API testing with OpenAPI/GraphQL specification support
|
||||
- `zap_auth_scanner.py` - Authenticated scanning with multiple authentication methods
|
||||
- `ci_integration.sh` - CI/CD integration examples for Jenkins, GitLab CI, GitHub Actions
|
||||
|
||||
### References (`references/`)
|
||||
|
||||
- `authentication_guide.md` - Complete authentication configuration for form-based, OAuth, and token authentication
|
||||
- `owasp_mapping.md` - Mapping of ZAP alerts to OWASP Top 10 2021 and CWE classifications
|
||||
- `api_testing_guide.md` - Advanced API testing patterns for REST, GraphQL, SOAP, and WebSocket
|
||||
- `scan_policies.md` - Custom scan policy configuration for different application types
|
||||
- `false_positive_handling.md` - Common false positives and verification techniques
|
||||
|
||||
### Assets (`assets/`)
|
||||
|
||||
- `zap_automation.yaml` - Automation framework configuration template
|
||||
- `zap_context.xml` - Context configuration with authentication and session management
|
||||
- `scan_policy_modern_web.policy` - Scan policy optimized for modern JavaScript applications
|
||||
- `scan_policy_api.policy` - Scan policy for REST and GraphQL APIs
|
||||
- `github_action.yml` - GitHub Actions workflow template
|
||||
- `gitlab_ci.yml` - GitLab CI pipeline template
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern 1: Progressive Scanning (Speed vs. Coverage)
|
||||
|
||||
Start with fast scans and progressively increase depth:
|
||||
|
||||
```bash
|
||||
# Stage 1: Quick baseline scan (5-10 minutes)
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py -t $TARGET_URL -r baseline.html
|
||||
|
||||
# Stage 2: Full spider + passive scan (15-30 minutes)
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py -t $TARGET_URL -r baseline.html -c baseline-rules.tsv
|
||||
|
||||
# Stage 3: Targeted active scan on critical endpoints (1-2 hours)
|
||||
docker run -t zaproxy/zap-stable zap-full-scan.py -t $TARGET_URL -r full.html -c full-rules.tsv
|
||||
```
|
||||
|
||||
### Pattern 2: API-First Testing
|
||||
|
||||
Prioritize API security testing:
|
||||
|
||||
```bash
|
||||
# 1. Test API endpoints with specification
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.target.com -f openapi -d /zap/wrk/openapi.yaml -r /zap/wrk/api.html
|
||||
|
||||
# 2. Run active scan on discovered API endpoints
|
||||
# (ZAP automatically includes spidered API routes)
|
||||
|
||||
# 3. Test authentication flows
|
||||
python3 scripts/zap_auth_scanner.py --target https://api.target.com --auth-type bearer --token-env API_TOKEN
|
||||
```
|
||||
|
||||
### Pattern 3: Authenticated Web Application Testing
|
||||
|
||||
Test complete application including protected areas:
|
||||
|
||||
```bash
|
||||
# 1. Configure authentication context
|
||||
# See assets/zap_context.xml for template
|
||||
|
||||
# 2. Run authenticated scan
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://app.target.com \
|
||||
--auth-type form \
|
||||
--login-url https://app.target.com/login \
|
||||
--username testuser \
|
||||
--password-env APP_PASSWORD \
|
||||
--verification-url https://app.target.com/dashboard \
|
||||
--output authenticated-scan.html
|
||||
|
||||
# 3. Review session-specific vulnerabilities (CSRF, privilege escalation)
|
||||
```
|
||||
|
||||
### Pattern 4: CI/CD Security Gate
|
||||
|
||||
Implement ZAP as a security gate in deployment pipelines:
|
||||
|
||||
```bash
|
||||
# Run baseline scan and fail build on high-risk findings
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py \
|
||||
-t https://staging.target.com \
|
||||
-r baseline-report.html \
|
||||
-J baseline-report.json \
|
||||
--hook=scripts/ci_integration.sh
|
||||
|
||||
# Check exit code
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Security scan failed! High-risk vulnerabilities detected."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **CI/CD**: GitHub Actions, GitLab CI, Jenkins, Azure DevOps, CircleCI
|
||||
- **Issue Tracking**: Jira, GitHub Issues (via SARIF), ServiceNow
|
||||
- **Security Tools**: Defect Dojo (vulnerability management), SonarQube, OWASP Dependency-Check
|
||||
- **SDLC**: Pre-production testing phase, security regression testing, penetration testing preparation
|
||||
- **Authentication**: Integrates with OAuth providers, SAML, API gateways, custom authentication scripts
|
||||
- **Reporting**: HTML, JSON, XML, Markdown, SARIF (for GitHub Security), PDF (via custom scripts)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Docker Container Cannot Reach Target Application
|
||||
|
||||
**Solution**: For scanning applications running on localhost or in other containers:
|
||||
|
||||
```bash
|
||||
# Scanning host application from Docker container
|
||||
# Use docker0 bridge IP instead of localhost
|
||||
HOST_IP=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py -t http://$HOST_IP:8080
|
||||
|
||||
# Scanning between containers - create shared network
|
||||
docker network create zap-network
|
||||
docker run --network zap-network -t zaproxy/zap-stable zap-baseline.py -t http://app-container:8080
|
||||
```
|
||||
|
||||
### Issue: Scan Completes Too Quickly (Incomplete Coverage)
|
||||
|
||||
**Solution**: Increase spider depth and scan duration:
|
||||
|
||||
```bash
|
||||
# Configure spider to crawl deeper
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py \
|
||||
-t $TARGET_URL \
|
||||
-r report.html \
|
||||
-z "-config spider.maxDepth=10 -config spider.maxDuration=60"
|
||||
```
|
||||
|
||||
For JavaScript-heavy applications, use AJAX spider or Automation Framework.
|
||||
|
||||
### Issue: High False Positive Rate
|
||||
|
||||
**Solution**: Create custom scan policy and rules file:
|
||||
|
||||
```bash
|
||||
# Use bundled false positive handling guide
|
||||
# See references/false_positive_handling.md
|
||||
|
||||
# Generate rules file to suppress false positives
|
||||
# Format: alert_id URL_pattern parameter CWE_id WARN|IGNORE|FAIL
|
||||
echo "10202 https://target.com/static/.* .* 798 IGNORE" >> .zap/rules.tsv
|
||||
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py -t $TARGET_URL -c .zap/rules.tsv
|
||||
```
|
||||
|
||||
### Issue: Authentication Session Expires During Scan
|
||||
|
||||
**Solution**: Configure session re-authentication:
|
||||
|
||||
```bash
|
||||
# Use bundled authentication script with session monitoring
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target $TARGET_URL \
|
||||
--auth-type form \
|
||||
--login-url https://target.com/login \
|
||||
--username testuser \
|
||||
--password-env PASSWORD \
|
||||
--re-authenticate-on 401,403 \
|
||||
--verification-interval 300
|
||||
```
|
||||
|
||||
### Issue: Scan Triggering Rate Limiting or WAF Blocking
|
||||
|
||||
**Solution**: Reduce scan aggressiveness:
|
||||
|
||||
```bash
|
||||
# Slower scan with delays between requests
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py \
|
||||
-t $TARGET_URL \
|
||||
-r report.html \
|
||||
-z "-config scanner.threadPerHost=1 -config scanner.delayInMs=1000"
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [OWASP ZAP Documentation](https://www.zaproxy.org/docs/)
|
||||
- [ZAP Docker Documentation](https://www.zaproxy.org/docs/docker/)
|
||||
- [OWASP Top 10 2021](https://owasp.org/Top10/)
|
||||
- [ZAP Automation Framework](https://www.zaproxy.org/docs/automate/automation-framework/)
|
||||
- [GitHub Actions for ZAP](https://github.com/zaproxy/action-baseline)
|
||||
9
skills/appsec/dast-zap/assets/.gitkeep
Normal file
9
skills/appsec/dast-zap/assets/.gitkeep
Normal file
@@ -0,0 +1,9 @@
|
||||
# Assets Directory
|
||||
|
||||
Place files that will be used in the output Claude produces:
|
||||
- Templates
|
||||
- Configuration files
|
||||
- Images/logos
|
||||
- Boilerplate code
|
||||
|
||||
These files are NOT loaded into context but copied/modified in output.
|
||||
207
skills/appsec/dast-zap/assets/github_action.yml
Normal file
207
skills/appsec/dast-zap/assets/github_action.yml
Normal file
@@ -0,0 +1,207 @@
|
||||
# GitHub Actions Workflow for OWASP ZAP Security Scanning
|
||||
# Place this file in .github/workflows/zap-security-scan.yml
|
||||
|
||||
name: OWASP ZAP Security Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
# Run weekly security scans on Sunday at 2 AM
|
||||
- cron: '0 2 * * 0'
|
||||
workflow_dispatch: # Allow manual triggering
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write # For uploading SARIF reports
|
||||
issues: write # For creating security issues
|
||||
|
||||
jobs:
|
||||
zap-baseline-scan:
|
||||
name: ZAP Baseline Scan (PR/Push)
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' || github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run ZAP Baseline Scan
|
||||
uses: zaproxy/action-baseline@v0.10.0
|
||||
with:
|
||||
target: ${{ secrets.STAGING_URL }}
|
||||
rules_file_name: '.zap/rules.tsv'
|
||||
cmd_options: '-a -j'
|
||||
fail_action: true
|
||||
allow_issue_writing: false
|
||||
|
||||
- name: Upload ZAP Scan Report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: zap-baseline-report
|
||||
path: |
|
||||
report_html.html
|
||||
report_json.json
|
||||
retention-days: 30
|
||||
|
||||
- name: Create Issue on Failure
|
||||
if: failure()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: '🔒 ZAP Baseline Scan Found Security Issues',
|
||||
body: 'ZAP baseline scan detected security vulnerabilities. Please review the scan report in the workflow artifacts.',
|
||||
labels: ['security', 'automated']
|
||||
})
|
||||
|
||||
zap-full-scan:
|
||||
name: ZAP Full Active Scan (Staging)
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/develop' || github.event_name == 'schedule'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run ZAP Full Scan
|
||||
uses: zaproxy/action-full-scan@v0.8.0
|
||||
with:
|
||||
target: ${{ secrets.STAGING_URL }}
|
||||
rules_file_name: '.zap/rules.tsv'
|
||||
cmd_options: '-a -j -x report.xml'
|
||||
fail_action: true
|
||||
allow_issue_writing: true
|
||||
issue_title: 'ZAP Full Scan: Security Vulnerabilities Detected'
|
||||
|
||||
- name: Upload ZAP Full Scan Report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: zap-full-scan-report
|
||||
path: |
|
||||
report_html.html
|
||||
report_json.json
|
||||
report.xml
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload SARIF Report to GitHub Security
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: report.xml
|
||||
|
||||
zap-api-scan:
|
||||
name: ZAP API Scan
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run ZAP API Scan
|
||||
uses: zaproxy/action-api-scan@v0.6.0
|
||||
with:
|
||||
target: ${{ secrets.API_URL }}
|
||||
format: openapi
|
||||
api_spec_file: './openapi.yaml'
|
||||
cmd_options: '-a -j'
|
||||
fail_action: true
|
||||
|
||||
- name: Upload API Scan Report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: zap-api-scan-report
|
||||
path: |
|
||||
report_html.html
|
||||
report_json.json
|
||||
retention-days: 30
|
||||
|
||||
zap-authenticated-scan:
|
||||
name: ZAP Authenticated Scan
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Run Authenticated Scan
|
||||
env:
|
||||
APP_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
|
||||
TARGET_URL: ${{ secrets.STAGING_URL }}
|
||||
run: |
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target $TARGET_URL \
|
||||
--auth-type form \
|
||||
--login-url $TARGET_URL/login \
|
||||
--username testuser \
|
||||
--password-env APP_PASSWORD \
|
||||
--output ./authenticated-scan-report.html
|
||||
|
||||
- name: Upload Authenticated Scan Report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: zap-authenticated-scan-report
|
||||
path: authenticated-scan-report.*
|
||||
retention-days: 90
|
||||
|
||||
security-gate:
|
||||
name: Security Gate Check
|
||||
runs-on: ubuntu-latest
|
||||
needs: [zap-baseline-scan]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Download Scan Results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: zap-baseline-report
|
||||
|
||||
- name: Check Security Thresholds
|
||||
run: |
|
||||
# Install jq for JSON parsing
|
||||
sudo apt-get update && sudo apt-get install -y jq
|
||||
|
||||
# Count high and medium findings
|
||||
HIGH_COUNT=$(jq '[.site[].alerts[] | select(.risk == "High")] | length' report_json.json)
|
||||
MEDIUM_COUNT=$(jq '[.site[].alerts[] | select(.risk == "Medium")] | length' report_json.json)
|
||||
|
||||
echo "High risk findings: $HIGH_COUNT"
|
||||
echo "Medium risk findings: $MEDIUM_COUNT"
|
||||
|
||||
# Fail if thresholds exceeded
|
||||
if [ "$HIGH_COUNT" -gt 0 ]; then
|
||||
echo "❌ Security gate failed: $HIGH_COUNT high-risk vulnerabilities found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$MEDIUM_COUNT" -gt 10 ]; then
|
||||
echo "❌ Security gate failed: $MEDIUM_COUNT medium-risk vulnerabilities (max: 10)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Security gate passed"
|
||||
|
||||
- name: Post Summary
|
||||
if: always()
|
||||
run: |
|
||||
echo "## Security Scan Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Risk Level | Count |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|------------|-------|" >> $GITHUB_STEP_SUMMARY
|
||||
jq -r '.site[].alerts[] | .risk' report_json.json | sort | uniq -c | \
|
||||
awk '{print "| " $2 " | " $1 " |"}' >> $GITHUB_STEP_SUMMARY
|
||||
226
skills/appsec/dast-zap/assets/gitlab_ci.yml
Normal file
226
skills/appsec/dast-zap/assets/gitlab_ci.yml
Normal file
@@ -0,0 +1,226 @@
|
||||
# GitLab CI/CD Pipeline for OWASP ZAP Security Scanning
|
||||
# Add this to your .gitlab-ci.yml file
|
||||
|
||||
stages:
|
||||
- security
|
||||
- report
|
||||
|
||||
variables:
|
||||
ZAP_IMAGE: "zaproxy/zap-stable:latest"
|
||||
STAGING_URL: "https://staging.example.com"
|
||||
REPORTS_DIR: "security-reports"
|
||||
|
||||
# Baseline scan for all merge requests
|
||||
zap_baseline_scan:
|
||||
stage: security
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- mkdir -p $REPORTS_DIR
|
||||
- |
|
||||
docker run --rm \
|
||||
-v $(pwd)/$REPORTS_DIR:/zap/wrk/:rw \
|
||||
$ZAP_IMAGE \
|
||||
zap-baseline.py \
|
||||
-t $STAGING_URL \
|
||||
-r /zap/wrk/baseline-report.html \
|
||||
-J /zap/wrk/baseline-report.json \
|
||||
-w /zap/wrk/baseline-report.md \
|
||||
|| true
|
||||
- echo "Baseline scan completed"
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORTS_DIR/
|
||||
reports:
|
||||
junit: $REPORTS_DIR/baseline-report.xml
|
||||
expire_in: 1 week
|
||||
only:
|
||||
- merge_requests
|
||||
- develop
|
||||
- main
|
||||
tags:
|
||||
- docker
|
||||
|
||||
# Full active scan (manual trigger for staging)
|
||||
zap_full_scan:
|
||||
stage: security
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- mkdir -p $REPORTS_DIR
|
||||
- |
|
||||
docker run --rm \
|
||||
-v $(pwd)/$REPORTS_DIR:/zap/wrk/:rw \
|
||||
-v $(pwd)/.zap:/zap/config/:ro \
|
||||
$ZAP_IMAGE \
|
||||
zap-full-scan.py \
|
||||
-t $STAGING_URL \
|
||||
-c /zap/config/rules.tsv \
|
||||
-r /zap/wrk/full-scan-report.html \
|
||||
-J /zap/wrk/full-scan-report.json \
|
||||
-x /zap/wrk/full-scan-report.xml \
|
||||
|| true
|
||||
# Check for high-risk findings
|
||||
- |
|
||||
if command -v jq &> /dev/null; then
|
||||
HIGH_COUNT=$(jq '[.site[].alerts[] | select(.risk == "High")] | length' $REPORTS_DIR/full-scan-report.json)
|
||||
echo "High risk findings: $HIGH_COUNT"
|
||||
if [ "$HIGH_COUNT" -gt 0 ]; then
|
||||
echo "❌ Security scan failed: $HIGH_COUNT high-risk vulnerabilities"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORTS_DIR/
|
||||
expire_in: 4 weeks
|
||||
only:
|
||||
- develop
|
||||
when: manual
|
||||
allow_failure: false
|
||||
tags:
|
||||
- docker
|
||||
|
||||
# API security scan
|
||||
zap_api_scan:
|
||||
stage: security
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- mkdir -p $REPORTS_DIR
|
||||
- |
|
||||
if [ -f "openapi.yaml" ]; then
|
||||
docker run --rm \
|
||||
-v $(pwd)/$REPORTS_DIR:/zap/wrk/:rw \
|
||||
-v $(pwd):/zap/specs/:ro \
|
||||
$ZAP_IMAGE \
|
||||
zap-api-scan.py \
|
||||
-t $STAGING_URL \
|
||||
-f openapi \
|
||||
-d /zap/specs/openapi.yaml \
|
||||
-r /zap/wrk/api-scan-report.html \
|
||||
-J /zap/wrk/api-scan-report.json \
|
||||
|| true
|
||||
else
|
||||
echo "OpenAPI specification not found, skipping API scan"
|
||||
fi
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORTS_DIR/
|
||||
expire_in: 1 week
|
||||
only:
|
||||
- merge_requests
|
||||
- develop
|
||||
allow_failure: true
|
||||
tags:
|
||||
- docker
|
||||
|
||||
# Authenticated scan (requires test credentials)
|
||||
zap_authenticated_scan:
|
||||
stage: security
|
||||
image: python:3.11-slim
|
||||
before_script:
|
||||
- apt-get update && apt-get install -y docker.io
|
||||
script:
|
||||
- mkdir -p $REPORTS_DIR
|
||||
- |
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target $STAGING_URL \
|
||||
--auth-type form \
|
||||
--login-url $STAGING_URL/login \
|
||||
--username $TEST_USERNAME \
|
||||
--password-env TEST_PASSWORD \
|
||||
--output $REPORTS_DIR/authenticated-scan-report.html
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORTS_DIR/
|
||||
expire_in: 4 weeks
|
||||
only:
|
||||
- develop
|
||||
when: manual
|
||||
tags:
|
||||
- docker
|
||||
|
||||
# Security gate - check thresholds
|
||||
security_gate:
|
||||
stage: report
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache jq
|
||||
script:
|
||||
- |
|
||||
if [ -f "$REPORTS_DIR/baseline-report.json" ]; then
|
||||
HIGH_COUNT=$(jq '[.site[].alerts[] | select(.risk == "High")] | length' $REPORTS_DIR/baseline-report.json)
|
||||
MEDIUM_COUNT=$(jq '[.site[].alerts[] | select(.risk == "Medium")] | length' $REPORTS_DIR/baseline-report.json)
|
||||
|
||||
echo "==================================="
|
||||
echo "Security Scan Results"
|
||||
echo "==================================="
|
||||
echo "High risk findings: $HIGH_COUNT"
|
||||
echo "Medium risk findings: $MEDIUM_COUNT"
|
||||
echo "==================================="
|
||||
|
||||
# Fail on high-risk findings
|
||||
if [ "$HIGH_COUNT" -gt 0 ]; then
|
||||
echo "❌ Build failed: High-risk vulnerabilities detected"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Warn on medium-risk findings above threshold
|
||||
if [ "$MEDIUM_COUNT" -gt 10 ]; then
|
||||
echo "⚠️ Warning: $MEDIUM_COUNT medium-risk findings (threshold: 10)"
|
||||
fi
|
||||
|
||||
echo "✅ Security gate passed"
|
||||
else
|
||||
echo "No scan report found, skipping security gate"
|
||||
fi
|
||||
dependencies:
|
||||
- zap_baseline_scan
|
||||
only:
|
||||
- merge_requests
|
||||
- develop
|
||||
- main
|
||||
|
||||
# Generate consolidated report
|
||||
generate_report:
|
||||
stage: report
|
||||
image: alpine:latest
|
||||
before_script:
|
||||
- apk add --no-cache jq curl
|
||||
script:
|
||||
- |
|
||||
echo "# Security Scan Report" > $REPORTS_DIR/summary.md
|
||||
echo "" >> $REPORTS_DIR/summary.md
|
||||
echo "**Scan Date:** $(date)" >> $REPORTS_DIR/summary.md
|
||||
echo "**Target:** $STAGING_URL" >> $REPORTS_DIR/summary.md
|
||||
echo "" >> $REPORTS_DIR/summary.md
|
||||
echo "## Findings Summary" >> $REPORTS_DIR/summary.md
|
||||
echo "" >> $REPORTS_DIR/summary.md
|
||||
|
||||
if [ -f "$REPORTS_DIR/baseline-report.json" ]; then
|
||||
echo "| Risk Level | Count |" >> $REPORTS_DIR/summary.md
|
||||
echo "|------------|-------|" >> $REPORTS_DIR/summary.md
|
||||
jq -r '.site[].alerts[] | .risk' $REPORTS_DIR/baseline-report.json | \
|
||||
sort | uniq -c | awk '{print "| " $2 " | " $1 " |"}' >> $REPORTS_DIR/summary.md
|
||||
fi
|
||||
|
||||
cat $REPORTS_DIR/summary.md
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $REPORTS_DIR/summary.md
|
||||
expire_in: 4 weeks
|
||||
dependencies:
|
||||
- zap_baseline_scan
|
||||
only:
|
||||
- merge_requests
|
||||
- develop
|
||||
- main
|
||||
196
skills/appsec/dast-zap/assets/zap_automation.yaml
Normal file
196
skills/appsec/dast-zap/assets/zap_automation.yaml
Normal file
@@ -0,0 +1,196 @@
|
||||
# OWASP ZAP Automation Framework Configuration
|
||||
# Complete automation workflow for web application security testing
|
||||
|
||||
env:
|
||||
contexts:
|
||||
- name: WebApp-Security-Scan
|
||||
urls:
|
||||
- ${TARGET_URL}
|
||||
includePaths:
|
||||
- ${TARGET_URL}.*
|
||||
excludePaths:
|
||||
- .*logout.*
|
||||
- .*signout.*
|
||||
- .*\\.css
|
||||
- .*\\.js
|
||||
- .*\\.png
|
||||
- .*\\.jpg
|
||||
- .*\\.gif
|
||||
- .*\\.svg
|
||||
authentication:
|
||||
method: form
|
||||
parameters:
|
||||
loginUrl: ${LOGIN_URL}
|
||||
loginRequestData: username={%username%}&password={%password%}
|
||||
verification:
|
||||
method: response
|
||||
loggedInRegex: "\\QWelcome\\E"
|
||||
loggedOutRegex: "\\QLogin\\E"
|
||||
sessionManagement:
|
||||
method: cookie
|
||||
parameters:
|
||||
sessionCookieName: JSESSIONID
|
||||
users:
|
||||
- name: test-user
|
||||
credentials:
|
||||
username: ${TEST_USERNAME}
|
||||
password: ${TEST_PASSWORD}
|
||||
|
||||
parameters:
|
||||
failOnError: true
|
||||
failOnWarning: false
|
||||
progressToStdout: true
|
||||
|
||||
vars:
|
||||
target_url: ${TARGET_URL}
|
||||
api_key: ${ZAP_API_KEY}
|
||||
|
||||
jobs:
|
||||
# Environment setup
|
||||
- type: environment
|
||||
parameters:
|
||||
deleteGlobalAlerts: true
|
||||
updateAddOns: true
|
||||
|
||||
# Import OpenAPI specification (if available)
|
||||
- type: openapi
|
||||
parameters:
|
||||
apiFile: ${OPENAPI_SPEC_FILE}
|
||||
apiUrl: ${TARGET_URL}
|
||||
targetUrl: ${TARGET_URL}
|
||||
context: WebApp-Security-Scan
|
||||
optional: true
|
||||
|
||||
# Spider crawling
|
||||
- type: spider
|
||||
parameters:
|
||||
context: WebApp-Security-Scan
|
||||
user: test-user
|
||||
maxDuration: 10
|
||||
maxDepth: 5
|
||||
maxChildren: 10
|
||||
acceptCookies: true
|
||||
handleODataParametersVisited: true
|
||||
parseComments: true
|
||||
parseRobotsTxt: true
|
||||
parseSitemapXml: true
|
||||
parseSVNEntries: true
|
||||
parseGit: true
|
||||
postForm: true
|
||||
processForm: true
|
||||
requestWaitTime: 200
|
||||
|
||||
# AJAX Spider for JavaScript-heavy applications
|
||||
- type: spiderAjax
|
||||
parameters:
|
||||
context: WebApp-Security-Scan
|
||||
user: test-user
|
||||
maxDuration: 10
|
||||
maxCrawlDepth: 5
|
||||
numberOfBrowsers: 2
|
||||
browserId: firefox-headless
|
||||
clickDefaultElems: true
|
||||
clickElemsOnce: true
|
||||
eventWait: 1000
|
||||
reloadWait: 1000
|
||||
optional: true
|
||||
|
||||
# Wait for passive scanning to complete
|
||||
- type: passiveScan-wait
|
||||
parameters:
|
||||
maxDuration: 5
|
||||
|
||||
# Configure passive scan rules
|
||||
- type: passiveScan-config
|
||||
parameters:
|
||||
maxAlertsPerRule: 10
|
||||
scanOnlyInScope: true
|
||||
enableTags: true
|
||||
disableRules:
|
||||
- 10096 # Timestamp Disclosure (informational)
|
||||
|
||||
# Active scanning
|
||||
- type: activeScan
|
||||
parameters:
|
||||
context: WebApp-Security-Scan
|
||||
user: test-user
|
||||
policy: Default Policy
|
||||
maxRuleDurationInMins: 5
|
||||
maxScanDurationInMins: 30
|
||||
addQueryParam: false
|
||||
defaultPolicy: Default Policy
|
||||
delayInMs: 0
|
||||
handleAntiCSRFTokens: true
|
||||
injectPluginIdInHeader: false
|
||||
scanHeadersAllRequests: false
|
||||
threadPerHost: 2
|
||||
|
||||
# Wait for active scanning to complete
|
||||
- type: activeScan-wait
|
||||
|
||||
# Generate reports
|
||||
- type: report
|
||||
parameters:
|
||||
template: traditional-html
|
||||
reportDir: ${REPORT_DIR}
|
||||
reportFile: security-report.html
|
||||
reportTitle: Web Application Security Assessment
|
||||
reportDescription: Automated DAST scan using OWASP ZAP
|
||||
displayReport: false
|
||||
|
||||
- type: report
|
||||
parameters:
|
||||
template: traditional-json
|
||||
reportDir: ${REPORT_DIR}
|
||||
reportFile: security-report.json
|
||||
reportTitle: Web Application Security Assessment
|
||||
|
||||
- type: report
|
||||
parameters:
|
||||
template: traditional-xml
|
||||
reportDir: ${REPORT_DIR}
|
||||
reportFile: security-report.xml
|
||||
reportTitle: Web Application Security Assessment
|
||||
|
||||
- type: report
|
||||
parameters:
|
||||
template: sarif-json
|
||||
reportDir: ${REPORT_DIR}
|
||||
reportFile: security-report.sarif
|
||||
reportTitle: Web Application Security Assessment (SARIF)
|
||||
optional: true
|
||||
|
||||
# Alert filters (false positive suppression)
|
||||
alertFilters:
|
||||
- ruleId: 10021
|
||||
newRisk: Info
|
||||
url: ".*\\.css|.*\\.js|.*cdn\\..*"
|
||||
context: WebApp-Security-Scan
|
||||
|
||||
- ruleId: 10096
|
||||
newRisk: Info
|
||||
url: ".*api\\..*"
|
||||
parameter: "created_at|updated_at|timestamp"
|
||||
context: WebApp-Security-Scan
|
||||
|
||||
# Scan policies
|
||||
policies:
|
||||
- name: Default Policy
|
||||
defaultStrength: Medium
|
||||
defaultThreshold: Medium
|
||||
rules:
|
||||
- id: 40018 # SQL Injection
|
||||
strength: High
|
||||
threshold: Low
|
||||
- id: 40012 # Cross-Site Scripting (Reflected)
|
||||
strength: High
|
||||
threshold: Low
|
||||
- id: 40014 # Cross-Site Scripting (Persistent)
|
||||
strength: High
|
||||
threshold: Low
|
||||
- id: 90019 # Server-Side Code Injection
|
||||
strength: High
|
||||
threshold: Low
|
||||
- id: 90020 # Remote OS Command Injection
|
||||
strength: High
|
||||
threshold: Low
|
||||
192
skills/appsec/dast-zap/assets/zap_context.xml
Normal file
192
skills/appsec/dast-zap/assets/zap_context.xml
Normal file
@@ -0,0 +1,192 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
OWASP ZAP Authentication Context Template
|
||||
Configure this file for form-based, HTTP, or script-based authentication
|
||||
-->
|
||||
<configuration>
|
||||
<context>
|
||||
<!-- Context Name -->
|
||||
<name>WebApp-Auth-Context</name>
|
||||
<desc>Authentication context for web application security testing</desc>
|
||||
|
||||
<!-- Enable context -->
|
||||
<inscope>true</inscope>
|
||||
|
||||
<!-- URL Scope Definition -->
|
||||
<!-- Include all URLs under target domain -->
|
||||
<incregexes>https://app\.example\.com/.*</incregexes>
|
||||
|
||||
<!-- Exclude logout and static content -->
|
||||
<excregexes>https://app\.example\.com/logout</excregexes>
|
||||
<excregexes>https://app\.example\.com/signout</excregexes>
|
||||
<excregexes>https://app\.example\.com/static/.*</excregexes>
|
||||
<excregexes>.*\.css</excregexes>
|
||||
<excregexes>.*\.js</excregexes>
|
||||
<excregexes>.*\.png|.*\.jpg|.*\.gif</excregexes>
|
||||
|
||||
<!-- Technology Detection -->
|
||||
<tech>
|
||||
<include>Language</include>
|
||||
<include>Language.JavaScript</include>
|
||||
<include>OS</include>
|
||||
<include>OS.Linux</include>
|
||||
<include>WS</include>
|
||||
</tech>
|
||||
|
||||
<!-- Authentication Configuration -->
|
||||
<authentication>
|
||||
<!--
|
||||
Authentication Types:
|
||||
- formBasedAuthentication: Traditional login forms
|
||||
- httpAuthentication: HTTP Basic/Digest/NTLM
|
||||
- scriptBasedAuthentication: Custom authentication via script
|
||||
-->
|
||||
<type>formBasedAuthentication</type>
|
||||
|
||||
<!-- Form-Based Authentication -->
|
||||
<form>
|
||||
<!-- Login URL -->
|
||||
<loginurl>https://app.example.com/login</loginurl>
|
||||
|
||||
<!-- Login Request Body (POST parameters) -->
|
||||
<!-- Use {%username%} and {%password%} as placeholders -->
|
||||
<loginbody>username={%username%}&password={%password%}&csrf_token={%csrf_token%}</loginbody>
|
||||
|
||||
<!-- Login Page URL (where login form is displayed) -->
|
||||
<loginpageurl>https://app.example.com/login</loginpageurl>
|
||||
</form>
|
||||
|
||||
<!-- HTTP Authentication (uncomment if using) -->
|
||||
<!--
|
||||
<http>
|
||||
<realm>Protected Area</realm>
|
||||
<hostname>app.example.com</hostname>
|
||||
<port>443</port>
|
||||
</http>
|
||||
-->
|
||||
|
||||
<!-- Logged-In Indicator (regex pattern that appears when logged in) -->
|
||||
<!-- This helps ZAP determine if authentication succeeded -->
|
||||
<loggedin>\QWelcome,\E</loggedin>
|
||||
<!-- Alternative patterns:
|
||||
<loggedin>\QLogout\E</loggedin>
|
||||
<loggedin>\Qdashboard\E</loggedin>
|
||||
<loggedin>class="user-menu"</loggedin>
|
||||
-->
|
||||
|
||||
<!-- Logged-Out Indicator (regex pattern that appears when logged out) -->
|
||||
<loggedout>\QYou are not logged in\E</loggedout>
|
||||
<!-- Alternative patterns:
|
||||
<loggedout>\QLogin\E</loggedout>
|
||||
<loggedout>\QSign In\E</loggedout>
|
||||
-->
|
||||
|
||||
<!-- Poll URL for verification (optional) -->
|
||||
<pollurl>https://app.example.com/api/session/verify</pollurl>
|
||||
<polldata></polldata>
|
||||
<pollfreq>60</pollfreq>
|
||||
</authentication>
|
||||
|
||||
<!-- Session Management -->
|
||||
<sessionManagement>
|
||||
<!--
|
||||
Session Management Types:
|
||||
- cookieBasedSessionManagement: Session via cookies (most common)
|
||||
- httpAuthSessionManagement: HTTP authentication
|
||||
- scriptBasedSessionManagement: Custom session handling
|
||||
-->
|
||||
<type>cookieBasedSessionManagement</type>
|
||||
|
||||
<!-- Session cookies to monitor -->
|
||||
<sessioncookies>
|
||||
<cookie>JSESSIONID</cookie>
|
||||
<cookie>PHPSESSID</cookie>
|
||||
<cookie>sessionid</cookie>
|
||||
<cookie>session_token</cookie>
|
||||
</sessioncookies>
|
||||
</sessionManagement>
|
||||
|
||||
<!-- Test Users -->
|
||||
<users>
|
||||
<!-- User 1: Standard test user -->
|
||||
<user>
|
||||
<name>testuser</name>
|
||||
<enabled>true</enabled>
|
||||
<credentials>
|
||||
<credential>
|
||||
<name>username</name>
|
||||
<value>testuser</value>
|
||||
</credential>
|
||||
<credential>
|
||||
<name>password</name>
|
||||
<value>TestPassword123!</value>
|
||||
</credential>
|
||||
<!-- CSRF token (if needed) -->
|
||||
<!--
|
||||
<credential>
|
||||
<name>csrf_token</name>
|
||||
<value></value>
|
||||
</credential>
|
||||
-->
|
||||
</credentials>
|
||||
</user>
|
||||
|
||||
<!-- User 2: Admin user (if testing authorization) -->
|
||||
<user>
|
||||
<name>adminuser</name>
|
||||
<enabled>false</enabled>
|
||||
<credentials>
|
||||
<credential>
|
||||
<name>username</name>
|
||||
<value>adminuser</value>
|
||||
</credential>
|
||||
<credential>
|
||||
<name>password</name>
|
||||
<value>AdminPassword123!</value>
|
||||
</credential>
|
||||
</credentials>
|
||||
</user>
|
||||
</users>
|
||||
|
||||
<!-- Forced User Mode (for authorization testing) -->
|
||||
<!--
|
||||
Enables testing if authenticated user can access resources
|
||||
they shouldn't have access to
|
||||
-->
|
||||
<forcedUserMode>false</forcedUserMode>
|
||||
|
||||
<!-- Data Driven Nodes -->
|
||||
<!--
|
||||
For testing parameters with different values
|
||||
-->
|
||||
<datadrivennodes>
|
||||
<node>
|
||||
<name>user_id</name>
|
||||
<url>https://app.example.com/api/users/{user_id}</url>
|
||||
</node>
|
||||
</datadrivennodes>
|
||||
</context>
|
||||
|
||||
<!-- Global Exclude URLs (applied to all contexts) -->
|
||||
<globalexcludeurl>
|
||||
<regex>https://.*\.googleapis\.com/.*</regex>
|
||||
<regex>https://.*\.google-analytics\.com/.*</regex>
|
||||
<regex>https://.*\.googletagmanager\.com/.*</regex>
|
||||
<regex>https://cdn\..*</regex>
|
||||
</globalexcludeurl>
|
||||
|
||||
<!-- Anti-CSRF Token Configuration -->
|
||||
<anticsrf>
|
||||
<!-- Enable anti-CSRF token handling -->
|
||||
<enabled>true</enabled>
|
||||
|
||||
<!-- Token names to automatically detect and handle -->
|
||||
<tokennames>
|
||||
<tokenname>csrf_token</tokenname>
|
||||
<tokenname>csrftoken</tokenname>
|
||||
<tokenname>_csrf</tokenname>
|
||||
<tokenname>authenticity_token</tokenname>
|
||||
<tokenname>__RequestVerificationToken</tokenname>
|
||||
</tokennames>
|
||||
</anticsrf>
|
||||
</configuration>
|
||||
40
skills/appsec/dast-zap/references/EXAMPLE.md
Normal file
40
skills/appsec/dast-zap/references/EXAMPLE.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Reference Document Template
|
||||
|
||||
This file contains detailed reference material that Claude should load only when needed.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Section 1](#section-1)
|
||||
- [Section 2](#section-2)
|
||||
- [Security Standards](#security-standards)
|
||||
|
||||
## Section 1
|
||||
|
||||
Detailed information, schemas, or examples that are too large for SKILL.md.
|
||||
|
||||
## Section 2
|
||||
|
||||
Additional reference material.
|
||||
|
||||
## Security Standards
|
||||
|
||||
### OWASP Top 10
|
||||
|
||||
Reference relevant OWASP categories:
|
||||
- A01: Broken Access Control
|
||||
- A02: Cryptographic Failures
|
||||
- etc.
|
||||
|
||||
### CWE Mappings
|
||||
|
||||
Map to relevant Common Weakness Enumeration categories:
|
||||
- CWE-79: Cross-site Scripting
|
||||
- CWE-89: SQL Injection
|
||||
- etc.
|
||||
|
||||
### MITRE ATT&CK
|
||||
|
||||
Reference relevant tactics and techniques if applicable:
|
||||
- TA0001: Initial Access
|
||||
- T1190: Exploit Public-Facing Application
|
||||
- etc.
|
||||
475
skills/appsec/dast-zap/references/api_testing_guide.md
Normal file
475
skills/appsec/dast-zap/references/api_testing_guide.md
Normal file
@@ -0,0 +1,475 @@
|
||||
# ZAP API Security Testing Guide
|
||||
|
||||
Advanced guide for testing REST, GraphQL, SOAP, and WebSocket APIs using OWASP ZAP.
|
||||
|
||||
## Overview
|
||||
|
||||
Modern applications rely heavily on APIs. This guide covers comprehensive API security testing patterns using ZAP's API scanning capabilities.
|
||||
|
||||
## API Types Supported
|
||||
|
||||
- **REST APIs** (JSON, XML)
|
||||
- **GraphQL APIs**
|
||||
- **SOAP APIs** (WSDL-based)
|
||||
- **gRPC APIs**
|
||||
- **WebSocket APIs**
|
||||
|
||||
## REST API Testing
|
||||
|
||||
### Testing with OpenAPI/Swagger Specification
|
||||
|
||||
**Best Practice:** Always use API specifications when available for complete coverage.
|
||||
|
||||
```bash
|
||||
# Basic OpenAPI scan
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.example.com \
|
||||
-f openapi \
|
||||
-d /zap/wrk/openapi.yaml \
|
||||
-r /zap/wrk/api-report.html
|
||||
```
|
||||
|
||||
### Testing Without Specification (Spider-Based)
|
||||
|
||||
When no specification is available:
|
||||
|
||||
```bash
|
||||
# Use standard spider with API context
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-full-scan.py \
|
||||
-t https://api.example.com \
|
||||
-r /zap/wrk/api-report.html \
|
||||
-z "-config spider.parseComments=true -config spider.parseRobotsTxt=true"
|
||||
```
|
||||
|
||||
### Authentication Patterns
|
||||
|
||||
#### Bearer Token (JWT)
|
||||
|
||||
```bash
|
||||
# Obtain token first
|
||||
TOKEN=$(curl -X POST https://api.example.com/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"testuser","password":"password"}' \
|
||||
| jq -r '.access_token')
|
||||
|
||||
# Scan with authentication
|
||||
python3 scripts/zap_api_scan.py \
|
||||
--target https://api.example.com \
|
||||
--format openapi \
|
||||
--spec openapi.yaml \
|
||||
--header "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
#### API Key Authentication
|
||||
|
||||
```bash
|
||||
# API key in header
|
||||
python3 scripts/zap_api_scan.py \
|
||||
--target https://api.example.com \
|
||||
--format openapi \
|
||||
--spec openapi.yaml \
|
||||
--header "X-API-Key: your-api-key-here"
|
||||
|
||||
# API key in query parameter
|
||||
python3 scripts/zap_api_scan.py \
|
||||
--target https://api.example.com?api_key=your-api-key \
|
||||
--format openapi \
|
||||
--spec openapi.yaml
|
||||
```
|
||||
|
||||
### Common REST API Vulnerabilities
|
||||
|
||||
#### 1. Broken Object Level Authorization (BOLA)
|
||||
|
||||
**Detection:** Test access to resources belonging to other users.
|
||||
|
||||
**Manual Test:**
|
||||
```bash
|
||||
# Request resource with different user IDs
|
||||
curl -H "Authorization: Bearer $USER1_TOKEN" \
|
||||
https://api.example.com/users/123/profile
|
||||
|
||||
curl -H "Authorization: Bearer $USER2_TOKEN" \
|
||||
https://api.example.com/users/123/profile # Should be denied
|
||||
```
|
||||
|
||||
**ZAP Configuration:**
|
||||
Add authorization test scripts to detect BOLA.
|
||||
|
||||
#### 2. Mass Assignment
|
||||
|
||||
**Detection:** Send additional fields not in API specification.
|
||||
|
||||
**Test Payload:**
|
||||
```json
|
||||
{
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"is_admin": true, # Unauthorized field
|
||||
"role": "admin" # Unauthorized field
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Rate Limiting
|
||||
|
||||
**Detection:** Send multiple requests rapidly.
|
||||
|
||||
```bash
|
||||
# Test rate limiting
|
||||
for i in {1..100}; do
|
||||
curl https://api.example.com/endpoint -H "Authorization: Bearer $TOKEN"
|
||||
done
|
||||
```
|
||||
|
||||
**Expected:** HTTP 429 (Too Many Requests) after threshold.
|
||||
|
||||
## GraphQL API Testing
|
||||
|
||||
### Testing with GraphQL Schema
|
||||
|
||||
```bash
|
||||
# Scan GraphQL endpoint with schema
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.example.com/graphql \
|
||||
-f graphql \
|
||||
-d /zap/wrk/schema.graphql \
|
||||
-r /zap/wrk/graphql-report.html
|
||||
```
|
||||
|
||||
### GraphQL Introspection
|
||||
|
||||
**Check if introspection is enabled:**
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/graphql \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"query": "{ __schema { types { name } } }"}'
|
||||
```
|
||||
|
||||
**Security Note:** Disable introspection in production.
|
||||
|
||||
### GraphQL-Specific Vulnerabilities
|
||||
|
||||
#### 1. Query Depth/Complexity Attacks
|
||||
|
||||
**Malicious Query:**
|
||||
```graphql
|
||||
query {
|
||||
user {
|
||||
posts {
|
||||
comments {
|
||||
author {
|
||||
posts {
|
||||
comments {
|
||||
author {
|
||||
# ... deeply nested
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Mitigation:** Implement query depth/complexity limits.
|
||||
|
||||
#### 2. Batch Query Attacks
|
||||
|
||||
**Malicious Query:**
|
||||
```graphql
|
||||
query {
|
||||
user1: user(id: 1) { name email }
|
||||
user2: user(id: 2) { name email }
|
||||
# ... repeated hundreds of times
|
||||
user500: user(id: 500) { name email }
|
||||
}
|
||||
```
|
||||
|
||||
**Mitigation:** Limit batch query size.
|
||||
|
||||
#### 3. Field Suggestions
|
||||
|
||||
When introspection is disabled, test field suggestions:
|
||||
|
||||
```graphql
|
||||
query {
|
||||
user {
|
||||
nam # Intentional typo to trigger suggestions
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SOAP API Testing
|
||||
|
||||
### Testing with WSDL
|
||||
|
||||
```bash
|
||||
# SOAP API scan with WSDL
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.example.com/soap \
|
||||
-f soap \
|
||||
-d /zap/wrk/service.wsdl \
|
||||
-r /zap/wrk/soap-report.html
|
||||
```
|
||||
|
||||
### SOAP-Specific Vulnerabilities
|
||||
|
||||
#### 1. XML External Entity (XXE)
|
||||
|
||||
**Test Payload:**
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
|
||||
<soap:Envelope>
|
||||
<soap:Body>
|
||||
<login>
|
||||
<username>&xxe;</username>
|
||||
</login>
|
||||
</soap:Body>
|
||||
</soap:Envelope>
|
||||
```
|
||||
|
||||
#### 2. XML Injection
|
||||
|
||||
**Test Payload:**
|
||||
```xml
|
||||
<username>admin</username><role>admin</role></user><user><username>attacker</username>
|
||||
```
|
||||
|
||||
## WebSocket Testing
|
||||
|
||||
### Manual WebSocket Testing
|
||||
|
||||
ZAP can intercept WebSocket traffic:
|
||||
|
||||
1. Configure browser proxy to ZAP
|
||||
2. Connect to WebSocket endpoint
|
||||
3. Review messages in ZAP's WebSocket tab
|
||||
4. Manually craft malicious messages
|
||||
|
||||
### Common WebSocket Vulnerabilities
|
||||
|
||||
- **Message Injection:** Inject malicious payloads in WebSocket messages
|
||||
- **Authentication Bypass:** Test if authentication is required for WebSocket connections
|
||||
- **Message Tampering:** Modify messages in transit
|
||||
|
||||
## API Security Testing Checklist
|
||||
|
||||
### Authentication & Authorization
|
||||
|
||||
- [ ] Test unauthenticated access to protected endpoints
|
||||
- [ ] Test authorization bypass (access other users' data)
|
||||
- [ ] Test JWT token validation (expiration, signature)
|
||||
- [ ] Test API key validation
|
||||
- [ ] Test role-based access control (RBAC)
|
||||
|
||||
### Input Validation
|
||||
|
||||
- [ ] Test SQL injection in parameters
|
||||
- [ ] Test NoSQL injection (MongoDB, etc.)
|
||||
- [ ] Test command injection
|
||||
- [ ] Test XML injection (for SOAP APIs)
|
||||
- [ ] Test mass assignment vulnerabilities
|
||||
- [ ] Test parameter pollution
|
||||
|
||||
### Rate Limiting & DoS
|
||||
|
||||
- [ ] Verify rate limiting is enforced
|
||||
- [ ] Test resource exhaustion (large payloads)
|
||||
- [ ] Test query complexity limits (GraphQL)
|
||||
- [ ] Test batch request limits
|
||||
|
||||
### Data Exposure
|
||||
|
||||
- [ ] Check for sensitive data in responses
|
||||
- [ ] Test verbose error messages
|
||||
- [ ] Verify PII is properly protected
|
||||
- [ ] Check for data leakage in logs
|
||||
|
||||
### Transport Security
|
||||
|
||||
- [ ] Verify HTTPS is enforced
|
||||
- [ ] Test TLS configuration (strong ciphers only)
|
||||
- [ ] Check certificate validation
|
||||
- [ ] Verify HSTS header is set
|
||||
|
||||
### Business Logic
|
||||
|
||||
- [ ] Test state manipulation
|
||||
- [ ] Test payment flow manipulation
|
||||
- [ ] Test workflow bypass
|
||||
- [ ] Test negative values/amounts
|
||||
|
||||
## ZAP Automation for API Testing
|
||||
|
||||
### Automation Framework Configuration
|
||||
|
||||
`api_automation.yaml`:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
contexts:
|
||||
- name: API-Context
|
||||
urls:
|
||||
- https://api.example.com
|
||||
includePaths:
|
||||
- https://api.example.com/.*
|
||||
authentication:
|
||||
method: header
|
||||
parameters:
|
||||
header: Authorization
|
||||
value: "Bearer ${API_TOKEN}"
|
||||
|
||||
jobs:
|
||||
- type: openapi
|
||||
parameters:
|
||||
apiFile: /zap/wrk/openapi.yaml
|
||||
apiUrl: https://api.example.com
|
||||
targetUrl: https://api.example.com
|
||||
context: API-Context
|
||||
|
||||
- type: passiveScan-wait
|
||||
|
||||
- type: activeScan
|
||||
parameters:
|
||||
context: API-Context
|
||||
policy: API-Scan-Policy
|
||||
user: api-user
|
||||
|
||||
- type: report
|
||||
parameters:
|
||||
template: traditional-html
|
||||
reportDir: /zap/wrk/
|
||||
reportFile: api-security-report.html
|
||||
reportTitle: API Security Assessment
|
||||
```
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
export API_TOKEN="your-token-here"
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable \
|
||||
zap.sh -cmd -autorun /zap/wrk/api_automation.yaml
|
||||
```
|
||||
|
||||
## Custom API Scan Policies
|
||||
|
||||
### Create API-Optimized Scan Policy
|
||||
|
||||
Disable irrelevant checks for APIs:
|
||||
- Disable DOM XSS checks (no browser context)
|
||||
- Disable CSRF checks (stateless APIs)
|
||||
- Enable injection checks (SQL, NoSQL, Command)
|
||||
- Enable authentication/authorization checks
|
||||
|
||||
See `assets/scan_policy_api.policy` for pre-configured policy.
|
||||
|
||||
## API Testing Tools Integration
|
||||
|
||||
### Postman Integration
|
||||
|
||||
Export Postman collection to OpenAPI:
|
||||
|
||||
```bash
|
||||
# Use Postman's built-in export or newman
|
||||
newman run collection.json --export-collection openapi.yaml
|
||||
```
|
||||
|
||||
### cURL to OpenAPI Conversion
|
||||
|
||||
Use tools like `curl-to-openapi` to generate specs from cURL commands.
|
||||
|
||||
## Common API Testing Patterns
|
||||
|
||||
### Pattern 1: CRUD Operation Testing
|
||||
|
||||
Test all CRUD operations for each resource:
|
||||
|
||||
```bash
|
||||
# CREATE
|
||||
curl -X POST https://api.example.com/users \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{"username":"testuser"}'
|
||||
|
||||
# READ
|
||||
curl https://api.example.com/users/123 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# UPDATE
|
||||
curl -X PUT https://api.example.com/users/123 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-d '{"username":"updated"}'
|
||||
|
||||
# DELETE
|
||||
curl -X DELETE https://api.example.com/users/123 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### Pattern 2: Multi-User Testing
|
||||
|
||||
Test with different user roles:
|
||||
|
||||
```bash
|
||||
# Admin user
|
||||
export ADMIN_TOKEN="admin-token"
|
||||
python3 scripts/zap_api_scan.py --target https://api.example.com \
|
||||
--header "Authorization: Bearer $ADMIN_TOKEN"
|
||||
|
||||
# Regular user
|
||||
export USER_TOKEN="user-token"
|
||||
python3 scripts/zap_api_scan.py --target https://api.example.com \
|
||||
--header "Authorization: Bearer $USER_TOKEN"
|
||||
```
|
||||
|
||||
### Pattern 3: Versioned API Testing
|
||||
|
||||
Test all API versions:
|
||||
|
||||
```bash
|
||||
# v1
|
||||
python3 scripts/zap_api_scan.py --target https://api.example.com/v1 \
|
||||
--spec openapi-v1.yaml
|
||||
|
||||
# v2
|
||||
python3 scripts/zap_api_scan.py --target https://api.example.com/v2 \
|
||||
--spec openapi-v2.yaml
|
||||
```
|
||||
|
||||
## Troubleshooting API Scans
|
||||
|
||||
### Issue: OpenAPI Import Fails
|
||||
|
||||
**Solution:** Validate OpenAPI spec:
|
||||
|
||||
```bash
|
||||
# Use Swagger Editor or openapi-validator
|
||||
npx @apidevtools/swagger-cli validate openapi.yaml
|
||||
```
|
||||
|
||||
### Issue: Authentication Not Working
|
||||
|
||||
**Solution:** Test authentication manually first:
|
||||
|
||||
```bash
|
||||
curl -v https://api.example.com/protected-endpoint \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### Issue: Rate Limiting During Scan
|
||||
|
||||
**Solution:** Reduce scan speed:
|
||||
|
||||
```bash
|
||||
docker run -t zaproxy/zap-stable zap-api-scan.py \
|
||||
-t https://api.example.com -f openapi -d /zap/wrk/spec.yaml \
|
||||
-z "-config scanner.delayInMs=1000"
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [OWASP API Security Top 10](https://owasp.org/www-project-api-security/)
|
||||
- [REST API Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html)
|
||||
- [GraphQL Security](https://graphql.org/learn/authorization/)
|
||||
- [ZAP OpenAPI Add-on](https://www.zaproxy.org/docs/desktop/addons/openapi-support/)
|
||||
431
skills/appsec/dast-zap/references/authentication_guide.md
Normal file
431
skills/appsec/dast-zap/references/authentication_guide.md
Normal file
@@ -0,0 +1,431 @@
|
||||
# ZAP Authentication Configuration Guide
|
||||
|
||||
Comprehensive guide for configuring authenticated scanning in OWASP ZAP for form-based, token-based, and OAuth authentication.
|
||||
|
||||
## Overview
|
||||
|
||||
Authenticated scanning is critical for testing protected application areas that require login. ZAP supports multiple authentication methods:
|
||||
|
||||
- **Form-Based Authentication** - Traditional username/password login forms
|
||||
- **HTTP Authentication** - Basic, Digest, NTLM authentication
|
||||
- **Script-Based Authentication** - Custom authentication flows (OAuth, SAML)
|
||||
- **Token-Based Authentication** - Bearer tokens, API keys, JWT
|
||||
|
||||
## Form-Based Authentication
|
||||
|
||||
### Configuration Steps
|
||||
|
||||
1. **Identify Login Parameters**
|
||||
- Login URL
|
||||
- Username field name
|
||||
- Password field name
|
||||
- Submit button/action
|
||||
|
||||
2. **Create Authentication Context**
|
||||
|
||||
```bash
|
||||
# Use bundled script
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://app.example.com \
|
||||
--auth-type form \
|
||||
--login-url https://app.example.com/login \
|
||||
--username testuser \
|
||||
--password-env APP_PASSWORD \
|
||||
--verification-url https://app.example.com/dashboard \
|
||||
--output authenticated-scan-report.html
|
||||
```
|
||||
|
||||
3. **Configure Logged-In Indicator**
|
||||
|
||||
Specify a regex pattern that appears only when logged in:
|
||||
- Example: `Welcome, testuser`
|
||||
- Example: `<a href="/logout">Logout</a>`
|
||||
- Example: Check for presence of dashboard elements
|
||||
|
||||
### Manual Context Configuration
|
||||
|
||||
Create `auth-context.xml`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<context>
|
||||
<name>WebAppAuth</name>
|
||||
<desc>Authenticated scanning context</desc>
|
||||
<inscope>true</inscope>
|
||||
<incregexes>https://app\.example\.com/.*</incregexes>
|
||||
|
||||
<authentication>
|
||||
<type>formBasedAuthentication</type>
|
||||
<form>
|
||||
<loginurl>https://app.example.com/login</loginurl>
|
||||
<loginbody>username={%username%}&password={%password%}</loginbody>
|
||||
<loginpageurl>https://app.example.com/login</loginpageurl>
|
||||
</form>
|
||||
<loggedin>\QWelcome,\E</loggedin>
|
||||
<loggedout>\QYou are not logged in\E</loggedout>
|
||||
</authentication>
|
||||
|
||||
<users>
|
||||
<user>
|
||||
<name>testuser</name>
|
||||
<credentials>
|
||||
<credential>
|
||||
<name>username</name>
|
||||
<value>testuser</value>
|
||||
</credential>
|
||||
<credential>
|
||||
<name>password</name>
|
||||
<value>SecureP@ssw0rd</value>
|
||||
</credential>
|
||||
</credentials>
|
||||
<enabled>true</enabled>
|
||||
</user>
|
||||
</users>
|
||||
|
||||
<sessionManagement>
|
||||
<type>cookieBasedSessionManagement</type>
|
||||
</sessionManagement>
|
||||
</context>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
Run scan with context:
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v $(pwd):/zap/wrk/:rw \
|
||||
-t zaproxy/zap-stable \
|
||||
zap-full-scan.py \
|
||||
-t https://app.example.com \
|
||||
-n /zap/wrk/auth-context.xml \
|
||||
-r /zap/wrk/auth-report.html
|
||||
```
|
||||
|
||||
## Token-Based Authentication (Bearer Tokens)
|
||||
|
||||
### JWT/Bearer Token Configuration
|
||||
|
||||
1. **Obtain Authentication Token**
|
||||
|
||||
```bash
|
||||
# Example: Login to get token
|
||||
TOKEN=$(curl -X POST https://api.example.com/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"testuser","password":"password"}' \
|
||||
| jq -r '.token')
|
||||
```
|
||||
|
||||
2. **Configure ZAP to Include Token**
|
||||
|
||||
Use ZAP Replacer to add Authorization header:
|
||||
|
||||
```bash
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://api.example.com \
|
||||
--auth-type bearer \
|
||||
--token-env API_TOKEN \
|
||||
--output api-auth-scan.html
|
||||
```
|
||||
|
||||
### Manual Token Configuration
|
||||
|
||||
Using ZAP automation framework (`zap_automation.yaml`):
|
||||
|
||||
```yaml
|
||||
env:
|
||||
contexts:
|
||||
- name: API-Context
|
||||
urls:
|
||||
- https://api.example.com
|
||||
authentication:
|
||||
method: header
|
||||
parameters:
|
||||
header: Authorization
|
||||
value: "Bearer ${API_TOKEN}"
|
||||
sessionManagement:
|
||||
method: cookie
|
||||
|
||||
jobs:
|
||||
- type: spider
|
||||
parameters:
|
||||
context: API-Context
|
||||
user: api-user
|
||||
|
||||
- type: activeScan
|
||||
parameters:
|
||||
context: API-Context
|
||||
user: api-user
|
||||
```
|
||||
|
||||
## OAuth 2.0 Authentication
|
||||
|
||||
### Authorization Code Flow
|
||||
|
||||
1. **Manual Browser-Based Token Acquisition**
|
||||
|
||||
```bash
|
||||
# Step 1: Get authorization code (open in browser)
|
||||
https://oauth.example.com/authorize?
|
||||
client_id=YOUR_CLIENT_ID&
|
||||
redirect_uri=http://localhost:8080/callback&
|
||||
response_type=code&
|
||||
scope=openid profile
|
||||
|
||||
# Step 2: Exchange code for token
|
||||
TOKEN=$(curl -X POST https://oauth.example.com/token \
|
||||
-d "grant_type=authorization_code" \
|
||||
-d "code=AUTH_CODE_FROM_STEP_1" \
|
||||
-d "client_id=YOUR_CLIENT_ID" \
|
||||
-d "client_secret=YOUR_CLIENT_SECRET" \
|
||||
-d "redirect_uri=http://localhost:8080/callback" \
|
||||
| jq -r '.access_token')
|
||||
|
||||
# Step 3: Use token in ZAP scan
|
||||
export API_TOKEN="$TOKEN"
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://api.example.com \
|
||||
--auth-type bearer \
|
||||
--token-env API_TOKEN
|
||||
```
|
||||
|
||||
### Client Credentials Flow (Service-to-Service)
|
||||
|
||||
```bash
|
||||
# Obtain token using client credentials
|
||||
TOKEN=$(curl -X POST https://oauth.example.com/token \
|
||||
-d "grant_type=client_credentials" \
|
||||
-d "client_id=YOUR_CLIENT_ID" \
|
||||
-d "client_secret=YOUR_CLIENT_SECRET" \
|
||||
-d "scope=api.read api.write" \
|
||||
| jq -r '.access_token')
|
||||
|
||||
export API_TOKEN="$TOKEN"
|
||||
|
||||
# Run authenticated scan
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://api.example.com \
|
||||
--auth-type bearer \
|
||||
--token-env API_TOKEN
|
||||
```
|
||||
|
||||
## HTTP Basic/Digest Authentication
|
||||
|
||||
### Basic Authentication
|
||||
|
||||
```bash
|
||||
# Option 1: Using environment variable
|
||||
export BASIC_AUTH="dGVzdHVzZXI6cGFzc3dvcmQ=" # base64(testuser:password)
|
||||
|
||||
# Option 2: Using script
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://app.example.com \
|
||||
--auth-type http \
|
||||
--username testuser \
|
||||
--password-env HTTP_PASSWORD
|
||||
```
|
||||
|
||||
### Digest Authentication
|
||||
|
||||
Similar to Basic, but ZAP automatically handles the challenge-response:
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v $(pwd):/zap/wrk/:rw \
|
||||
-t zaproxy/zap-stable \
|
||||
zap-full-scan.py \
|
||||
-t https://app.example.com \
|
||||
-n /zap/wrk/digest-auth-context.xml \
|
||||
-r /zap/wrk/digest-auth-report.html
|
||||
```
|
||||
|
||||
## Session Management
|
||||
|
||||
### Cookie-Based Sessions
|
||||
|
||||
**Default Behavior:** ZAP automatically manages cookies.
|
||||
|
||||
**Custom Configuration:**
|
||||
- Set session cookie name in context
|
||||
- Configure session timeout
|
||||
- Define re-authentication triggers
|
||||
|
||||
### Token Refresh Handling
|
||||
|
||||
For tokens that expire during scan:
|
||||
|
||||
```yaml
|
||||
# zap_automation.yaml
|
||||
env:
|
||||
contexts:
|
||||
- name: API-Context
|
||||
authentication:
|
||||
method: script
|
||||
parameters:
|
||||
script: |
|
||||
// JavaScript to refresh token
|
||||
function authenticate(helper, paramsValues, credentials) {
|
||||
var loginUrl = "https://api.example.com/auth/login";
|
||||
var postData = '{"username":"' + credentials.getParam("username") +
|
||||
'","password":"' + credentials.getParam("password") + '"}';
|
||||
|
||||
var msg = helper.prepareMessage();
|
||||
msg.setRequestHeader("POST " + loginUrl + " HTTP/1.1");
|
||||
msg.setRequestBody(postData);
|
||||
helper.sendAndReceive(msg);
|
||||
|
||||
var response = msg.getResponseBody().toString();
|
||||
var token = JSON.parse(response).token;
|
||||
|
||||
// Store token for use in requests
|
||||
helper.getHttpSender().setRequestHeader("Authorization", "Bearer " + token);
|
||||
return msg;
|
||||
}
|
||||
```
|
||||
|
||||
## Verification and Troubleshooting
|
||||
|
||||
### Verify Authentication is Working
|
||||
|
||||
1. **Check Logged-In Indicator**
|
||||
|
||||
Run a spider scan and verify protected pages are accessed:
|
||||
|
||||
```bash
|
||||
# Look for dashboard, profile, or other authenticated pages in spider results
|
||||
```
|
||||
|
||||
2. **Monitor Authentication Requests**
|
||||
|
||||
Enable ZAP logging to see authentication attempts:
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v $(pwd):/zap/wrk/:rw \
|
||||
-e ZAP_LOG_LEVEL=DEBUG \
|
||||
-t zaproxy/zap-stable \
|
||||
zap-full-scan.py -t https://app.example.com -n /zap/wrk/context.xml
|
||||
```
|
||||
|
||||
3. **Test with Manual Request**
|
||||
|
||||
Send a manual authenticated request via ZAP GUI or API to verify credentials work.
|
||||
|
||||
### Common Authentication Issues
|
||||
|
||||
#### Issue: Session Expires During Scan
|
||||
|
||||
**Solution:** Configure re-authentication:
|
||||
|
||||
```python
|
||||
# In zap_auth_scanner.py, add re-authentication trigger
|
||||
--re-authenticate-on 401,403 \
|
||||
--verification-interval 300 # Check every 5 minutes
|
||||
```
|
||||
|
||||
#### Issue: CSRF Tokens Required
|
||||
|
||||
**Solution:** Use anti-CSRF token handling:
|
||||
|
||||
```yaml
|
||||
# zap_automation.yaml
|
||||
env:
|
||||
contexts:
|
||||
- name: WebApp
|
||||
authentication:
|
||||
verification:
|
||||
method: response
|
||||
loggedInRegex: "\\QWelcome\\E"
|
||||
sessionManagement:
|
||||
method: cookie
|
||||
parameters:
|
||||
antiCsrfTokens: true
|
||||
```
|
||||
|
||||
#### Issue: Rate Limiting Blocking Authentication
|
||||
|
||||
**Solution:** Slow down scan:
|
||||
|
||||
```bash
|
||||
docker run -t zaproxy/zap-stable zap-full-scan.py \
|
||||
-t https://app.example.com \
|
||||
-z "-config scanner.delayInMs=2000 -config scanner.threadPerHost=1"
|
||||
```
|
||||
|
||||
#### Issue: Multi-Step Login (MFA)
|
||||
|
||||
**Solution:** Use script-based authentication with Selenium or manual token acquisition.
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never Hardcode Credentials**
|
||||
- Use environment variables
|
||||
- Use secrets management tools (Vault, AWS Secrets Manager)
|
||||
|
||||
2. **Use Dedicated Test Accounts**
|
||||
- Create accounts specifically for security testing
|
||||
- Limit permissions to test data only
|
||||
- Monitor for abuse
|
||||
|
||||
3. **Rotate Credentials Regularly**
|
||||
- Change test account passwords after each scan
|
||||
- Rotate API tokens frequently
|
||||
|
||||
4. **Log Authentication Attempts**
|
||||
- Monitor for failed authentication attempts
|
||||
- Alert on unusual patterns
|
||||
|
||||
5. **Secure Context Files**
|
||||
- Never commit context files with credentials to version control
|
||||
- Use `.gitignore` to exclude `*.context` files
|
||||
- Encrypt context files at rest
|
||||
|
||||
## Examples by Framework
|
||||
|
||||
### Django Application
|
||||
|
||||
```bash
|
||||
# Django CSRF token handling
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://django-app.example.com \
|
||||
--auth-type form \
|
||||
--login-url https://django-app.example.com/accounts/login/ \
|
||||
--username testuser \
|
||||
--password-env DJANGO_PASSWORD \
|
||||
--verification-url https://django-app.example.com/dashboard/
|
||||
```
|
||||
|
||||
### Spring Boot Application
|
||||
|
||||
```bash
|
||||
# Spring Security form login
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://spring-app.example.com \
|
||||
--auth-type form \
|
||||
--login-url https://spring-app.example.com/login \
|
||||
--username testuser \
|
||||
--password-env SPRING_PASSWORD
|
||||
```
|
||||
|
||||
### React SPA with JWT
|
||||
|
||||
```bash
|
||||
# Get JWT from API, then scan
|
||||
TOKEN=$(curl -X POST https://api.example.com/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"test@example.com","password":"password"}' \
|
||||
| jq -r '.token')
|
||||
|
||||
export API_TOKEN="$TOKEN"
|
||||
|
||||
python3 scripts/zap_auth_scanner.py \
|
||||
--target https://spa.example.com \
|
||||
--auth-type bearer \
|
||||
--token-env API_TOKEN
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [ZAP Authentication Documentation](https://www.zaproxy.org/docs/desktop/start/features/authentication/)
|
||||
- [ZAP Session Management](https://www.zaproxy.org/docs/desktop/start/features/sessionmanagement/)
|
||||
- [OAuth 2.0 RFC 6749](https://tools.ietf.org/html/rfc6749)
|
||||
427
skills/appsec/dast-zap/references/false_positive_handling.md
Normal file
427
skills/appsec/dast-zap/references/false_positive_handling.md
Normal file
@@ -0,0 +1,427 @@
|
||||
# ZAP False Positive Handling Guide
|
||||
|
||||
Guide for identifying, verifying, and suppressing false positives in OWASP ZAP scan results.
|
||||
|
||||
## Overview
|
||||
|
||||
DAST tools like ZAP generate false positives - alerts for issues that aren't actually exploitable vulnerabilities. This guide helps you:
|
||||
|
||||
1. Identify common false positives
|
||||
2. Verify findings manually
|
||||
3. Suppress false positives in future scans
|
||||
4. Tune scan policies
|
||||
|
||||
## Common False Positives
|
||||
|
||||
### 1. X-Content-Type-Options Missing
|
||||
|
||||
**Alert:** Missing X-Content-Type-Options header
|
||||
|
||||
**False Positive Scenario:**
|
||||
- Static content served by CDNs
|
||||
- Third-party resources
|
||||
- Legacy browsers not supported
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
curl -I https://example.com/static/script.js
|
||||
# Check if browser performs MIME sniffing
|
||||
```
|
||||
|
||||
**When to Suppress:**
|
||||
- Static content only (CSS, JS, images)
|
||||
- Content served from trusted CDN
|
||||
- No user-controlled content in responses
|
||||
|
||||
**Suppression Rule:**
|
||||
```tsv
|
||||
10021 https://cdn.example.com/.* .* 693 IGNORE
|
||||
```
|
||||
|
||||
### 2. Cookie Without Secure Flag
|
||||
|
||||
**Alert:** Cookie without Secure flag set
|
||||
|
||||
**False Positive Scenario:**
|
||||
- Development/testing environments (HTTP)
|
||||
- Non-sensitive cookies (analytics, preferences)
|
||||
- Localhost testing
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
curl -I https://example.com
|
||||
# Check Set-Cookie headers
|
||||
# Verify if cookie contains sensitive data
|
||||
```
|
||||
|
||||
**When to Suppress:**
|
||||
- Non-sensitive cookies (theme preference, language)
|
||||
- HTTP-only development environments
|
||||
- Third-party analytics cookies
|
||||
|
||||
**Suppression Rule:**
|
||||
```tsv
|
||||
10054 https://example.com.* _ga|_gid|theme 614 WARN
|
||||
```
|
||||
|
||||
### 3. Cross-Domain JavaScript Source File Inclusion
|
||||
|
||||
**Alert:** JavaScript loaded from external domain
|
||||
|
||||
**False Positive Scenario:**
|
||||
- Legitimate CDN usage (jQuery, Bootstrap, etc.)
|
||||
- Third-party integrations (Google Analytics, Stripe)
|
||||
- Using Subresource Integrity (SRI)
|
||||
|
||||
**Verification:**
|
||||
```html
|
||||
<!-- Check if SRI is used -->
|
||||
<script src="https://cdn.example.com/library.js"
|
||||
integrity="sha384-HASH"
|
||||
crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
**When to Suppress:**
|
||||
- CDN resources with SRI
|
||||
- Trusted third-party services
|
||||
- Company-owned CDN domains
|
||||
|
||||
**Suppression Rule:**
|
||||
```tsv
|
||||
10017 https://example.com/.* https://cdn.jsdelivr.net/.* 829 IGNORE
|
||||
```
|
||||
|
||||
### 4. Timestamp Disclosure
|
||||
|
||||
**Alert:** Unix timestamps found in response
|
||||
|
||||
**False Positive Scenario:**
|
||||
- Legitimate timestamp fields in API responses
|
||||
- Non-sensitive metadata
|
||||
- Public timestamps (post dates, etc.)
|
||||
|
||||
**Verification:**
|
||||
```json
|
||||
{
|
||||
"created_at": 1640995200, // Legitimate field
|
||||
"post_date": "2022-01-01"
|
||||
}
|
||||
```
|
||||
|
||||
**When to Suppress:**
|
||||
- API responses with datetime fields
|
||||
- Public-facing timestamps
|
||||
- Non-sensitive metadata
|
||||
|
||||
**Suppression Rule:**
|
||||
```tsv
|
||||
10096 https://api.example.com/.* created_at|updated_at 200 IGNORE
|
||||
```
|
||||
|
||||
### 5. Server Version Disclosure
|
||||
|
||||
**Alert:** Server version exposed in headers
|
||||
|
||||
**False Positive Scenario:**
|
||||
- Behind WAF/load balancer (version is of proxy, not app server)
|
||||
- Generic server headers
|
||||
- Already public knowledge
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
curl -I https://example.com | grep Server
|
||||
# Check if version matches actual server
|
||||
```
|
||||
|
||||
**When to Suppress:**
|
||||
- Proxy/WAF version (not actual app server)
|
||||
- Generic headers without version numbers
|
||||
- When other compensating controls exist
|
||||
|
||||
**Suppression Rule:**
|
||||
```tsv
|
||||
10036 https://example.com.* .* 200 WARN
|
||||
```
|
||||
|
||||
## Verification Methodology
|
||||
|
||||
### Step 1: Understand the Alert
|
||||
|
||||
Review ZAP alert details:
|
||||
- **Description:** What is the potential vulnerability?
|
||||
- **Evidence:** What triggered the alert?
|
||||
- **CWE/OWASP Mapping:** What category does it fall under?
|
||||
- **Risk Level:** How severe is it?
|
||||
|
||||
### Step 2: Reproduce Manually
|
||||
|
||||
Attempt to exploit the vulnerability:
|
||||
|
||||
```bash
|
||||
# For XSS alerts
|
||||
curl "https://example.com/search?q=<script>alert(1)</script>"
|
||||
# Check if script is reflected unencoded
|
||||
|
||||
# For SQL injection alerts
|
||||
curl "https://example.com/api/user?id=1' OR '1'='1"
|
||||
# Check for SQL errors or unexpected behavior
|
||||
|
||||
# For path traversal alerts
|
||||
curl "https://example.com/download?file=../../etc/passwd"
|
||||
# Check if file is accessible
|
||||
```
|
||||
|
||||
### Step 3: Check Context
|
||||
|
||||
Consider the application context:
|
||||
- Is the functionality available to unauthenticated users?
|
||||
- Does it handle sensitive data?
|
||||
- Are there compensating controls (WAF, input validation)?
|
||||
|
||||
### Step 4: Document Decision
|
||||
|
||||
Create documentation for suppression decisions:
|
||||
|
||||
```markdown
|
||||
## Alert: SQL Injection in /api/user
|
||||
|
||||
**Decision:** False Positive
|
||||
|
||||
**Rationale:**
|
||||
- Endpoint requires authentication
|
||||
- Input is validated server-side (allowlist: 0-9 only)
|
||||
- WAF rule blocks SQL injection patterns
|
||||
- Manual testing confirmed no injection possible
|
||||
|
||||
**Suppressed:** Yes (Rule ID 40018, /api/user endpoint)
|
||||
|
||||
**Reviewed by:** security-team@example.com
|
||||
**Date:** 2024-01-15
|
||||
```
|
||||
|
||||
## Creating Suppression Rules
|
||||
|
||||
### Rules File Format
|
||||
|
||||
ZAP uses TSV (tab-separated values) format:
|
||||
|
||||
```
|
||||
alert_id URL_pattern parameter CWE_id action
|
||||
```
|
||||
|
||||
- **alert_id:** ZAP alert ID (e.g., 40018 for SQL Injection)
|
||||
- **URL_pattern:** Regex pattern for URL
|
||||
- **parameter:** Parameter name (or .* for all)
|
||||
- **CWE_id:** CWE identifier
|
||||
- **action:** IGNORE, WARN, or FAIL
|
||||
|
||||
### Example Rules File
|
||||
|
||||
`.zap/rules.tsv`:
|
||||
|
||||
```tsv
|
||||
# Suppress X-Content-Type-Options for CDN static content
|
||||
10021 https://cdn.example.com/static/.* .* 693 IGNORE
|
||||
|
||||
# Warn (don't fail) on analytics cookies without Secure flag
|
||||
10054 https://example.com/.* _ga|_gid 614 WARN
|
||||
|
||||
# Ignore timestamp disclosure in API responses
|
||||
10096 https://api.example.com/.* .* 200 IGNORE
|
||||
|
||||
# Ignore legitimate external JavaScript (with SRI)
|
||||
10017 https://example.com/.* https://cdn.jsdelivr.net/.* 829 IGNORE
|
||||
|
||||
# Suppress CSRF warnings for stateless API
|
||||
10202 https://api.example.com/.* .* 352 IGNORE
|
||||
```
|
||||
|
||||
### Using Rules File
|
||||
|
||||
```bash
|
||||
# Baseline scan with rules
|
||||
docker run -t zaproxy/zap-stable zap-baseline.py \
|
||||
-t https://example.com \
|
||||
-c .zap/rules.tsv \
|
||||
-r report.html
|
||||
|
||||
# Full scan with rules
|
||||
docker run -v $(pwd):/zap/wrk/:rw -t zaproxy/zap-stable zap-full-scan.py \
|
||||
-t https://example.com \
|
||||
-c /zap/wrk/.zap/rules.tsv \
|
||||
-r /zap/wrk/report.html
|
||||
```
|
||||
|
||||
## Custom Scan Policies
|
||||
|
||||
### Disable Entire Scan Rules
|
||||
|
||||
Create custom scan policy to disable problematic rules:
|
||||
|
||||
1. **Via ZAP GUI:**
|
||||
- Analyze > Scan Policy Manager
|
||||
- Create new policy
|
||||
- Disable specific rules
|
||||
- Export policy file
|
||||
|
||||
2. **Via Automation Framework:**
|
||||
|
||||
```yaml
|
||||
# zap_automation.yaml
|
||||
jobs:
|
||||
- type: activeScan
|
||||
parameters:
|
||||
policy: Custom-Policy
|
||||
rules:
|
||||
- id: 40018 # SQL Injection
|
||||
threshold: MEDIUM
|
||||
strength: HIGH
|
||||
- id: 10202 # CSRF
|
||||
threshold: OFF # Disable completely
|
||||
```
|
||||
|
||||
## Handling Different Alert Types
|
||||
|
||||
### High-Risk Alerts (Never Suppress Without Verification)
|
||||
|
||||
- SQL Injection
|
||||
- Command Injection
|
||||
- Remote Code Execution
|
||||
- Authentication Bypass
|
||||
- Server-Side Request Forgery (SSRF)
|
||||
|
||||
**Process:**
|
||||
1. Manual verification required
|
||||
2. Security team review
|
||||
3. Document compensating controls
|
||||
4. Re-test after fixes
|
||||
|
||||
### Medium-Risk Alerts (Contextual Suppression)
|
||||
|
||||
- XSS (if output is properly encoded)
|
||||
- CSRF (if tokens are implemented)
|
||||
- Missing headers (if compensating controls exist)
|
||||
|
||||
**Process:**
|
||||
1. Verify finding
|
||||
2. Check for compensating controls
|
||||
3. Document decision
|
||||
4. Suppress with WARN (not IGNORE)
|
||||
|
||||
### Low-Risk Alerts (Can Be Suppressed)
|
||||
|
||||
- Informational headers
|
||||
- Timestamp disclosure
|
||||
- Technology fingerprinting
|
||||
|
||||
**Process:**
|
||||
1. Quick verification
|
||||
2. Document reason
|
||||
3. Suppress with IGNORE
|
||||
|
||||
## Quality Assurance
|
||||
|
||||
### Review Suppression Rules Regularly
|
||||
|
||||
```bash
|
||||
# Monthly review checklist
|
||||
- [ ] Review all suppression rules for continued relevance
|
||||
- [ ] Check if suppressed issues have been fixed
|
||||
- [ ] Verify compensating controls are still in place
|
||||
- [ ] Update rules file with new false positives
|
||||
```
|
||||
|
||||
### Track Suppression Metrics
|
||||
|
||||
Monitor suppression trends:
|
||||
|
||||
```bash
|
||||
# Count suppressions by alert type
|
||||
grep -v '^#' .zap/rules.tsv | awk '{print $1}' | sort | uniq -c
|
||||
|
||||
# Alert if suppression count increases significantly
|
||||
```
|
||||
|
||||
### Peer Review Process
|
||||
|
||||
Require security team approval for suppressing high-risk alerts:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/security-review.yml
|
||||
- name: Check for new suppressions
|
||||
run: |
|
||||
git diff origin/main .zap/rules.tsv > suppressions.diff
|
||||
if [ -s suppressions.diff ]; then
|
||||
echo "New suppressions require security team review"
|
||||
# Notify security team
|
||||
fi
|
||||
```
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
### ❌ Don't Suppress Everything
|
||||
|
||||
Never create blanket suppression rules:
|
||||
|
||||
```tsv
|
||||
# BAD: Suppresses all XSS findings
|
||||
40012 .* .* 79 IGNORE
|
||||
```
|
||||
|
||||
### ❌ Don't Suppress Without Documentation
|
||||
|
||||
Always document why a finding is suppressed:
|
||||
|
||||
```tsv
|
||||
# BAD: No context
|
||||
10054 https://example.com/.* session_id 614 IGNORE
|
||||
|
||||
# GOOD: Documented reason
|
||||
# Session cookie is HTTPS-only in production; suppressing for staging environment
|
||||
10054 https://staging.example.com/.* session_id 614 IGNORE
|
||||
```
|
||||
|
||||
### ❌ Don't Ignore High-Risk Findings
|
||||
|
||||
Never suppress critical vulnerabilities without thorough investigation:
|
||||
|
||||
```tsv
|
||||
# DANGEROUS: Never suppress SQL injection without verification
|
||||
40018 https://example.com/.* .* 89 IGNORE
|
||||
```
|
||||
|
||||
## Tools and Scripts
|
||||
|
||||
### Analyze ZAP JSON Report
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import sys
|
||||
|
||||
with open('report.json') as f:
|
||||
report = json.load(f)
|
||||
|
||||
false_positives = []
|
||||
for site in report['site']:
|
||||
for alert in site['alerts']:
|
||||
if alert['risk'] in ['High', 'Medium']:
|
||||
print(f"{alert['alert']} - {alert['risk']}")
|
||||
print(f" URL: {alert['url']}")
|
||||
print(f" Evidence: {alert.get('evidence', 'N/A')}")
|
||||
print()
|
||||
```
|
||||
|
||||
### Generate Suppression Rules Template
|
||||
|
||||
```bash
|
||||
# Extract unique alert IDs from report
|
||||
jq -r '.site[].alerts[] | "\(.pluginid)\t\(.url)\t.*\t\(.cweid)\tWARN"' report.json \
|
||||
| sort -u > rules-template.tsv
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [ZAP Alert Details](https://www.zaproxy.org/docs/alerts/)
|
||||
- [ZAP Scan Rules](https://www.zaproxy.org/docs/docker/baseline-scan/)
|
||||
- [OWASP Testing Guide](https://owasp.org/www-project-web-security-testing-guide/)
|
||||
255
skills/appsec/dast-zap/references/owasp_mapping.md
Normal file
255
skills/appsec/dast-zap/references/owasp_mapping.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# OWASP ZAP Alert Mapping to OWASP Top 10 2021 and CWE
|
||||
|
||||
This reference maps common OWASP ZAP alerts to OWASP Top 10 2021 categories and CWE (Common Weakness Enumeration) identifiers for compliance and reporting.
|
||||
|
||||
## OWASP Top 10 2021 Coverage
|
||||
|
||||
### A01:2021 - Broken Access Control
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Path Traversal (CWE-22)
|
||||
- Directory Browsing (CWE-548)
|
||||
- Cross-Domain Misconfiguration (CWE-346)
|
||||
- Bypassing Access Controls (CWE-284)
|
||||
|
||||
**Risk Level:** High to Medium
|
||||
|
||||
**Remediation:**
|
||||
- Implement proper access control checks on server-side
|
||||
- Use allowlists for file access patterns
|
||||
- Disable directory listing
|
||||
- Enforce CORS policies strictly
|
||||
|
||||
### A02:2021 - Cryptographic Failures
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Weak SSL/TLS Ciphers (CWE-327)
|
||||
- Cookie Without Secure Flag (CWE-614)
|
||||
- Password Autocomplete (CWE-522)
|
||||
- Sensitive Information in URL (CWE-598)
|
||||
|
||||
**Risk Level:** High to Medium
|
||||
|
||||
**Remediation:**
|
||||
- Use TLS 1.2+ with strong cipher suites
|
||||
- Set Secure and HttpOnly flags on all cookies
|
||||
- Disable autocomplete for sensitive fields
|
||||
- Never transmit sensitive data in URLs
|
||||
|
||||
### A03:2021 - Injection
|
||||
|
||||
**ZAP Alerts:**
|
||||
- SQL Injection (CWE-89)
|
||||
- Cross-Site Scripting (XSS) (CWE-79)
|
||||
- Command Injection (CWE-78)
|
||||
- LDAP Injection (CWE-90)
|
||||
- XML Injection (CWE-91)
|
||||
- XPath Injection (CWE-643)
|
||||
|
||||
**Risk Level:** High
|
||||
|
||||
**Remediation:**
|
||||
- Use parameterized queries (prepared statements)
|
||||
- Implement context-aware output encoding
|
||||
- Validate and sanitize all user input
|
||||
- Use allowlists for input validation
|
||||
- Implement Content Security Policy (CSP)
|
||||
|
||||
### A04:2021 - Insecure Design
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Application Error Disclosure (CWE-209)
|
||||
- Insufficient Anti-automation (CWE-799)
|
||||
- Missing Rate Limiting
|
||||
|
||||
**Risk Level:** Medium to Low
|
||||
|
||||
**Remediation:**
|
||||
- Implement proper error handling (generic error messages)
|
||||
- Add CAPTCHA or rate limiting for sensitive operations
|
||||
- Design security controls during architecture phase
|
||||
- Implement anti-automation measures
|
||||
|
||||
### A05:2021 - Security Misconfiguration
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Missing Security Headers (CWE-693)
|
||||
- X-Content-Type-Options
|
||||
- X-Frame-Options (CWE-1021)
|
||||
- Content-Security-Policy
|
||||
- Strict-Transport-Security (HSTS)
|
||||
- Server Leaks Information (CWE-200)
|
||||
- Default Credentials
|
||||
- Unnecessary HTTP Methods Enabled (CWE-650)
|
||||
|
||||
**Risk Level:** Medium to Low
|
||||
|
||||
**Remediation:**
|
||||
- Configure all security headers properly
|
||||
- Remove server version headers
|
||||
- Disable unnecessary HTTP methods (PUT, DELETE, TRACE)
|
||||
- Change default credentials
|
||||
- Implement minimal privilege principle
|
||||
|
||||
### A06:2021 - Vulnerable and Outdated Components
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Outdated Software Version Detected
|
||||
- Known Vulnerable Components (requires integration with CVE databases)
|
||||
|
||||
**Risk Level:** High to Medium
|
||||
|
||||
**Remediation:**
|
||||
- Maintain software inventory
|
||||
- Regularly update dependencies and libraries
|
||||
- Subscribe to security advisories
|
||||
- Use dependency scanning tools (OWASP Dependency-Check, Snyk)
|
||||
|
||||
### A07:2021 - Identification and Authentication Failures
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Weak Authentication (CWE-287)
|
||||
- Session Fixation (CWE-384)
|
||||
- Session ID in URL Rewrite (CWE-598)
|
||||
- Cookie No HttpOnly Flag (CWE-1004)
|
||||
- Credential Enumeration (CWE-209)
|
||||
|
||||
**Risk Level:** High
|
||||
|
||||
**Remediation:**
|
||||
- Implement multi-factor authentication (MFA)
|
||||
- Use secure session management
|
||||
- Regenerate session IDs after login
|
||||
- Set HttpOnly and Secure flags on session cookies
|
||||
- Implement account lockout mechanisms
|
||||
- Use generic error messages for authentication failures
|
||||
|
||||
### A08:2021 - Software and Data Integrity Failures
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Missing Subresource Integrity (SRI) (CWE-353)
|
||||
- Insecure Deserialization (CWE-502)
|
||||
|
||||
**Risk Level:** High to Medium
|
||||
|
||||
**Remediation:**
|
||||
- Implement Subresource Integrity for CDN resources
|
||||
- Avoid deserializing untrusted data
|
||||
- Use digital signatures for critical data
|
||||
- Implement integrity checks
|
||||
|
||||
### A09:2021 - Security Logging and Monitoring Failures
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Authentication attempts not logged
|
||||
- No monitoring of security events
|
||||
|
||||
**Risk Level:** Low (detection issue, not vulnerability)
|
||||
|
||||
**Remediation:**
|
||||
- Log all authentication attempts
|
||||
- Monitor for security anomalies
|
||||
- Implement centralized logging
|
||||
- Set up alerts for suspicious activities
|
||||
|
||||
### A10:2021 - Server-Side Request Forgery (SSRF)
|
||||
|
||||
**ZAP Alerts:**
|
||||
- Server-Side Request Forgery (CWE-918)
|
||||
- External Redirect (CWE-601)
|
||||
|
||||
**Risk Level:** High
|
||||
|
||||
**Remediation:**
|
||||
- Validate and sanitize all URLs
|
||||
- Use allowlists for allowed domains
|
||||
- Disable unnecessary URL schemas (file://, gopher://)
|
||||
- Implement network segmentation
|
||||
|
||||
## ZAP Alert ID to OWASP/CWE Quick Reference
|
||||
|
||||
| Alert ID | Alert Name | OWASP 2021 | CWE | Risk |
|
||||
|----------|-----------|------------|-----|------|
|
||||
| 40018 | SQL Injection | A03 | CWE-89 | High |
|
||||
| 40012 | Cross-Site Scripting (Reflected) | A03 | CWE-79 | High |
|
||||
| 40014 | Cross-Site Scripting (Persistent) | A03 | CWE-79 | High |
|
||||
| 40013 | Cross-Site Scripting (DOM) | A03 | CWE-79 | High |
|
||||
| 6 | Path Traversal | A01 | CWE-22 | High |
|
||||
| 7 | Remote File Inclusion | A01 | CWE-98 | High |
|
||||
| 90019 | Server-Side Code Injection | A03 | CWE-94 | High |
|
||||
| 90020 | Remote OS Command Injection | A03 | CWE-78 | High |
|
||||
| 90033 | Loosely Scoped Cookie | A07 | CWE-565 | Medium |
|
||||
| 10021 | X-Content-Type-Options Missing | A05 | CWE-693 | Low |
|
||||
| 10020 | X-Frame-Options Missing | A05 | CWE-1021 | Medium |
|
||||
| 10038 | Content Security Policy Missing | A05 | CWE-693 | Medium |
|
||||
| 10035 | Strict-Transport-Security Missing | A05 | CWE-319 | Low |
|
||||
| 10054 | Cookie Without Secure Flag | A02 | CWE-614 | Medium |
|
||||
| 10010 | Cookie No HttpOnly Flag | A07 | CWE-1004 | Medium |
|
||||
| 10098 | Cross-Domain Misconfiguration | A01 | CWE-346 | Medium |
|
||||
| 10055 | CSP Scanner: Wildcard Directive | A05 | CWE-693 | Medium |
|
||||
| 10096 | Timestamp Disclosure | A05 | CWE-200 | Low |
|
||||
| 10049 | Weak Authentication Method | A07 | CWE-287 | Medium |
|
||||
| 40029 | Server-Side Request Forgery | A10 | CWE-918 | High |
|
||||
|
||||
## Risk Level Priority Matrix
|
||||
|
||||
### High Risk (Immediate Action Required)
|
||||
- SQL Injection
|
||||
- Remote Code Execution
|
||||
- Authentication Bypass
|
||||
- SSRF
|
||||
- XXE (XML External Entity)
|
||||
|
||||
### Medium Risk (Fix in Current Sprint)
|
||||
- XSS (Cross-Site Scripting)
|
||||
- CSRF (Cross-Site Request Forgery)
|
||||
- Missing Security Headers (CSP, X-Frame-Options)
|
||||
- Insecure Cookie Configuration
|
||||
- Path Traversal (with limited impact)
|
||||
|
||||
### Low Risk (Fix in Backlog)
|
||||
- Information Disclosure (version headers)
|
||||
- Missing Informational Headers
|
||||
- Timestamp Disclosure
|
||||
- Autocomplete on Form Fields
|
||||
|
||||
### Informational (Documentation/Awareness)
|
||||
- Server Technology Disclosure
|
||||
- Application Error Messages
|
||||
- Charset Mismatch
|
||||
|
||||
## Compliance Mapping
|
||||
|
||||
### PCI-DSS 3.2.1
|
||||
- **Requirement 6.5.1** (Injection): SQL Injection, Command Injection, XSS
|
||||
- **Requirement 6.5.3** (Insecure Cryptography): Weak SSL/TLS, Insecure Cookies
|
||||
- **Requirement 6.5.7** (XSS): All XSS variants
|
||||
- **Requirement 6.5.8** (Access Control): Path Traversal, Broken Access Control
|
||||
- **Requirement 6.5.10** (Authentication): Weak Authentication, Session Management
|
||||
|
||||
### NIST 800-53
|
||||
- **AC-3** (Access Enforcement): Path Traversal, Authorization Issues
|
||||
- **IA-5** (Authenticator Management): Weak Authentication
|
||||
- **SC-8** (Transmission Confidentiality): Missing HTTPS, Weak TLS
|
||||
- **SI-10** (Information Input Validation): All Injection Flaws
|
||||
|
||||
### GDPR
|
||||
- **Article 32** (Security of Processing): All High/Medium findings affecting data security
|
||||
- **Article 25** (Data Protection by Design): Security Misconfigurations
|
||||
|
||||
## Usage in Reports
|
||||
|
||||
When generating compliance reports, reference this mapping to:
|
||||
|
||||
1. **Categorize findings** by OWASP Top 10 category
|
||||
2. **Assign CWE IDs** for standardized vulnerability classification
|
||||
3. **Map to compliance requirements** for audit trails
|
||||
4. **Prioritize remediation** based on risk level and compliance impact
|
||||
5. **Track metrics** by OWASP category over time
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [OWASP Top 10 2021](https://owasp.org/Top10/)
|
||||
- [CWE Top 25](https://cwe.mitre.org/top25/)
|
||||
- [ZAP Alert Details](https://www.zaproxy.org/docs/alerts/)
|
||||
- [OWASP Testing Guide](https://owasp.org/www-project-web-security-testing-guide/)
|
||||
Reference in New Issue
Block a user