iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
Kubernetes

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

Day 3|防禦初始存取:API Server 強化 + NetworkPolicy 邊界

  • 分享至 

  • xImage
  •  

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

ATT&CK TA0001 的防禦面——如何讓 Day 2 的三條入侵路徑全部失效。

防禦總覽

攻擊 防禦措施 層級
S01 SSRF → Metadata NetworkPolicy 阻擋 169.254.169.254 Network
S02 kubelet 暴露 --anonymous-auth=false + Webhook(API Server 收到請求時自動呼叫的外部 HTTP 回呼端點)認證 Node
S03 kubeconfig 洩漏 RBAC 最小權限 + Secret 掃描 Cluster
通用 API Server 認證強化 Cluster

防禦的核心原則是縱深防禦(Defense in Depth)——不依賴單一機制,而是在多個層面設置障礙。即使攻擊者突破了應用層(SSRF 漏洞),網路層(NetworkPolicy)仍然阻擋 Metadata 存取;即使 NetworkPolicy 被繞過,kubelet 認證仍然有效。每一層都獨立運作,互不依賴。


前置準備

所有指令都在 koad 專案目錄下執行。如果還沒 clone,請先參考 Day 1 的 Step 0。

開始前請確認以下環境就緒。

1. 確認攻擊場景 Pod 運行中

防禦實作需要先確認攻擊環境可用——這樣才能對比「防禦前」與「防禦後」的差異。

# 主機終端
kubectl get pods -n koad -l 'koad-scenario in (S01,S02,S03)'

預期結果:

NAME              READY   STATUS    RESTARTS   AGE
ssrf-webapp       1/1     Running   0          ...
attacker          1/1     Running   0          ...

如果 Pod 不在 Running 狀態,重新部署:

kubectl apply -f scenarios/initial-access/
kubectl wait --for=condition=Ready pod -l 'koad-scenario in (S01,S02,S03)' -n koad --timeout=60s

2. 確認防禦工具運行中

# 主機終端
kubectl get pods -n kyverno | head -5
kubectl get pods -n falco | head -5

Kyverno 和 Falco 應該都是 Running 狀態。如果不是,參考 Day 1 的部署指引重新安裝。

3. 確認 Calico CNI 就緒

# 主機終端
kubectl get pods -n kube-system -l k8s-app=calico-node

NetworkPolicy 需要 Calico CNI 支援。如果使用 Flannel,NetworkPolicy 不會生效。

學習目標

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

  • 撰寫並部署 NetworkPolicy(Default Deny + 白名單)
  • 驗證 NetworkPolicy 成功阻擋 SSRF → Metadata 攻擊
  • 理解 kubelet 安全配置參數並驗證強化效果
  • 配置 RBAC 最小權限原則
  • 使用 git-secrets / gitleaks 掃描憑證洩漏

防禦 S01:NetworkPolicy 阻擋 Metadata API

NetworkPolicy 基礎

NetworkPolicy 是 K8s 原生的網路分段機制。在沒有 NetworkPolicy 的情況下,叢集內所有 Pod 可以自由互相通訊——這是 K8s 的設計預設(flat network)。

核心概念:

概念 說明 範例
podSelector 選取策略要套用到哪些 Pod matchLabels: {app: webapp}
namespaceSelector 選取允許/阻擋的 Namespace matchLabels: {env: prod}
policyTypes 控制方向:Ingress(入站)/ Egress(出站) [Ingress, Egress]
ipBlock 基於 IP 範圍的規則 cidr: 10.0.0.0/8

重要規則:

  1. 沒有任何 NetworkPolicy → 所有流量允許(預設 allow-all)
  2. 一旦有任何一條 NetworkPolicy 選中某個 Pod → 該 Pod 的對應方向變成「預設拒絕」
  3. 多條 NetworkPolicy 是聯集關係(OR),不是交集

CNI 實作差異

NetworkPolicy 本身只是 K8s API 的規範,實際執行由 CNI 插件負責:

CNI 實作方式 NetworkPolicy 支援 效能
Calico iptables 或 eBPF 完整支援 + 自訂擴展
Cilium eBPF 完整支援 + L7 策略 很高
Flannel VXLAN 不支援
WeaveNet 使用者態 部分支援

KOAD 使用 Calico CNI,因為它是 CKS 考試中最常見的 CNI,且同時支援 iptables 和 eBPF dataplane。

# 確認 Calico 已安裝
$ kubectl get pods -n kube-system -l k8s-app=calico-node
NAME                READY   STATUS    RESTARTS   AGE
calico-node-xxxxx   1/1     Running   0          1h

# 確認 NetworkPolicy API 可用
$ kubectl api-resources | grep networkpolicies
networkpolicies   netpol   networking.k8s.io/v1   true   NetworkPolicy

實作:Default Deny + 白名單

KOAD 的 NetworkPolicy 設計遵循「預設拒絕,明確允許」原則。這是業界公認的最佳實踐——先鎖死所有流量,再逐一開放需要的連接埠。

第一步:Default Deny All

# 1. 預設拒絕所有流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: koad
spec:
  podSelector: {}       # 選取所有 Pod(空 selector = 全選)
  policyTypes:
    - Ingress
    - Egress
  # 注意:沒有 ingress/egress 規則 = 全部拒絕

踩坑提醒: podSelector: {} 表示選取 Namespace 內所有 Pod。很多人誤以為 {} 是「不選任何 Pod」——正好相反!

第二步:Allow DNS(必要!)

# 2. 允許 DNS(否則什麼都解析不了)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns
  namespace: koad
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

踩坑提醒: 忘記開 DNS 是 NetworkPolicy 新手最常犯的錯。Default Deny 後如果不開 UDP/TCP 53,Pod 內的 curl http://some-service 全部失敗——不是因為 HTTP 被擋,而是 DNS 解析不了。

第三步:明確阻擋 Metadata API

# 3. 明確阻擋 Metadata API
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: block-metadata-api
  namespace: koad
spec:
  podSelector:
    matchLabels:
      app: ssrf-webapp
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 169.254.169.254/32    # 阻擋 Metadata API
              - 10.0.0.0/8            # 阻擋私有網段
              - 172.16.0.0/12
              - 192.168.0.0/16
      ports:
        - protocol: TCP
          port: 80
        - protocol: TCP
          port: 443

驗證防禦效果

# 1. 先不套用 NetworkPolicy,確認 SSRF 可以打到 Metadata
$ kubectl exec -n koad attacker -- \
    curl -s http://ssrf-webapp.koad:5000/fetch \
    -d "url=http://mock-metadata.koad/latest/meta-data/"
# 成功回傳 IAM 憑證

# 2. 套用 Default Deny
$ kubectl apply -f defense/network-policies/default-deny.yaml

# 3. 再次嘗試 SSRF → 超時
$ kubectl exec -n koad attacker -- \
    curl -s --max-time 5 http://ssrf-webapp.koad:5000/fetch \
    -d "url=http://mock-metadata.koad/latest/meta-data/"
# curl: (28) Connection timed out

# 4. 驗證 attacker Pod 連 DNS 都不通
$ kubectl exec -n koad attacker -- nslookup kubernetes.default
;; connection timed out; no servers could be reached

# 5. 套用 allow-dns 後 DNS 恢復
$ kubectl apply -f defense/network-policies/allow-dns.yaml
$ kubectl exec -n koad attacker -- nslookup kubernetes.default
Name: kubernetes.default
Address: 10.96.0.1

NetworkPolicy 常見錯誤

錯誤 症狀 解決方案
忘記開 DNS 所有服務名稱解析失敗 加 allow-dns 策略
Label 拼錯 策略看起來套用了但不生效 kubectl get pods --show-labels 確認
忘記 policyTypes 只擋 Ingress 不擋 Egress 明確列出 [Ingress, Egress]
用 Flannel NetworkPolicy 完全不生效 換 Calico 或 Cilium
跨 NS 通訊被擋 服務間通訊中斷 namespaceSelector 允許規則

雲端平台的替代方案

平台 阻擋 Metadata 的方法 說明
AWS EKS IMDSv2 + HttpPutResponseHopLimit=1 要求 PUT token,容器因為 hop limit 拿不到 token
GCP GKE Workload Identity 完全取代 Node SA,Pod 直接用 GCP IAM
Azure AKS Pod Identity(AAD) 取代 Node Managed Identity

AWS IMDSv2 詳解:

# 設定實例只允許 IMDSv2
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890 \
    --http-tokens required \              # 強制 IMDSv2
    --http-put-response-hop-limit 1       # 容器內拿不到 token

# IMDSv2 需要兩步
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/

# HttpPutResponseHopLimit=1 時
# Node(hop 0)可以取得 token
# Pod(hop 1+)因為 TTL 到期拿不到 token → SSRF 失敗

防禦 S02:kubelet 強化

kubelet 安全配置全景

kubelet 是 Node 上最關鍵的元件——它負責管理所有 Pod 的生命週期。如果 kubelet 被攻陷,等於整個 Node 上的所有容器都被攻陷。

完整的安全配置(/var/lib/kubelet/config.yaml):

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration

# 認證設定
authentication:
  anonymous:
    enabled: false          # 關閉匿名存取
  webhook:
    enabled: true           # 透過 API Server 驗證身份
    cacheTTL: 2m0s
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt

# 授權設定
authorization:
  mode: Webhook             # 透過 API Server 檢查授權(不是 AlwaysAllow!)

# 連接埠設定
readOnlyPort: 0             # 關閉 10255 唯讀連接埠
port: 10250                 # HTTPS 連接埠(保留,但需要認證)

# TLS 設定
tlsCertFile: /var/lib/kubelet/pki/kubelet.crt
tlsPrivateKeyFile: /var/lib/kubelet/pki/kubelet.key
tlsMinVersion: VersionTLS12

# 其他安全設定
protectKernelDefaults: true
rotateCertificates: true    # 自動輪換 kubelet 證書
serverTLSBootstrap: true

驗證強化效果

# 強化前(anonymous-auth=true)
$ curl -sk https://$NODE_IP:10250/pods | jq '.items | length'
42

# 強化後(anonymous-auth=false)
$ curl -sk https://$NODE_IP:10250/pods
Unauthorized

# 用有效的證書才能存取
$ curl -sk --cert kubelet-client.crt --key kubelet-client.key \
    https://$NODE_IP:10250/pods | jq '.items | length'
42

NodeRestriction Admission Controller

NodeRestriction 限制 kubelet 只能修改自己節點上的 Pod 和 Node 物件:

# API Server 啟用 NodeRestriction
--enable-admission-plugins=NodeRestriction,...

# 效果:
# Node A 的 kubelet 嘗試修改 Node B 上的 Pod → 403 Forbidden
# Node A 的 kubelet 修改自己節點上的 Pod → 200 OK

如果沒有 NodeRestriction,一個被攻陷的 kubelet 可以透過 API Server 操控整個叢集的 Pod。

在 Minikube 中配置

# 啟動時配置
minikube start \
  --extra-config=kubelet.anonymous-auth=false \
  --extra-config=kubelet.read-only-port=0 \
  --extra-config=kubelet.protect-kernel-defaults=true \
  --extra-config=apiserver.enable-admission-plugins=NodeRestriction

# 驗證
minikube ssh -- cat /var/lib/kubelet/config.yaml | grep -A2 anonymous

CKS 考點

kubelet 強化是 CKS 考試 Cluster Setup(15%) 領域的高頻考點。你需要能夠:

  1. 識別 kubelet 的不安全配置(ps aux | grep kubelet
  2. 修改 /var/lib/kubelet/config.yaml
  3. 重啟 kubelet:systemctl restart kubelet
  4. 驗證 10255 連接埠已關閉:ss -tlnp | grep 10255
  5. 確認 anonymous-auth 已關閉:curl -sk https://localhost:10250/pods → Unauthorized

防禦 S03:API Server 認證強化

API Server 認證方式比較

K8s API Server 支援多種認證方式,各有適用場景:

認證方式 安全性 適用場景 管理複雜度
x509 客戶端證書 管理員 + 元件通訊 高(需要 PKI)
Static Token File 很低 不建議使用
OIDC Token 使用者認證(SSO)
Webhook Token 自訂認證系統
ServiceAccount Token Pod 內部存取
Bootstrap Token 節點加入叢集

關閉匿名認證

# API Server flag
--anonymous-auth=false

關閉後,未認證的請求直接回傳 401 Unauthorized,而不是以 system:anonymous 身份通過。

啟用 RBAC + Node Authorization

--authorization-mode=Node,RBAC
  • Node authorizer:限制 kubelet 只能存取自己節點上的資源
  • RBAC:基於角色的存取控制

RBAC 最小權限範例:

# 建立只有 view 權限的 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: developer-readonly
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list", "watch"]

---
# 綁定到特定使用者
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: developer-readonly-binding
subjects:
  - kind: User
    name: developer@company.com
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: developer-readonly
  apiGroup: rbac.authorization.k8s.io

OIDC 認證設定

企業環境推薦使用 OIDC(OpenID Connect)整合現有身份系統:

# API Server OIDC 參數
--oidc-issuer-url=https://keycloak.company.com/realms/k8s
--oidc-client-id=kubernetes
--oidc-username-claim=email
--oidc-groups-claim=groups
--oidc-ca-file=/etc/kubernetes/pki/oidc-ca.crt

認證流程:

使用者 → Keycloak/Dex 登入 → 取得 ID Token → kubectl --token=<id-token> → API Server 驗證

憑證管理最佳實踐

做法 說明
禁止 Static Token File 移除 --token-auth-file,改用 x509 或 OIDC
短期 Token 使用 Bound Service Account Token(有效期限 + audience 綁定)
定期輪換 啟用 RotateKubeletServerCertificate feature gate
CI/CD 安全 使用 Workload Identity 而非長期 kubeconfig
最小權限 automountServiceAccountToken: false 除非真的需要

Bound Service Account Token

K8s 1.22+ 預設啟用 Bound SA Token Projection:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  automountServiceAccountToken: false    # 不自動掛載 SA Token
  containers:
    - name: app
      image: myapp:v1.0
      volumeMounts:
        - name: token
          mountPath: /var/run/secrets/tokens
          readOnly: true
  volumes:
    - name: token
      projected:
        sources:
          - serviceAccountToken:
              path: token
              expirationSeconds: 3600    # 1 小時過期
              audience: "api"            # 綁定 audience

與傳統 SA Token 的差異:

項目 傳統 SA Token Bound Token
有效期 永不過期 可設定(預設 1 小時)
audience 綁定特定服務
儲存 Secret 物件 TokenRequest API 動態產生
風險 洩漏後永久可用 過期後自動失效
K8s 版本 所有版本 1.22+

automountServiceAccountToken: false

這是最容易忽略但影響最大的安全設定。預設情況下,每個 Pod 都會自動掛載 SA Token 到 /var/run/secrets/kubernetes.io/serviceaccount/token——即使這個 Pod 根本不需要存取 K8s API。

# 在 ServiceAccount 層級關閉(影響所有使用此 SA 的 Pod)
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: production
automountServiceAccountToken: false

# 或在 Pod 層級關閉(更精細)
apiVersion: v1
kind: Pod
spec:
  automountServiceAccountToken: false

通用防禦:憑證掃描工具

git-secrets

防止 kubeconfig 和其他敏感資料洩漏到 Git:

# 安裝 git-secrets
brew install git-secrets

# 加入 K8s 相關 patterns
git secrets --add 'kind: Config'
git secrets --add 'certificate-authority-data:'
git secrets --add 'client-certificate-data:'
git secrets --add 'client-key-data:'
git secrets --add 'token:.*eyJ'

# 設定 pre-commit hook
git secrets --install

# 掃描整個 repo
git secrets --scan

gitleaks

gitleaks 是更現代的替代方案,支援正規表達式和 entropy 偵測:

# 安裝
brew install gitleaks

# 掃描整個 repo
gitleaks detect -v

# 掃描 staged changes(pre-commit hook)
gitleaks protect --staged -v

.gitleaks.toml 自訂規則:

[extend]
useDefault = true

[[rules]]
id = "k8s-kubeconfig"
description = "Kubernetes kubeconfig file content"
regex = '''certificate-authority-data:\s*[A-Za-z0-9+/=]{20,}'''
tags = ["kubernetes", "secret"]

[[rules]]
id = "k8s-sa-token"
description = "Kubernetes ServiceAccount Token"
regex = '''eyJhbGciOiJSUzI1NiIsImtpZCI6'''
tags = ["kubernetes", "token"]

CI/CD 整合:GitHub Actions

name: Secret Scan
on: [push, pull_request]
jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

truffleHog

# 掃描 Git repo(包含歷史記錄)
trufflehog git file://. --only-verified

# 掃描特定分支
trufflehog git file://. --branch main --only-verified

防禦實戰演練

完整的防禦部署流程,可以在 KOAD 靶場中跟著操作:

Step 1:部署 NetworkPolicy

# 主機終端 — 確認目前沒有 NetworkPolicy
$ kubectl get networkpolicies -n koad
No resources found in koad namespace.

# 部署 Default Deny
$ kubectl apply -f defense/network-policies/default-deny.yaml
$ kubectl apply -f defense/network-policies/allow-dns.yaml
$ kubectl apply -f defense/network-policies/block-metadata.yaml

# 確認策略已生效
$ kubectl get networkpolicies -n koad
NAME                 POD-SELECTOR   AGE
default-deny-all     <none>         5s
allow-dns            <none>         5s
block-metadata-api   app=ssrf-webapp   5s

Step 2:驗證 SSRF 被阻擋

驗證: 對比防禦前後的效果——同樣的攻擊指令,套用 NetworkPolicy 後應該超時失敗。

# 主機終端 — 嘗試 SSRF 攻擊 → 失敗
$ kubectl exec -n koad attacker -- \
    curl -s --max-time 5 http://ssrf-webapp.koad:5000/fetch \
    -d "url=http://mock-metadata.koad/latest/meta-data/"
# curl: (28) Connection timed out

# 驗證正常流量仍然通
$ kubectl exec -n koad ssrf-webapp-xxxxx -- \
    nslookup kubernetes.default
# 應該成功解析

Step 3:驗證 kubelet 認證

# 主機終端
$ minikube ssh -- cat /var/lib/kubelet/config.yaml | grep -A3 authentication

# 測試匿名存取
$ curl -sk https://$(minikube ip):10250/pods
Unauthorized

Step 4:檢查 RBAC 權限

# 主機終端 — 列出所有 cluster-admin 綁定
$ kubectl get clusterrolebindings -o json | \
    jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'

# 檢查是否有可疑的綁定
$ kubectl get clusterrolebindings -o json | \
    jq '.items[] | select(.roleRef.name=="cluster-admin") |
    {name: .metadata.name, subjects: .subjects}'

Step 5:掃描 ConfigMap 中的敏感資料

# 搜尋所有 ConfigMap 中是否有 token 或 password
$ kubectl get configmaps -A -o json | \
    jq -r '.items[] | select(.data != null) |
    .data | to_entries[] | select(.value | test("token|password|secret|key"; "i")) |
    "\(.key)"' 2>/dev/null

KOAD 防禦驗證

NetworkPolicy 阻擋效果

# 開啟 NetworkPolicy(default-deny-all)
$ kubectl apply -f defense/network-policies/default-deny.yaml

# 嘗試 SSRF 攻擊 → 超時
$ kubectl exec -n koad attacker -- \
    curl -s --max-time 5 http://ssrf-webapp.koad:5000/fetch \
    -d "url=http://mock-metadata.koad/latest/meta-data/"
# curl: (28) Connection timed out

NetworkPolicy 生效後,attacker pod 的所有出站流量被阻擋,攻擊鏈完全中斷。

Kyverno 審計

$ kubectl get policyreport -n koad -o json | \
    jq '.items[].results[] | select(.result=="fail") | .policy' | sort | uniq -c

  72 koad-block-privileged
  72 koad-disable-automount-sa
  72 koad-drop-capabilities
  72 koad-require-run-as-nonroot
  64 koad-require-trusted-registry
   4 koad-block-hostpath
   1 koad-block-host-namespaces

357 個違規被記錄。如果把 Kyverno 從 Audit 切換到 Enforce 模式,大部分攻擊場景在 Pod 建立時就會被拒絕。


防禦對照表

攻擊技術 KOAD 場景 防禦措施 CKS 領域
T1190 SSRF S01 NetworkPolicy + IMDSv2 Cluster Setup
T1133 kubelet S02 anonymous-auth=false + Webhook Cluster Setup
T1078 kubeconfig S03 RBAC + Bound Token + git-secrets Cluster Hardening

CKS 考點對照

考點 本日內容 可能的考試題型
NetworkPolicy Default Deny + 白名單 「撰寫 NetworkPolicy 阻止 NS X 的 Pod 存取 NS Y」
API Server 安全 kubelet 認證 + RBAC 「配置 kubelet 以拒絕匿名請求」
Secret 管理 kubeconfig 洩漏 「找出 ConfigMap 中的機密資料並移到 Secret」
Admission Control NodeRestriction 「啟用 NodeRestriction admission controller」

CKS 考試提醒: NetworkPolicy 題目通常要求你從零撰寫一條策略,而不是修改現有的。記住 YAML 結構:podSelectorpolicyTypesingress/egress 規則。考試時不能上網查,必須背熟。


清理與重設

如果你需要還原環境以便重新操作 Day 2 的攻擊場景:

# 主機終端 — 移除 NetworkPolicy
kubectl delete networkpolicies -n koad --all

# 確認 NetworkPolicy 已清除
kubectl get networkpolicies -n koad
# No resources found in koad namespace.

移除 NetworkPolicy 後,Pod 間的通訊恢復預設的 allow-all 狀態,Day 2 的攻擊場景可以重新操作。


本日小結

你完成了什麼

  • [x] 部署 Default Deny NetworkPolicy(阻擋所有流量)
  • [x] 配置 allow-dns 策略(恢復 DNS 解析)
  • [x] 驗證 NetworkPolicy 成功阻擋 SSRF 攻擊
  • [x] 確認 kubelet 認證配置(anonymous-auth=false
  • [x] 檢查 RBAC 權限綁定(識別 cluster-admin)
  • [x] 掃描 ConfigMap 中的敏感資料

完成度自我檢查

  • [ ] 已部署 Default Deny NetworkPolicy 並驗證其阻擋所有非白名單流量
  • [ ] 已部署 allow-dns NetworkPolicy 並確認 DNS 解析正常
  • [ ] 能驗證 NetworkPolicy 成功阻擋 S01 SSRF 攻擊(curl 169.254.169.254 失敗)
  • [ ] 能確認 kubelet anonymous-auth=false 配置生效
  • [ ] 能用 kubectl auth can-i --list 識別過度授權的 ServiceAccount
  • [ ] 能用 gitleaks 或 git-secrets 掃描 ConfigMap 中的敏感資料
  • [ ] 能解釋縱深防禦(Defense in Depth)中每一層的獨立作用

關鍵帶走

  1. NetworkPolicy 是 K8s 原生的網路分段機制,default-deny-all + 白名單 = 最小權限網路
  2. kubelet 強化 只需要三行配置,但少了它就等於 Node 大門敞開
  3. API Server 認證 + Bound Token 消除了長期憑證洩漏的風險
  4. 憑證掃描 git-secrets / gitleaks / truffleHog 在 CI/CD 層面阻止洩漏

核心觀念:防禦不是一道牆,而是多道門檻。 即使攻擊者突破了應用層(SSRF),NetworkPolicy 仍然擋在中間;即使 NetworkPolicy 被繞過,kubelet 認證仍然有效。這就是縱深防禦。

下一步

明天 Day 4 進入 TA0002 Execution——我們會操作 Web Shell、kubectl、特權 Pod 部署和 CronJob 四種執行手法。



上一篇
Day 2|三條入侵路徑:SSRF + 暴露服務 + 洩漏憑證
下一篇
Day 4|四種執行手法:Web Shell + kubectl + 部署 Pod + CronJob
系列文
資安這條路:從攻擊者視角看 Kubernetes7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言