OWASP ZAP Troubleshooting
OWASP ZAP Troubleshooting Security Scanner Proxy Authentication Spider Active Scan CI/CD False Positive Performance
| ปัญหา | สาเหตุ | วิธีแก้ | ความยาก |
|---|---|---|---|
| Proxy ไม่ทำงาน | Port 8080 ชนกับ App อื่น | เปลี่ยน Port ใน Options → Local Proxies | ง่าย |
| SSL Certificate Error | Browser ไม่ Trust ZAP CA | Export ZAP CA → Import ใน Browser | ง่าย |
| Auth Fail | Login Config ผิด | ตั้ง Context Authentication ใหม่ | กลาง |
| Spider ไม่ครบ | SPA/JS rendering | ใช้ Ajax Spider + Import Sitemap | กลาง |
| Scan ช้า | Thread น้อย Rule มาก | เพิ่ม Thread ลด Rule ที่ไม่จำเป็น | ง่าย |
| False Positive มาก | Default Threshold ต่ำ | ปรับ Scan Policy Threshold | กลาง |
Proxy & SSL Setup
# === ZAP Proxy Configuration ===
# เปลี่ยน Proxy Port (ถ้า 8080 ชน)
# ZAP → Options → Local Proxies → Port: 8090
#
# Export ZAP CA Certificate
# ZAP → Options → Dynamic SSL Certificates → Save
# ไฟล์: owasp_zap_root_ca.cer
#
# Import CA ใน Chrome
# Settings → Privacy → Security → Manage Certificates
# → Trusted Root CA → Import → เลือก owasp_zap_root_ca.cer
#
# Import CA ใน Firefox
# Settings → Privacy → View Certificates → Authorities
# → Import → เลือก owasp_zap_root_ca.cer → Trust for websites
#
# ตั้ง Browser Proxy
# HTTP Proxy: localhost:8090 (หรือ Port ที่ตั้ง)
# HTTPS Proxy: localhost:8090
# หรือใช้ FoxyProxy Extension สะดวกกว่า
# Command line proxy
# curl -x http://localhost:8090 https://target.com
# export HTTP_PROXY=http://localhost:8090
# export HTTPS_PROXY=http://localhost:8090
from dataclasses import dataclass
@dataclass
class ProxyIssue:
issue: str
symptom: str
cause: str
fix: str
verify: str
issues = [
ProxyIssue("Port Conflict",
"ZAP เริ่มไม่ได้ หรือ Browser เชื่อมต่อไม่ได้",
"Port 8080 ถูกใช้โดย Tomcat Jenkins หรือ App อื่น",
"เปลี่ยน Port เป็น 8090 หรือ Port ว่าง",
"netstat -an | findstr 8090 ต้องเห็น LISTENING"),
ProxyIssue("SSL Error",
"Browser แสดง SEC_ERROR_UNKNOWN_ISSUER",
"Browser ไม่ Trust ZAP CA Certificate",
"Export ZAP CA → Import ใน Browser Trusted Root CA",
"เปิด HTTPS เว็บผ่าน ZAP Proxy ไม่มี Warning"),
ProxyIssue("Connection Refused",
"ERR_PROXY_CONNECTION_FAILED",
"ZAP ไม่ได้รัน หรือ Proxy ตั้งผิด Port",
"ตรวจว่า ZAP รันอยู่ Port ตรงกัน",
"curl -x http://localhost:8090 http://example.com"),
ProxyIssue("Slow Browsing",
"เว็บโหลดช้ามากเมื่อผ่าน ZAP Proxy",
"Passive Scan ทำงานหนัก หรือ Break Point เปิดอยู่",
"ปิด Break Point ลด Passive Scan Rules",
"เปรียบเทียบความเร็วกับและไม่กับ Proxy"),
]
print("=== Proxy Issues ===")
for i in issues:
print(f" [{i.issue}] Symptom: {i.symptom}")
print(f" Cause: {i.cause}")
print(f" Fix: {i.fix}")
print(f" Verify: {i.verify}")
Authentication Setup
# === Authentication Configuration ===
# ZAP Authentication Context Setup
# 1. Right-click site → Include in Context → New Context
# 2. Context → Authentication:
# Method: Form-based Authentication
# Login Form Target URL: https://target.com/login
# Login Request POST Data: username={%username%}&password={%password%}
# Username Parameter: username
# Password Parameter: password
# 3. Context → Authentication → Verification Strategy:
# Logged In Indicator: \QLogout\E (regex)
# Logged Out Indicator: \QLogin\E (regex)
# 4. Context → Users → Add:
# Username: testuser
# Password: testpass123
# 5. Context → Session Management:
# Cookie-based Session Management
# API Authentication (Bearer Token)
# ZAP → Options → Replacer → Add Rule:
# Match Type: Request Header
# Match String: Authorization
# Replacement: Bearer eyJhbGciOiJIUzI1NiIs...
# Initiators: All
# Script Authentication (complex login)
# ZAP → Scripts → Authentication → New Script
# function authenticate(helper, paramsValues, credentials) {
# var loginUrl = "https://target.com/api/login";
# var msg = helper.prepareMessage();
# msg.setRequestHeader(new HttpRequestHeader(
# HttpRequestHeader.POST, new URI(loginUrl, false), "1.1"));
# msg.setRequestBody('{"email":"' + credentials.getParam("username") +
# '","password":"' + credentials.getParam("password") + '"}');
# helper.sendAndReceive(msg, false);
# return msg;
# }
@dataclass
class AuthMethod:
method: str
use_case: str
setup: str
common_issue: str
fix: str
methods = [
AuthMethod("Form-based",
"Traditional login form (POST username/password)",
"Context → Auth → Form-based → Login URL + POST Data",
"Login Indicator ไม่ตรง ZAP คิดว่า Logout แล้ว",
"ใช้ Regex ที่เฉพาะเจาะจง เช่น \\QLogout\\E"),
AuthMethod("Header-based (API)",
"API ที่ใช้ Bearer Token หรือ API Key",
"Replacer Rule → Add Authorization Header",
"Token หมดอายุระหว่าง Scan",
"ใช้ Script Auth ดึง Token ใหม่อัตโนมัติ"),
AuthMethod("Script-based",
"Complex login เช่น MFA CAPTCHA OAuth",
"เขียน Authentication Script ใน ZAP",
"Script Error Debug ยาก",
"ใช้ Script Console debug ทีละ Step"),
AuthMethod("Manual",
"Login ด้วยมือผ่าน Browser แล้วให้ ZAP ใช้ Session",
"Login ใน Browser → ZAP จับ Cookie อัตโนมัติ",
"Session หมดอายุระหว่าง Scan",
"ตั้ง Session timeout ยาวขึ้น หรือ Re-login"),
]
print("=== Auth Methods ===")
for m in methods:
print(f" [{m.method}] Use: {m.use_case}")
print(f" Setup: {m.setup}")
print(f" Issue: {m.common_issue}")
print(f" Fix: {m.fix}")
CI/CD Integration
# === CI/CD Pipeline ===
# GitHub Actions - Baseline Scan
# name: ZAP Baseline Scan
# on: [push]
# jobs:
# zap_scan:
# runs-on: ubuntu-latest
# steps:
# - name: ZAP Baseline Scan
# uses: zaproxy/action-baseline@v0.10.0
# with:
# target: 'https://staging.myapp.com'
# rules_file_name: '.zap/rules.tsv'
# cmd_options: '-a'
# Docker Full Scan
# docker run -t owasp/zap2docker-stable zap-full-scan.py \
# -t https://staging.myapp.com \
# -g gen.conf \
# -r report.html \
# -J report.json \
# -x report.xml
# ZAP Automation Framework (YAML config)
# env:
# contexts:
# - name: "My App"
# urls: ["https://staging.myapp.com"]
# authentication:
# method: "form"
# parameters:
# loginPageUrl: "https://staging.myapp.com/login"
# loginRequestUrl: "https://staging.myapp.com/api/login"
# loginRequestBody: "username={%username%}&password={%password%}"
# jobs:
# - type: spider
# parameters: { maxDuration: 5 }
# - type: spiderAjax
# parameters: { maxDuration: 5 }
# - type: passiveScan-wait
# - type: activeScan
# parameters: { maxRuleDurationInMins: 5 }
# - type: report
# parameters:
# template: "traditional-html"
# reportFile: "zap-report.html"
@dataclass
class CIScan:
scan_type: str
command: str
duration: str
coverage: str
when: str
scans = [
CIScan("Baseline Scan",
"zap-baseline.py -t URL",
"1-2 นาที", "Passive Scan เท่านั้น",
"ทุก Push/PR — เร็ว ไม่กระทบ App"),
CIScan("Full Scan",
"zap-full-scan.py -t URL",
"10-60 นาที", "Active + Passive ครบ",
"Nightly Build หรือ Weekly — ละเอียด"),
CIScan("API Scan",
"zap-api-scan.py -t openapi.json -f openapi",
"5-15 นาที", "API Endpoints ทั้งหมด",
"ทุก API Change — ตรวจ API Security"),
CIScan("Automation Framework",
"zap.sh -cmd -autorun config.yaml",
"กำหนดเอง", "Custom ตาม Config",
"Complex Scan ที่ต้อง Auth Spider Custom"),
]
print("=== CI/CD Scans ===")
for s in scans:
print(f" [{s.scan_type}] Duration: {s.duration}")
print(f" Command: {s.command}")
print(f" Coverage: {s.coverage}")
print(f" When: {s.when}")
เคล็ดลับ
- CA: Import ZAP CA Certificate ใน Browser ก่อนเริ่มสแกน HTTPS
- Auth: ตั้ง Login/Logout Indicator ให้ถูกต้อง ป้องกัน Scan ขณะ Logout
- Ajax Spider: ใช้ Ajax Spider สำหรับ SPA React Angular Vue
- CI/CD: ใช้ Baseline Scan ทุก PR Full Scan ทุกคืน
- False Positive: สร้าง rules.tsv Ignore False Positive ที่ตรวจแล้ว
OWASP ZAP คืออะไร
Open Source Security Scanner OWASP SQL Injection XSS CSRF Active Passive Scan Spider Fuzzer API CI/CD Docker Free Windows macOS Linux
ปัญหาที่พบบ่อยมีอะไร
Proxy Port ชน SSL CA Certificate Auth Login Fail Spider SPA URL Scan ช้า Thread Rule False Positive Threshold Tune Policy
ตั้งค่า Authentication อย่างไร
Context Form-based Login URL POST Data Username Password Indicator Regex User Session Cookie Token Script API Bearer Replacer Header
ใช้ใน CI/CD อย่างไร
Docker ZAP Baseline Scan Full Scan API Scan GitHub Actions GitLab CI Jenkins Threshold Fail Pipeline Report HTML JSON Automation Framework
สรุป
OWASP ZAP Troubleshooting Proxy SSL Authentication Spider Active Scan CI/CD Docker Baseline Full API Scan False Positive Performance
