English-first documentation for the OWASP Juice Shop pentest lab that complements the existing SOC-SIEM stack (Suricata → Filebeat → Elasticsearch → Kibana). The goal is to showcase an end-to-end offensive + defensive story for a SOC/Pentest Jr portfolio.
🇧🇷 Leia este conteúdo em português: README.pt-BR.md
- What I Built & Why
- Architecture & Flow
- Components & Versions
- Runbook (Setup → Scan → Teardown)
- One‑Shot Orchestration
- Automation Scripts
- Recon & DAST Findings
- Evidence and PDF
- Hardening
- Troubleshooting
- Project Layout
- Changelog, Contributing, Security
- Offensive stream: containerised OWASP Juice Shop target with a repeatable Recon + DAST pipeline (Nmap, ZAP baseline, ZAP full scan, optional Semgrep) that produces versioned artefacts.
- Defensive linkage: reuses the Port Scan Detection Lab (Suricata-based SOC lab) to prove detection of the Recon phase (
ET SCAN Nmap TCP Scan, sid 2001219) with Kibana evidence. - Portfolio focus: code + docs under version control, HTML/TXT/PNG evidence, MITRE T1595/T1046 mapping, bilingual docs.
┌──────────────────────────────┐ ┌────────────────────────────┐
│ homelab-security/pentest-lab │ │ homelab-security/soc-siem-lab │
│ Recon & DAST Orchestrator │──────────▶│ Suricata → Filebeat → Elastic │
└─────────────┬────────────────┘ HTTP └────────────┬─────────────────┘
│ (Nmap/ZAP) 3000/tcp │ (EVE JSON)
▼ alerts/flows (ECS)
┌───────────────┐ ▼
│ Juice Shop │◀───────────── Docker bridge ──┴──▶ Kibana Dashboards
│ (bkimminich) │
└───────────────┘
- Recon traffic triggers Suricata → Filebeat ships events → Elasticsearch/Kibana visualise alerts.
- Heads-up: if the SOC lab (Port Scan Detection Lab) is already running, container
suricata-lab-juice-shopowns port:3000. Stop or reuse it beforedocker compose uphere.
- Target:
bkimminich/juice-shop:latestathttp://localhost:3000. - Recon:
nmap 7.94SVN(-sV -A -p 3000). - DAST (baseline & full scans):
ghcr.io/zaproxy/zaproxy:stable(zap-baseline.py,zap-full-scan.py). - Evidence capture:
ghcr.io/puppeteer/puppeteer:21+Pillow(Python) for annotated PNGs. - Optional SAST:
returntocorp/semgrep:latest(--config auto).
Prereqs: Docker, Docker Compose, and access to the homelab-security/ workspace.
cd homelab-security/pentest-lab
# 1) Spin up the target (skip if Juice Shop already runs via SOC lab)
docker compose up -d
# 2) Recon & DAST (MITRE T1595 / T1046)
bash scripts/nmap_scan.sh # => reports/nmap_juice.txt
bash scripts/zap_baseline.sh # => reports/zap_baseline.html
bash scripts/zap_full_scan.sh # => reports/zap_fullscan.{html,md,json}
bash scripts/semgrep.sh # optional SAST (reports/semgrep.txt)
# 3) Evidence (UTC PNGs using preset highcontrast_text_panel_v1)
bash scripts/generate_evidence.sh
# 4) Tear down when done
docker compose down -vMakefile shortcuts: make preflight | make up | make recon | make dast | make fullscan | make evidence | make run | make run_notify | make report | make down.
# Validate environment (Docker daemon, tools, port 3000 ownership)
make preflight
# End‑to‑end run (stops SOC Juice Shop if present, pulls images if needed)
make run
# Include Suricata alert summary (requires SOC ingesting and ELK reachable)
ELASTIC_URL=http://localhost:9200 make run_notifyArtifacts land in reports/ and screenshots/. A consolidated PDF report is generated with:
make report # => reports/pentest_lab_report.pdfscripts/nmap_scan.sh— Recon-sV -Aagainst127.0.0.1:3000, saves raw output.scripts/zap_baseline.sh— Runs ZAP baseline, handles return codes, stores HTML.scripts/zap_full_scan.sh— Executeszap-full-scan.py, exporting HTML, Markdown, JSON reports.scripts/semgrep.sh— Opportunistic SAST; highlights Docker hardening gaps likeno-new-privileges.scripts/generate_evidence.sh— Headless Puppeteer captures key HTML sections (baseline + full scan) andannotate.pyapplies the required preset (right-side panel, DejaVu Sans Mono, no shapes).scripts/annotate.py— Centralises thehighcontrast_text_panel_v1rules.scripts/common.sh— Shared helpers (ensure_directories,utc_now,target_url).scripts/notify_suricata_alerts.sh— Queries Elasticsearch (filebeat-*) for Suricata alerts (sid 2001219 by default), writes summaries underreports/alert_notifications/, and supports optional Slack webhook delivery.
# run after executing Nmap (and with the SOC lab ingesting Suricata logs)
bash scripts/notify_suricata_alerts.sh # last 15 minutes
LOOKBACK=now-2h bash scripts/notify_suricata_alerts.sh # custom lookback window
SLACK_WEBHOOK_URL=https://hooks.slack.com/... \
bash scripts/notify_suricata_alerts.sh # fire-and-forget Slack message- Summaries live in
reports/alert_notifications/for portfolio evidence. - Override
ELASTIC_URL,ELASTIC_INDEX, orSURICATA_SIGNATURE_IDif your stack differs. - Gracefully reports “no alerts” (exit 0) when nothing is found.
Baseline scan (reports/zap_baseline.html): 95 URLs crawled, 10 WARN (Medium/Low). Top issues:
- Content Security Policy header not set — medium; enables XSS/data injection.
- Cross-domain JavaScript include — low; CDN script without hardening.
- Deprecated Feature-Policy header — low; indicates outdated security headers.
Full scan (reports/zap_fullscan.html|md|json): 134 URLs, 5 medium findings, 5 low, 5 informational. Highlights:
- Backup File Disclosure (31 instances) —
.bak,.zip, etc. exposed under/ftp/*. - CORS Misconfiguration (95 instances) — permissive
Access-Control-Allow-Origin. - Bypassing 403 (6 instances) — encoded path (
%2e/ftp/...) bypasses access controls. - CSP and cross-domain misconfiguration repeated from baseline (medium severity).
Nmap (reports/nmap_juice.txt): service 3000/tcp open with expressive headers (Feature-Policy, X-Recruiting), good banner analysis talking point.
Semgrep (reports/semgrep.txt): 103 blocking findings; key actions include security_opt: no-new-privileges and read_only: true for Docker services.
- Suricata alert (sid 2001219)
- Correlate
source.ipwith Recon host (lab vs external). - Inspect
suricata.eve.event_type: alertin Kibana Discover. - Update SOC runbook if scan is legitimate or escalate if unexpected.
- Correlate
- CSP / CORS / backup mitigation
- Draft baseline CSP (
default-src 'self') + reporting endpoint. - Remove legacy
.bak/.zipartefacts from exposure. - Restrict CORS to trusted origins; verify preflight requirements.
- Draft baseline CSP (
- Reports:
reports/zap_baseline.html,reports/zap_fullscan.html,reports/zap_fullscan.md,reports/zap_fullscan.json,reports/nmap_juice.txt,reports/semgrep.txt,reports/alert_notifications/*.txt. - Annotated screenshots (
highcontrast_text_panel_v1):screenshots/00_zap_summary_20251109T083126Z.pngscreenshots/01_zap_csp_missing_20251109T083126Z.pngscreenshots/02_zap_crossdomain_js_20251109T083126Z.pngscreenshots/03_zap_full_summary_20251109T083126Z.pngscreenshots/04_zap_backup_files_20251109T083126Z.pngscreenshots/05_zap_cors_misconfig_20251109T083126Z.pngscreenshots/kibana_suricata_portscan_20251109T083126Z.png
- T1595 – Active Scanning: Recon (
scripts/nmap_scan.sh). - T1046 – Network Service Scanning: Enumerate Juice Shop service on 3000/tcp.
- Detection: Suricata rule
ET SCAN Nmap TCP Scan (sid:2001219, rev:6)→ Filebeat →filebeat-*data stream → Kibana Discover (screenshots/kibana_suricata_portscan_20251109T083126Z.png). For the defensive workflow, see the Port Scan Detection Lab. - Defensive playbook: log the scan, validate origin, consider WAF/IPS throttling or network ACLs.
docker-compose.yml— Juice Shop target.Makefile— helper targets.scripts/— Recon, DAST (baseline/full), SAST, evidence tooling, alert notifier, shared helpers.reports/— HTML/TXT/JSON artefacts +alert_notifications/summaries.screenshots/— annotated PNGs + raw captures (screenshots/raw/).docs/annotation_preset_highcontrast_text_panel_v1.yaml— formal preset definition.SUMMARY.md— one-page executive summary for interviews.docs/PRIVATE.md— private guide (what was done, coaching notes, hiring manager Q&A prep).
Two options:
- Baseline hardening (enabled by default):
security_opt: no-new-privileges:trueindocker-compose.yml. - Hardened overlay (opt‑in): read‑only root FS and tmpfs for
/tmpviadocker-compose.hardened.yml.
Start with hardening overlay:
make up-hardenedIf the app needs write access, add explicit writable volumes to limited paths in the overlay.
- Docker permission denied on
/var/run/docker.sock: add your user to thedockergroup and re‑login:sudo usermod -aG docker $USER && newgrp docker - Port
3000in use: the SOC lab (Port Scan Detection Lab) may be runningsuricata-lab-juice-shop. Runmake runto auto‑remove it or stop the SOC lab first. - First run pulls images: ensure outbound access to Docker Hub + GHCR; or pre‑pull images listed in the README.
- Scripted
zap-full-scan.pywith authentication (login macro) for deeper coverage. - Wire Suricata alerts into an automated notification (Slack webhook / TheHive case creation).
- Harden
docker-compose.ymlper Semgrep (baseline applied; optional overlay provided). - Add CI (GitHub Actions) to run Recon/DAST in an isolated environment, publish artefacts as build outputs.
- See
CHANGELOG.mdfor versioned history. - See
CONTRIBUTING.mdfor how to contribute. - See
CODE_OF_CONDUCT.mdandSECURITY.mdfor policies.
- Target is fully controlled/local. Do not scan external systems without written approval.
- Tools: OWASP Juice Shop, OWASP ZAP, Nmap, Semgrep, Puppeteer.
- Defensive inspiration: Port Scan Detection Lab.
