
Hari 24: DAST Pertama, 66 Pass 0 Fail
ZAP baseline scan via Docker ke SecureBank API. Hasilnya 66 pass, 0 fail, 1 warn. Security headers yang dibikin di Day 15 ternyata bekerja — DAST konfirmasi.
DAST — Scan yang Beda dari SAST
Selama 23 hari terakhir kita pakai SAST (Semgrep) yang scan source code dan SCA (Trivy) yang scan dependencies. Keduanya scan tanpa menjalankan aplikasi. Hari ini beda — pakai DAST.
DAST (Dynamic Application Security Testing) scan aplikasi yang sedang berjalan. Tools-nya mengirim request ke API, baca response, dan analisis header, cookie, dan behavior. Kalau SAST itu baca kode, DAST itu kayak hacker yang coba-coba kirim request dan lihat reaksinya.
Tool yang dipakai: OWASP ZAP (Zed Attack Proxy). Salah satu DAST tool paling populer, open source, dan punya Docker image yang siap pakai.
Setup — Dari Docker Pull Sampai Scan
Step 1: Build dan Start SecureBank API
Aplikasi di-build dan dijalankan via Docker Compose. Image distroless yang sudah hardened dari Day 16-18 dipakai. API jalan di port 8080.
Step 2: Pull ZAP Docker Image
docker pull ghcr.io/zaproxy/zaproxy:stable
Image-nya sekitar 300MB. Di network yang lagi lambat, butuh waktu lumutan dan 2 layer susah di-download — berkali-kali retry. Tapi akhirnya selesai juga.
Step 3: Run ZAP Baseline Scan
docker run --rm \
-v "$(pwd)/securebank-api/security:/zap/wrk" \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t http://host.docker.internal:8080 \
-r zap-report.html \
-J zap-report.json \
-I
Penting buat yang pakai macOS Docker Desktop: --network host tidak berfungsi. Pakai host.docker.internal untuk akses host dari dalam container. Beda dengan Linux yang bisa langsung pakai localhost.
ZAP kemudian spidering aplikasi (crawling semua URL), lalu passive scanning (analisis setiap response yang diterima). Baseline scan tidak melakukan active attack — tidak kirim SQL injection atau XSS payload. Untuk itu butuh zap-full-scan.py.
Hasil — 66 Pass, 0 Fail, 1 Warn
FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 1 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 66
Yang Pass (66 checks)
Beberapa check penting yang lolos:
| Check ID | Name | Status |
|---|---|---|
| 10021 | X-Content-Type-Options Header Missing | PASS ✅ |
| 10035 | Strict-Transport-Security Header | PASS ✅ |
| 10038 | Content Security Policy (CSP) Header Not Set | PASS ✅ |
| 10063 | Permissions Policy Header Not Set | PASS ✅ |
| 10020 | Anti-clickjacking Header | PASS ✅ |
| 10010 | Cookie No HttpOnly Flag | PASS ✅ |
| 10011 | Cookie Without Secure Flag | PASS ✅ |
| 10054 | Cookie without SameSite Attribute | PASS ✅ |
Security headers yang diimplementasi di Day 15 (middleware SecurityHeaders) ternyata bekerja. ZAP mengkonfirmasi: CSP, X-Content-Type-Options, X-Frame-Options, X-XSS-Protection — semua terdeteksi di response header.
Yang Warn (1 check)
10049 — Storable and Cacheable Content (Informational/Medium)
Dua URL dikasih warning karena response-nya bisa di-cache:
http://host.docker.internal:8080(root path, 404)http://host.docker.internal:8080/robots.txt(404)
Kenapa? Karena path ini dapat 404 response default dari Go's http.HandleFunc — yang tidak melalui middleware SecurityHeaders. Middleware hanya apply ke route yang explicit didaftarkan: /health, /balance, /transfer. Path lain dapat 404 default tanpa Cache-Control: no-store.
Fix-nya: tambahin catch-all handler yang juga apply middleware ke 404 responses. Akan dikerjakan di Day 26 (DAST Remediation).
Pelajaran yang Didapat
1. DAST dan SAST saling melengkapi, bukan menggantikan. SAST nemuin insecure crypto di source code (md5 → bcrypt, Day 10). DAST nemuin missing cache-control header di 404 response. Keduanya melihat hal yang berbeda — SAST lihat kode, DAST lihat behavior. Pipeline yang ideal punya keduanya.
2. Middleware hanya apply ke route yang didefinisikan. Go's http.HandleFunc bahkan tidak apply middleware ke 404 responses. Setiap request ke path yang nggak didefinisikan dapat response default tanpa security headers. Kalau mau catch-all, perlu custom handler atau http.NotFoundHandler yang juga di-wrap dengan middleware.
3. Baseline scan = passive scan. ZAP baseline scan tidak mengirim payload attack. Hanya spidering + analisis response. Untuk scan yang lebih agresif (active attack), gunakan zap-full-scan.py atau zap-api-scan.py. Untuk API yang punya endpoint terbatas, baseline scan sudah cukup untuk phase pertama.
4. Security headers bekerja di level HTTP response. Bukan teori di kode — ZAP benar-benar membaca response header dan mengkonfirmasi: "ya, header ini ada di response". Ini bedanya DAST dengan SAST — DAST bukti langsung di runtime, bukan analisis static.
5. host.docker.internal bukan localhost di macOS. Docker Desktop di macOS tidak support --network host untuk akses host dari container. Pakai host.docker.internal sebagai hostname. Ini specific ke macOS Docker Desktop, bukan masalah di Linux.
Kesimpulan
Day 24 selesai. DAST pertama dengan OWASP ZAP. 66 dari 67 check pass (98.5%). 0 fail. 1 warn yang akan diperbaiki di Day 26. Security headers yang dibikin sejak Day 15 terbukti bekerja di level runtime.
Beberapa hal yang unik hari ini: Docker pull yang butuh waktu lama karena 2 layer susah ke-download, ZAP local install yang coba dulu tapi akhirnya pakai Docker image yang lebih clean, dan host.docker.internal yang specific ke macOS.
Besok Day 25: DAST di Pipeline — ZAP scan otomatis di GitHub Actions. Supaya setiap push ke repo, DAST scan jalan otomatis. Sampai jumpa besok!
Diskusi & Komentar
Hari 23: 0 Finding, Pipeline IaC Hijau
Next ArticleHari 25: DAST Otomatis di CI Pipeline
Artikel Terkait
Hari 5: Trivy SCA Scan Nemukan 4 CVE di Golang API
Hari kelima 60 hari DevSecOps! Scan dependensi Go pakai Trivy dan nemukan 4 CVE termasuk 1 CRITICAL — termasuk library deprecated jwt-go.
Hari 8: Semgrep SAST Scan Temukan Kode Tidak Aman
Hari kedelapan 60 hari DevSecOps! Install Semgrep, buat kode insecure (MD5), dan scan ketemu 2 finding — MD5 weak hash dan HTTP server tanpa TLS.
Hari 10: MD5 ke Bcrypt, Pipeline Hijau Lagi
Hari kesepuluh 60 hari DevSecOps! Fix SAST findings — ganti MD5 ke bcrypt, hapus custom rule HTTP TLS, dan pipeline CI kembali hijau setelah 4 job semua pass.