OWASP ZAP Home Lab
OWASP ZAP Home Lab Security Scanner Automated Scanning API Testing CI/CD Vulnerability Analysis OWASP Top 10 SQL Injection XSS CSRF Production
| Scan Type | Duration | Coverage | Use Case | Risk Detection |
|---|---|---|---|---|
| Baseline Scan | 1-2 min | Passive only | Every PR / commit | Low-Medium findings |
| Full Scan | 10-30 min | Active + Passive | Nightly / weekly | All risk levels |
| API Scan | 5-15 min | API endpoints | API changes | API-specific vulns |
| Ajax Spider | 10-20 min | SPA / JavaScript | Frontend changes | Client-side vulns |
| Authenticated Scan | 15-45 min | Behind login | Weekly | Auth-specific vulns |
Lab Setup with Docker
# === Docker Compose Home Lab ===
# docker-compose.yml
# version: '3.8'
# services:
# zap:
# image: owasp/zap2docker-stable
# ports:
# - "8080:8080"
# - "8090:8090"
# command: zap-webswing.sh
# networks:
# - security-lab
#
# dvwa:
# image: vulnerables/web-dvwa
# ports:
# - "8081:80"
# environment:
# MYSQL_DATABASE: dvwa
# networks:
# - security-lab
#
# juice-shop:
# image: bkimminich/juice-shop
# ports:
# - "3000:3000"
# networks:
# - security-lab
#
# webgoat:
# image: webgoat/webgoat
# ports:
# - "8082:8080"
# networks:
# - security-lab
#
# networks:
# security-lab:
# driver: bridge
# Start lab
# docker-compose up -d
# ZAP CLI Quick Scan
# docker run -t owasp/zap2docker-stable zap-baseline.py \
# -t http://dvwa:80 \
# -r report.html
# ZAP Full Scan
# docker run -t owasp/zap2docker-stable zap-full-scan.py \
# -t http://juice-shop:3000 \
# -r full-report.html \
# -J full-report.json
# ZAP API Scan
# docker run -t owasp/zap2docker-stable zap-api-scan.py \
# -t http://api-server:8000/openapi.json \
# -f openapi \
# -r api-report.html
from dataclasses import dataclass
@dataclass
class LabTarget:
name: str
image: str
port: int
purpose: str
difficulty: str
targets = [
LabTarget("DVWA", "vulnerables/web-dvwa", 8081,
"Classic vulnerable web app, adjustable difficulty", "Beginner"),
LabTarget("Juice Shop", "bkimminich/juice-shop", 3000,
"Modern OWASP Top 10, CTF challenges", "Beginner-Advanced"),
LabTarget("WebGoat", "webgoat/webgoat", 8082,
"Tutorial-style vulnerability learning", "Beginner"),
LabTarget("Mutillidae", "citizenstig/nowasp", 8083,
"OWASP Top 10 practice", "Intermediate"),
LabTarget("HackTheBox", "Custom VMs", 0,
"Real-world CTF challenges", "Advanced"),
]
print("=== Lab Targets ===")
for t in targets:
print(f" [{t.name}] Image: {t.image} | Port: {t.port}")
print(f" Purpose: {t.purpose}")
print(f" Difficulty: {t.difficulty}")
Automated Scanning
# === ZAP Automation Framework ===
# automation.yaml
# env:
# contexts:
# - name: "My App"
# urls: ["http://target:8080"]
# authentication:
# method: "form"
# parameters:
# loginUrl: "http://target:8080/login"
# loginRequestData: "username={%username%}&password={%password%}"
# verification:
# method: "response"
# loggedInRegex: "\\QWelcome\\E"
# users:
# - name: "test-user"
# credentials:
# username: "admin"
# password: "password"
#
# jobs:
# - type: spider
# parameters:
# context: "My App"
# user: "test-user"
# maxDuration: 5
# - type: spiderAjax
# parameters:
# context: "My App"
# maxDuration: 5
# - type: passiveScan-wait
# parameters:
# maxDuration: 10
# - type: activeScan
# parameters:
# context: "My App"
# user: "test-user"
# maxDuration: 30
# - type: report
# parameters:
# template: "traditional-html"
# reportDir: "/zap/reports/"
# reportFile: "scan-report"
# Run automation
# docker run -v $(pwd):/zap/wrk/:rw \
# owasp/zap2docker-stable \
# zap.sh -cmd -autorun /zap/wrk/automation.yaml
@dataclass
class VulnFinding:
risk: str
name: str
cwe: str
count: int
action: str
findings = [
VulnFinding("High", "SQL Injection", "CWE-89", 3,
"Use parameterized queries, input validation"),
VulnFinding("High", "Cross-Site Scripting (XSS)", "CWE-79", 5,
"Output encoding, Content Security Policy"),
VulnFinding("Medium", "Missing Security Headers", "CWE-693", 8,
"Add X-Frame-Options, CSP, HSTS headers"),
VulnFinding("Medium", "CSRF Token Missing", "CWE-352", 2,
"Implement anti-CSRF tokens"),
VulnFinding("Low", "Cookie without HttpOnly", "CWE-1004", 4,
"Set HttpOnly flag on session cookies"),
VulnFinding("Info", "Server Information Disclosure", "CWE-200", 1,
"Remove server version headers"),
]
print("\n=== Scan Findings ===")
for f in findings:
print(f" [{f.risk}] {f.name} (CWE: {f.cwe}) — {f.count} instances")
print(f" Action: {f.action}")
CI/CD Integration
# === GitHub Actions ZAP Scan ===
# .github/workflows/zap-scan.yml
# name: OWASP ZAP Security Scan
# on:
# pull_request:
# branches: [main]
# schedule:
# - cron: '0 2 * * *' # Nightly full scan
#
# jobs:
# baseline-scan:
# if: github.event_name == 'pull_request'
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Start application
# run: docker-compose up -d app
# - name: ZAP Baseline Scan
# uses: zaproxy/action-baseline@v0.10.0
# with:
# target: 'http://localhost:8080'
# rules_file_name: '.zap/rules.tsv'
# fail_action: 'true'
# - uses: actions/upload-artifact@v4
# with:
# name: zap-baseline-report
# path: report_html.html
#
# full-scan:
# if: github.event_name == 'schedule'
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Start application
# run: docker-compose up -d app
# - name: ZAP Full Scan
# uses: zaproxy/action-full-scan@v0.9.0
# with:
# target: 'http://localhost:8080'
# rules_file_name: '.zap/rules.tsv'
# - name: Send to Slack
# if: failure()
# uses: slackapi/slack-github-action@v1
# with:
# payload: '{"text": "ZAP Full Scan found vulnerabilities!"}'
# .zap/rules.tsv — Custom policy
# 10016 IGNORE (Web Browser XSS Protection Not Enabled)
# 10017 IGNORE (Cross-Domain JavaScript Source File Inclusion)
# 10021 WARN (X-Content-Type-Options Header Missing)
# 40012 FAIL (Cross Site Scripting - Reflected)
# 40014 FAIL (Cross Site Scripting - Persistent)
# 40018 FAIL (SQL Injection)
@dataclass
class CIPolicy:
risk: str
pr_action: str
nightly_action: str
sla: str
policies = [
CIPolicy("Critical", "Block merge", "Alert on-call + create P1 ticket", "Fix within 24 hours"),
CIPolicy("High", "Block merge", "Alert team + create P2 ticket", "Fix within 1 week"),
CIPolicy("Medium", "Warning comment", "Create P3 ticket", "Fix within 1 month"),
CIPolicy("Low", "Info only", "Log to dashboard", "Fix in next quarter"),
CIPolicy("Info", "Ignore", "Log to dashboard", "Best effort"),
]
print("CI/CD Security Policy:")
for p in policies:
print(f" [{p.risk}] PR: {p.pr_action} | Nightly: {p.nightly_action}")
print(f" SLA: {p.sla}")
เคล็ดลับ
- Baseline: เริ่มด้วย Baseline Scan ทุก PR เร็วและไม่ Intrusive
- Isolated: รัน Lab ใน Docker Network แยก ไม่ Scan ระบบอื่น
- Auth: ตั้ง Authentication Context สำหรับ Scan หลัง Login
- Policy: กำหนด Rules ว่า Finding ไหน FAIL ไหน WARN ไหน IGNORE
- Legal: Scan เฉพาะระบบที่ได้รับอนุญาต ไม่ Scan ระบบคนอื่น
OWASP ZAP คืออะไร
Open Source Security Scanner OWASP Active Passive Spider Fuzzer SQL Injection XSS CSRF OWASP Top 10 GUI CLI API CI/CD ฟรี
ตั้ง Home Lab อย่างไร
Docker Desktop ZAP DVWA Juice Shop WebGoat Docker Compose Network แยก Browser Proxy 8080 Certificate HTTPS Interception
Automated Scan ทำอย่างไร
CLI API zap-baseline.py 1-2 นาที zap-full-scan.py 10-30 นาที zap-api-scan.py OpenAPI Context Authentication Alert Threshold Report HTML JSON
ใช้ใน CI/CD อย่างไร
GitHub Actions GitLab CI Jenkins Docker owasp/zap2docker Baseline PR Full Nightly Report Slack Email Policy FAIL WARN IGNORE
สรุป
OWASP ZAP Home Lab Docker DVWA Juice Shop Automated Scanning Baseline Full API CI/CD GitHub Actions Policy Vulnerability OWASP Top 10 Production Security
