每個應用程式以 4 個負載平衡的 Docker 容器運行,透過 nginx 上游池在 VM 上的 nginx 反向代理提供存取。黏性工作階段確保有狀態的應用程式(Juice Shop、DVWA、VAmPI、CSD Demo)路由一致。所有應用程式均為刻意設計的弱點應用程式,供安全性測試使用。
在以下所有範例中,請將 <ORIGIN> 替換為 http://<PUBLIC_IP>。透過 Terraform 部署後,可使用 terraform output -raw public_ip 取得 IP 位址。
| 路徑 | 應用程式 | HTTP 方法 | 預期回應 |
|---|
/ | 首頁 | GET | 200 HTML,包含所有應用程式連結 |
/health | 健康檢查 | GET | 200 JSON {"status":"healthy","component":"origin-server",...} |
/juice-shop/ | Juice Shop | GET | 200 HTML(Angular SPA,約 75 KB) |
/juice-shop/rest/products/search?q= | Juice Shop API | GET | 200 JSON {"status":"success","data":[...]} (36 項產品) |
/dvwa/ | DVWA | GET | 302 重新導向至 /dvwa/login.php |
/dvwa/login.php | DVWA 登入 | GET | 200 HTML 登入表單 |
/dvwa/setup.php | DVWA 設定 | GET | 200 HTML(首次執行資料庫初始化) |
/vampi/ | VAmPI | GET | 200 HTML(API 文件) |
/vampi/users/v1 | VAmPI API | GET | 200 JSON {"users":[...]} |
/vampi/users/v1/register | VAmPI API | POST | 200 JSON {"status":"success",...} |
/vampi/users/v1/login | VAmPI API | POST | 200 JSON {"auth_token":"...","status":"success"} |
/httpbin/get | httpbin | GET | 200 JSON,包含請求詳細資訊 |
/httpbin/post | httpbin | POST | 200 JSON,包含已提交的資料 |
/httpbin/headers | httpbin | GET | 200 JSON {"headers":{...}} |
/httpbin/status/:code | httpbin | GET | 回傳指定的 HTTP 狀態碼 |
/whoami/ | whoami | GET | 200 純文字,包含主機名稱、IP 及所有標頭 |
/csd-demo/ | CSD Demo | GET | 200 HTML 結帳表單,含攻擊面板 |
/csd-demo/dashboard | CSD 攻擊者檢視 | GET | 200 HTML,顯示已外洩的資料 |
/csd-demo/health | CSD 健康檢查 | GET | 200 JSON {"status":"healthy","component":"csd-demo",...} |
/csd-demo/exfil/log | CSD 外洩記錄 | GET | 200 JSON 陣列,包含擷取的資料 |
/dvga/ | DVGA GraphiQL | GET | 200 HTML(GraphiQL IDE) |
/dvga/graphql | DVGA GraphQL API | POST | 200 JSON GraphQL 回應 |
/restaurant/ | RESTaurant | GET | 200(重新導向至文件) |
/restaurant/docs | RESTaurant Swagger | GET | 200 HTML(FastAPI Swagger UI) |
/restaurant/openapi.json | RESTaurant OpenAPI | GET | 200 JSON OpenAPI 規格 |
http://<PUBLIC_IP>:8888 | crAPI | GET | 200 HTML(SPA) |
http://<PUBLIC_IP>:8888/identity/api/auth/signup | crAPI 註冊 | POST | 200 JSON |
http://<PUBLIC_IP>:8888/identity/api/auth/login | crAPI 登入 | POST | 200 JSON {"token":"..."} |
| |
|---|
| 路徑 | /juice-shop/ |
| 映像檔 | bkimminich/juice-shop:latest |
| 執行個體 | 4 個(連接埠 3001-3004),透過 hash $cookie_token 實現黏性工作階段,代理快取(TTL 60 秒) |
| 資源 | 每個執行個體 2 CPU / 1 GiB RAM |
| 框架 | Node.js / Angular |
| 專案 | owasp.org/www-project-juice-shop |
OWASP Juice Shop 是目前最現代且積極維護的弱點 Web 應用程式。它以真實的電子商務應用程式為背景,涵蓋完整的 OWASP Top 10,並提供超過 100 個挑戰。
| 情境 | 類別 | 攻擊向量 |
|---|
| SQL 注入登入繞過 | WAF | 在登入電子郵件欄位輸入 ' OR 1=1-- |
| 反射式 XSS | WAF、CSD | 透過搜尋參數進行腳本注入 |
| DOM 型 XSS | CSD | URL 片段中的攻擊載荷 |
| 身份驗證失效 | WAF | 暴力破解登入、JWT 操控 |
| API 濫用 | API 安全性 | 未授權存取 /api/ 端點 |
| 敏感資料外洩 | API 安全性 | 未授權存取使用者資料 |
| CSRF | WAF | 對個人資料變更的跨站請求偽造 |
curl -s "http://<PUBLIC_IP>/juice-shop/" -o /dev/null -w "%{http_code}"
| |
|---|
| 路徑 | /dvwa/ |
| 映像檔 | 自訂 dvwa-fpm:latest(php-fpm + nginx,從 ghcr.io/digininja/dvwa:latest 建置) |
| 執行個體 | 4 個(連接埠 8101-8104),透過 hash $cookie_PHPSESSID 實現黏性工作階段 |
| 資源 | 每個執行個體 0.5 CPU / 256 MiB RAM |
| 資料庫 | 共用 MariaDB 10.11(dvwa-db 容器,1 CPU / 768 MiB) |
| 框架 | PHP 8 / php-fpm / MariaDB |
| 憑證 | admin / password |
DVWA 是 WAF 測試的業界標準。它提供可調整的安全等級(低、中、高、不可能),逐步增加輸入驗證與輸出編碼。
| 情境 | 類別 | 安全等級 |
|---|
| SQL 注入 | WAF | 低:簡易 ' OR 1=1#,高:盲注 SQLi |
| 指令注入 | WAF | 低:; ls,高:過濾特殊字元 |
| 檔案包含 | WAF | 低:直接路徑遍歷,高:已消毒處理 |
| XSS(反射式) | WAF、CSD | 低:基本 <script>,高:編碼繞過 |
| XSS(儲存式) | WAF、CSD | 低:留言板中的持久性腳本 |
| 檔案上傳 | WAF | 低:上傳 PHP Shell,高:副檔名過濾 |
| 暴力破解 | 機器人防禦 | 自動化登入嘗試 |
登入後於 /dvwa/security.php 設定安全等級:
- 低 — 無輸入驗證。所有攻擊均有效。適合 WAF 特徵示範。
- 中 — 基本過濾。部分攻擊需要編碼或繞過技術。
- 高 — 強力過濾。僅進階技術可成功。適合展示 WAF 的限制。
- 不可能 — 完全安全的實作。示範正確的防禦性程式設計。
DVWA 在首次部署後需要進行一次性的資料庫設定:
- 前往
http://<PUBLIC_IP>/dvwa/setup.php
- 點按 Create / Reset Database
- 使用
admin / password 登入
| |
|---|
| 路徑 | /vampi/ |
| 映像檔 | erev0s/vampi:latest,使用 gunicorn 進入點(4 個工作程序) |
| 執行個體 | 4 個(連接埠 5101-5104),透過 ip_hash 實現黏性工作階段(每個執行個體獨立 SQLite) |
| 資源 | 每個執行個體 0.5 CPU / 512 MiB RAM |
| 框架 | Python / Flask / gunicorn |
| 專案 | github.com/erev0s/VAmPI |
VAmPI 專為測試 OWASP API 安全性 Top 10 而設計,提供具有刻意弱點的真實 REST API。每個執行個體使用 gunicorn 搭配 4 個工作程序,並擁有獨立的 SQLite 資料庫。ip_hash 黏性工作階段確保來自相同用戶端 IP 的註冊與登入請求始終路由至同一個執行個體。
| 情境 | OWASP API Top 10 | 方法 |
|---|
| 物件層級授權失效(BOLA) | API1 | 透過操控 ID 存取其他使用者的資料 |
| 身份驗證失效 | API2 | 弱式令牌處理、無速率限制 |
| 過度資料暴露 | API3 | API 回傳超出用戶端所需的資料 |
| 大量指派 | API6 | 透過非預期參數修改管理員欄位 |
| SQL 注入 | API8 | 透過 API 參數進行注入 |
| 資產管理不當 | API9 | 未記錄的 API 端點 |
curl -X POST "http://<PUBLIC_IP>/vampi/users/v1/register" \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test123","email":"test@test.com"}'
curl -X POST "http://<PUBLIC_IP>/vampi/users/v1/login" \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test123"}'
curl "http://<PUBLIC_IP>/vampi/users/v1"
| |
|---|
| 路徑 | /httpbin/ |
| 映像檔 | kennethreitz/httpbin:latest,覆寫 gunicorn CMD(-w 4 -k gevent --timeout 30) |
| 執行個體 | 4 個(連接埠 8201-8204),輪詢(無狀態) |
| 資源 | 每個執行個體 0.5 CPU / 256 MiB RAM |
| 框架 | Python / Flask / gunicorn + gevent |
| 專案 | httpbin.org |
httpbin 是一個簡單的 HTTP 請求/回應服務,適用於基本 API 示範、測試請求標頭,以及驗證代理行為。
| 端點 | 用途 |
|---|
/httpbin/get | 回傳 GET 請求資料(標頭、參數、來源) |
/httpbin/post | 回傳 POST 請求資料(本文、表單、JSON) |
/httpbin/headers | 回傳請求標頭 |
/httpbin/ip | 回傳來源 IP |
/httpbin/user-agent | 回傳 User-Agent 標頭 |
/httpbin/status/:code | 回傳指定的 HTTP 狀態碼 |
/httpbin/delay/:seconds | 將回應延遲 N 秒 |
/httpbin/anything | 回傳請求中傳遞的所有內容 |
# 檢查來源看到的標頭(適用於驗證 F5 XC 標頭注入)
curl -s "http://<PUBLIC_IP>/httpbin/headers" | jq .
curl -s -o /dev/null -w "%{http_code}" "http://<PUBLIC_IP>/httpbin/status/403"
| |
|---|
| 路徑 | /whoami/ |
| 映像檔 | traefik/whoami:latest |
| 執行個體 | 4 個(連接埠 8082-8085),輪詢(無狀態) |
| 資源 | 每個執行個體 0.25 CPU / 64 MiB RAM |
| 框架 | Go |
| 專案 | github.com/traefik/whoami |
whoami 是 Traefik 的輕量級請求回顯伺服器。它以來源端所見的方式顯示傳入 HTTP 請求的每項詳細資訊——主機名稱、IP 位址、所有標頭、方法及 URL。這是驗證 F5 XC 是否正確注入標頭時最重要的單一診斷工具。
| 使用情境 | 注意事項 |
|---|
| 驗證 F5 XC 標頭注入 | X-Forwarded-For、True-Client-IP、X-Volterra-* 標頭 |
| 確認用戶端 IP 可見性 | X-Real-IP 與 RemoteAddr 的比較 |
| 偵錯 WAF 誤判 | 比較 F5 XC 前後的請求標頭 |
| 驗證機器人防禦標記 | X-Volterra-Bot-Type、X-Volterra-Bot-Verified 標頭 |
| 檢查 TLS 終止 | X-Forwarded-Proto 在 F5 XC 終止 TLS 時顯示 https |
curl "http://<PUBLIC_IP>/whoami/"
curl "http://<PUBLIC_IP>/whoami/" \
-H "X-Forwarded-For: 203.0.113.50" \
-H "True-Client-IP: 203.0.113.50" \
-H "X-Forwarded-Proto: https"
輸出範例:
RemoteAddr: 172.17.0.1:55118
True-Client-Ip: 203.0.113.50
X-Forwarded-For: 203.0.113.50, 10.0.0.1
X-Real-Ip: 104.219.105.84
DVGA 專為測試 GraphQL 特定弱點而設計。它在 /dvga/ 提供 GraphiQL IDE 供互動式查詢探索,並在 /dvga/graphql 提供 GraphQL API 端點。每個執行個體使用獨立的 SQLite 資料庫,因此 ip_hash 黏性工作階段可確保狀態一致性。
| 情境 | 類別 | 攻擊向量 |
|---|
| GraphQL 注入 | API 安全性 | 透過字串插值進行惡意查詢 |
| 阻斷服務 | API 安全性 | 深度巢狀查詢、批次查詢、資源耗盡 |
| 授權繞過 | API 安全性 | 透過 GraphQL 存取未授權的資料 |
| 資訊洩漏 | API 安全性 | 透過自省查詢揭露結構描述詳細資訊 |
| 批次攻擊 | API 安全性 | 在單一請求中執行多項操作 |
curl -sf "http://<PUBLIC_IP>/dvga/" -o /dev/null -w "%{http_code}"
curl -s "http://<PUBLIC_IP>/dvga/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{ __schema { types { name fields { name } } } }"}'
curl -s "http://<PUBLIC_IP>/dvga/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{ pastes { title content } }"}'
curl -s "http://<PUBLIC_IP>/dvga/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"mutation { createPaste(title:\"test\", content:\"hello\", public:true) { paste { title } } }"}'
| |
|---|
| 路徑 | /restaurant/ |
| 映像檔 | 從 theowni/Damn-Vulnerable-RESTaurant-API-Game 自訂建置 |
| 執行個體 | 4 個(連接埠 8301-8304),輪詢(共用 PostgreSQL) |
| 資源 | 每個執行個體 0.5 CPU / 256 MiB RAM |
| 資料庫 | 共用 PostgreSQL 15.4(restaurant-db 容器,0.5 CPU / 512 MiB) |
| 框架 | Python / FastAPI / PostgreSQL |
| 憑證 | admin / password(PostgreSQL) |
| 專案 | github.com/theowni/Damn-Vulnerable-RESTaurant-API-Game |
RESTaurant 是一個遊戲化的弱點 REST API,涵蓋 OWASP API 安全性 Top 10 2023。它使用 FastAPI,並在 /restaurant/docs 提供自動生成的 Swagger UI 文件。全部 4 個執行個體共用單一 PostgreSQL 資料庫,因此輪詢負載平衡無需黏性工作階段。
| 情境 | OWASP API Top 10 2023 | 方法 |
|---|
| 物件層級授權失效(BOLA) | API1 | 透過操控 ID 存取其他使用者的訂單 |
| 身份驗證失效 | API2 | 弱式令牌處理、憑證填充攻擊 |
| 物件屬性層級授權失效 | API3 | 對使用者個人資料欄位進行大量指派 |
| 無限制的資源消耗 | API4 | 端點無速率限制 |
| 功能層級授權失效(BFLA) | API5 | 以一般使用者身份存取管理員端點 |
| 伺服器端請求偽造(SSRF) | API7 | 操控伺服器端 URL 請求 |
| 安全性設定錯誤 | API8 | 詳細錯誤訊息、預設憑證 |
curl -sf "http://<PUBLIC_IP>/restaurant/docs" -o /dev/null -w "%{http_code}"
curl -s "http://<PUBLIC_IP>/restaurant/openapi.json" | jq .info
# BOLA -- 存取其他使用者的訂單(需身份驗證後)
curl -s "http://<PUBLIC_IP>/restaurant/orders/1" \
-H "Authorization: Bearer <token>"
# BFLA -- 以一般使用者嘗試執行管理員操作
curl -s -X POST "http://<PUBLIC_IP>/restaurant/admin/users" \
-H "Authorization: Bearer <user_token>" \
-H "Content-Type: application/json"
| |
|---|
| 連接埠 | 8888(專用——非路徑前綴) |
| 映像檔 | crapi/crapi-web、crapi/crapi-identity、crapi/crapi-community、crapi/crapi-workshop、PostgreSQL、MongoDB、MailHog |
| 執行個體 | 7 個微服務(各單一執行個體) |
| 資源 | 總計約 3.0 CPU / 約 2.0 GiB RAM |
| 框架 | React SPA + Java/Go/Python 微服務 |
| 專案 | github.com/OWASP/crAPI |
crAPI 是 OWASP API 安全性測試的旗艦專案。它以 7 個微服務運行在專用連接埠(8888)上,原因是 React SPA 硬式編碼了 API 路徑,無法在路徑前綴後方提供服務。NSG 允許連接埠 8888 上的輸入流量。
MailHog 擷取 crAPI 傳送的所有電子郵件(帳號驗證、密碼重設)。透過 SSH 通道在連接埠 18025 存取 MailHog。
| 類別 | 弱點 |
|---|
| BOLA(物件層級授權失效) | 存取其他使用者的車輛、訂單及報告 |
| BFLA(功能層級授權失效) | 提升至管理員、存取受限端點 |
| 大量指派 | 透過 API 修改受保護的欄位(角色、餘額) |
| SSRF(伺服器端請求偽造) | 操控伺服器端 URL 擷取 |
| JWT 操控 | 偽造或修改 JWT 令牌以進行權限提升 |
| NoSQL 注入 | 向 MongoDB 支援的端點注入查詢 |
| 過度資料暴露 | API 回傳敏感的使用者資料 |
curl -sf "http://<PUBLIC_IP>:8888" -o /dev/null -w "%{http_code}"
curl -s -X POST "http://<PUBLIC_IP>:8888/identity/api/auth/signup" \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","number":"1234567890","password":"Test1234!"}'
curl -s -X POST "http://<PUBLIC_IP>:8888/identity/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"Test1234!"}'
# 存取 MailHog(透過 SSH 通道進行電子郵件驗證)
# ssh -L 18025:localhost:18025 azureuser@<PUBLIC_IP>
# 然後在瀏覽器中開啟 http://localhost:18025
Port 8888 -> crapi-web (React SPA + nginx)
-> crapi-identity (Java, user auth, JWT)
-> crapi-community (Go, forums, posts)
-> crapi-workshop (Python, vehicle service)
-> crapi-postgres (PostgreSQL)
-> crapi-mailhog (email capture, port 18025)
| 示範使用情境 | 主要應用程式 | 次要應用程式 |
|---|
| WAF — SQL 注入 | DVWA | Juice Shop |
| WAF — XSS | DVWA | Juice Shop |
| WAF — 指令注入 | DVWA | — |
| API 安全性 — BOLA | VAmPI | — |
| API 安全性 — 身份驗證繞過 | VAmPI | Juice Shop |
| API 安全性 — 資料暴露 | VAmPI | httpbin |
| 機器人防禦 — 暴力破解 | DVWA | Juice Shop |
| 機器人防禦 — 爬取 | Juice Shop | — |
| 用戶端防禦 — DOM XSS | Juice Shop | — |
| 用戶端防禦 — 儲存式 XSS | DVWA | Juice Shop |
| 用戶端防禦 — 信用卡側錄 | CSD Demo | — |
| 用戶端防禦 — 表單劫持 | CSD Demo | — |
| 用戶端防禦 — 鍵盤記錄 | CSD Demo | — |
| 用戶端防禦 — 加密貨幣挖礦 | CSD Demo | — |
| 用戶端防禦 — DOM 劫持 | CSD Demo | — |
| API 安全性 — GraphQL 注入 | DVGA | — |
| API 安全性 — GraphQL DoS | DVGA | — |
| API 安全性 — OWASP API Top 10 2023 | RESTaurant | crAPI |
| API 安全性 — BFLA | RESTaurant | crAPI |
| API 安全性 — 大量指派 | crAPI | RESTaurant |
| API 安全性 — SSRF | crAPI | RESTaurant |
| API 安全性 — JWT 操控 | crAPI | — |
| API 安全性 — NoSQL 注入 | crAPI | — |
| 基本連線測試 | httpbin | — |
| 請求診斷 | whoami | httpbin |
| 標頭注入驗證 | whoami | — |