
一、開場:你的K8s叢集,正在被敲門
想像一下,5月8號下午4點23分,你可能正在會議室跟PM吵需求,或者正在享受下午咖啡——但你的API Gateway,正在默默地擋下第一波攻勢。
[WARN] api-gateway: 401 | method=HEAD path=/
[WARN] api-gateway: 401 | method=GET path=/health
[WARN] api-gateway: 401 | method=GET path=/version
[WARN] api-gateway: 401 | method=GET path=/swagger
看到沒?這不是什麼神祕的APT組織,也不是什麼國家級駭客——只是一個帶著 curl/8.7.1 的腳本小子,正在依序敲你的門:先敲 /health 看看你有沒有活著,再敲 /version 問你用什麼版本,最後敲 /swagger 看看你的API文件有沒有乖乖晾在外面。
聽起來很初階對吧?但接下來三天發生的事,會讓你開始冒冷汗。
就在這短短72小時內,同一個系統遭遇了5波不同型態的攻擊:從單純的curl掃描,到多路徑 .env 憑證竊取,再到75+請求的大規模自動化漏洞掃描,最後是85次認證端點的憑證填充攻擊(Credential Stuffing)。攻擊者就像一個越來越有耐心的闖空門小偷:先觀察,再試鎖,最後直接拿萬用鑰匙來捅。
你以為你的K8s叢集躲在雲端很安全?別傻了。在攻擊者的眼中,你的API端點就是一扇扇沒鎖好的窗戶。
今天,我們就來場「資安辦案實錄」,用你提供的真實日誌還原攻擊現場,並帶你深入了解這些攻擊手法背後的技術原理,以及——最重要的是——你要怎麼擋下它們。
二、K8s攻擊面總覽:駭客眼中的「藏寶圖」
在進入個案分析之前,我們先拉高視角,看看K8s叢集在攻擊者眼中到底是什麼樣子的。
你可能會想:「我的K8s叢集有API Gateway擋在前面,攻擊者連kubelet長怎樣都看不到吧?」
確實,很多攻擊在第一道防線就被擋下來了——就像你提供的日誌中,全部回傳 401 Unauthorized,看起來好像沒事。
但問題是:攻擊者不需要一次成功,他們只需要一次失誤。
以下是K8s環境中常見的攻擊類型與風險等級一覽:
| 攻擊類型 | 目標 | 常見工具/手法 | 成功後果 | 風險等級 |
|---|---|---|---|---|
| API Server未授權存取 | kube-apiserver | kubectl、curl | 叢集完全淪陷 | 🔴 極高 |
| etcd資料竊取 | etcd儲存層 | etcdctl、埠掃描 | 所有Secrets、ConfigMap外洩 | 🔴 極高 |
| kubelet API濫用 | kubelet 10250埠 | kubeletctl | 在Node上執行任意指令 | 🔴 高 |
| 容器逃逸至Host | 容器Runtime | CVE-2024-…、Linux Capabilities濫用 | 突破容器隔離,控制Node | 🔴 高 |
| 加密貨幣挖礦 | 未受保護的Pod | 惡意镜像、kubectl apply | CPU/GPU資源被竊取,帳單暴增 | 🟡 中高 |
| 橫向移動 | 內部Service | 服務帳號令牌竊取、DNS掃描 | 從一個薄弱Pod擴散到整個叢集 | 🟡 中高 |
| 憑證填充/暴力破解 | Auth端點 | Hydra、Burp Suite、自訂腳本 | 帳號被盜用,資料外洩 | 🟡 中 |
| 配置錯誤利用 | Ingress/RBAC/NetworkPolicy | kube-hunter、kube-bench | 權限提升,敏感資料存取 | 🟡 中 |
看到這張表,你是不是開始回想自己的叢集做了哪些防護?如果還不確定,沒關係——接下來我們直接用你的日誌來場「現場辦案」。
三、真實攻擊手法深度解析:五波攻防全記錄
準備好了嗎?我們要把時間倒回5月8號,一個平凡無奇的星期四下午。
3.1 第一波:curl系統偵察掃描(May 08 16:23)
這是整個攻擊鏈的起點。攻擊者首先用最樸素的方式——直接拿 curl/8.7.1 敲門:
[WARN] api-gateway: 401 | method=HEAD path=/
[WARN] api-gateway: 401 | method=GET path=/
[WARN] api-gateway: 401 | method=GET path=/health
[WARN] api-gateway: 401 | method=GET path=/version
[WARN] api-gateway: 401 | method=GET path=/swagger
[WARN] api-gateway: 401 | method=HEAD path=/swagger/v1/swagger.json
User-Agent: curl/8.7.1 — 連偽裝都懶得偽裝。
這個階段的攻擊者像個觀光客,拿著地圖一個一個點踩點:
/health→ 確認服務有沒有活著/version→ 確認你用什麼版本(有沒有已知漏洞)/swagger→ 找API文件(這是最危險的,因為Swagger/OpenAPI文件等於把你的API地圖送給攻擊者)
攻擊者思維: 「先確認目標還活著,再確認版本,最後找API說明書。如果Swagger有開,就等於拿到整棟大樓的藍圖。」
好險你們家的 /swagger 有擋住。 很多團隊為了開發方便,會把Swagger UI暴露在外網——這就像把保險箱密碼貼在保險箱外面一樣荒唐。
3.2 第二波:多路徑.env憑證竊取掃描(May 09 04:20)
隔天凌晨4點20分,攻擊者換了個劇本。
[WARN] api-gateway: 401 | method=GET path=/.env
[WARN] api-gateway: 401 | method=GET path=/v1/.env
[WARN] api-gateway: 401 | method=GET path=/v2/.env
[WARN] api-gateway: 401 | method=GET path=/v3/.env
[WARN] api-gateway: 401 | method=GET path=/dev/.env
[WARN] api-gateway: 401 | method=GET path=/staging/.env
同一支Windows Chrome瀏覽器,1分鐘內掃了6個常見的 .env 路徑。
.env 檔案是什麼?它是很多開發框架用來存放環境變數的地方——資料庫連線字串、API金鑰、JWT密碼——所有不該公開的秘密,全都寫在裡面。
你以為 .env 在伺服器上很安全?但很多團隊會不小心:
- 把
.env提交到GitHub(Google一下就能找到上千筆) - 把
.env放在Web伺服器的可存取路徑下 - 把
.env打包進Docker镜像裡
攻擊者掃描這些路徑,賭的就是有人犯了這些錯。
防禦啟示:
.env不要放在Web根目錄,更不要提交到Git repository。使用K8s的Secrets搭配External Secrets Operator或Vault來管理機敏資料。
3.3 🔴 第三波:大規模自動化漏洞掃描(May 09 21:36~21:37)
這波攻擊,才是真正讓人心跳加速的。
1分鐘內,75+個請求排山倒海而來,而且攻擊者還很專業地輪換了多種User-Agent:
Windows NT 10.0 Chrome
Macintosh macOS Safari
X11 Linux Chrome
iPhone Safari Mobile
Windows Firefox 121.0
來看看他們在掃什麼:
(Nuclei/自訂掃描器) participant WAF as API Gateway participant K8s as K8s叢集 Attacker->>WAF: GET /user (x5) Attacker->>WAF: GET /admin (x5) Attacker->>WAF: GET /me (x5) WAF-->>Attacker: 401 Unauthorized Attacker->>WAF: GET /.env Attacker->>WAF: GET /config/env Attacker->>WAF: GET /templates/env WAF-->>Attacker: 401 Unauthorized Attacker->>WAF: GET /openapi.json Attacker->>WAF: GET /documentation.json Attacker->>WAF: GET /docs.json WAF-->>Attacker: 401 Unauthorized Note over Attacker,WAF: 重點!針對現代技術棧 Attacker->>WAF: GET /inngest Attacker->>WAF: GET /edge/inngest Attacker->>WAF: GET /fn Attacker->>WAF: GET /v1/chatflows Attacker->>WAF: GET /v1/ping WAF-->>Attacker: 401 Unauthorized
我把掃描目標分成幾個類別來分析:
| 探測類別 | 路徑範例 | 攻擊者意圖 |
|---|---|---|
| 使用者/Admin端點 | /user ×5、/admin ×5、/me ×5 | 尋找未授權的個資存取點 |
| Auth流程 | /auth/session ×5 | 會話洩露偵測 |
| 環境設定檔 | /.env、/env、/config/env、/templates/env | 設定檔洩露嘗試 |
| API文件 | /documentation.json、/docs.json、/openapi.json | API Schema洩露 |
| 偵錯/狀態 | /debug、/status、/v1/debug、/admin/debug | 偵錯端點暴露嘗試 |
| Inngest Serverless | /inngest、/edge/inngest、/fn、/handler | 針對Inngest Webhook框架漏洞 |
| AI Chatbot API | /v1/chatflows、/v1/ping | 針對Flowise AI / LangChain端點 |
為什麼特別強調Inngest和Flowise?
因為這代表了攻擊者已經不只針對傳統的LAMP架構或WordPress。他們知道現在大家都在用Serverless框架(Inngest)、AI聊天機器人平台(Flowise/LangChain),這些新技術雖然方便,但安全社群對它們的認識還不夠深,漏洞通常也還沒被大規模修補。
這就像是小偷不只會撬傳統喇叭鎖,現在連電子鎖的破解方法也研究好了。
這波攻擊的關鍵教訓: 你的API Gateway成功擋下了全部75+請求,這很好。但攻擊者已經知道你們用了哪些技術棧——從Inngest到Flowise,他們已經建立了完整的攻擊清單。這代表你必須主動補強這些現代框架的安全性,不能等到CVE公布才來修。
3.4 🔴 第四波:Auth端點憑證填充攻擊(May 10 08:45~08:46)
隔天早上8點45分,攻擊者決定不再繞圈子,直接朝心臟開刀。
2分鐘內,85個請求集中轟炸認證端點:
POST /auth/signin ← 登入嘗試(最關鍵)
POST /auth/signout ← 登出流程探測
POST /auth/session ← 會話操作
POST /auth/callback ← OAuth回調端點
POST /auth ← 主認證端點
POST /trpc ← tRPC API端點
而且User-Agent輪換得非常專業——Windows Chrome、Mac Safari、Linux Chrome、Windows Firefox輪流上陣,讓人難以從UA辨識這是機器人。
這招叫做憑證填充攻擊(Credential Stuffing),跟一般暴力破解不一樣:
| 面向 | 暴力破解 | 憑證填充 |
|---|---|---|
| 原理 | 對單一帳號嘗試不同密碼 | 利用外洩的帳密組合批量嘗試 |
| 特徵 | 同一帳號大量失敗 | 不同帳號少量嘗試 |
| 資料來源 | 猜測/字典 | 暗網外洩資料庫 |
| 防禦難度 | 較低(lockout策略有效) | 較高(看起來像正常登入) |
| 成功率 | 極低 | 如果使用者重用密碼,很高 |
為什麼這波攻擊特別危險?因為如果你的用戶在其他網站洩漏了密碼,又在你的平台上使用同一組帳密,那攻擊者只要找到一個配對——就中了。
以K8s環境來說,如果攻擊者成功登入,下一步就是:
- 透過Pod內部的Service Account Token掃描K8s API
- 嘗試從Pod橫向移動到其他Service
- 找出可以存取資料庫的Pod
你提供的日誌中,系統因為缺少有效的JWT都回傳了401——但如果哪天攻擊者真的拿到的有效的token呢?
3.5 補充:那些年K8s叢集的經典屠殺
除了你遇到的這幾波攻擊,業界還有一些K8s安全事件值得我們當作借鏡:
🚨 Tesla Kubernetes挖礦事件(2018)
2018年,Tesla的AWS環境遭駭客入侵。攻擊者不是直接打API,而是利用Kubernetes Dashboard未設置密碼保護的配置失誤,直接登入管理介面,然後在Pod內部署了挖礦軟體。
是的,Kubernetes Dashboard,預設沒有認證,直接暴露在外網——等於把大門鑰匙掛在門口。
🚨 Siloscape — 首個K8s後門惡意軟體(2021)
這傢伙厲害了。Siloscape是安全研究員發現的第一個專門針對K8s的惡意軟體。它利用了Windows容器的已知漏洞,成功突破容器隔離後,在受害者的K8s叢集中建立後門,用來部署加密貨幣挖礦容器。
Siloscape的攻擊鏈長這樣:
🚨 RBAC權限繞過攻擊(2023~持續發生中)
這不是單一事件,而是一整類問題。常見場景:一個Service Account被賦予了過大的ClusterRole權限(例如 cluster-admin),攻擊者只要拿到這個Service Account的token,就能在整個叢集橫著走。
小提醒: 檢查你們家的RBAC設定,看看有多少Service Account被掛上了
cluster-admin——你可能會嚇一跳。
四、攻擊鏈還原:把日誌拼成一張完整的攻擊地圖
現在,我們把這五天的事整合起來,看看攻擊者的完整手法演進:
| 時間 | 事件 | 攻擊階段 | 攻擊者成熟度 |
|---|---|---|---|
| D1 16:23 | curl偵察掃描 | 資訊蒐集 | 🟢 初階(腳本小子) |
| D2 04:20 | .env路徑掃描 | 弱點掃描 | 🟡 中階 |
| D2 21:36 | 75+大規模漏洞掃描 | 針對性探測 | 🔴 高階(工具化) |
| D3 08:45 | 85次Auth填充攻擊 | 入侵嘗試 | 🔴 高階(自動化) |
| D4~D5 | 零星探測 | 持續監控 | 🟡 中階 |
這份攻擊日誌顯示了一個非常重要的模式:攻擊者不是來一次就放棄,他們會持續回來嘗試不同的方法。
第一天可能是自動化腳本在掃,第二天發現沒收穫,換了更進階的工具來。到了第三天,他們已經決定直接攻擊認證端點——這是整個攻擊鏈中最危險的一步,因為只要找到一個弱密碼,整個系統就可能淪陷。
防禦的關鍵不是擋下一次攻擊,而是確保每次攻擊都被擋下。
五、防禦策略:7層K8s安全防禦架構
好了,講了這麼多驚心動魄的攻擊手法,來點實用的。以下是我推薦的7層K8s安全防禦架構,從外到內層層把關:
攻擊者] --> L1[L1: WAF/API Gateway
Web應用防火牆] L1 --> L2[L2: Rate Limiting
速率限制] L2 --> L3[L3: Authentication
身份驗證 + JWT/OAuth] L3 --> L4[L4: Authorization
授權控制 RBAC/ABAC] L4 --> L5[L5: NetworkPolicy
微隔離網路] L5 --> L6[L6: Pod Security
Pod安全標準] L6 --> L7[L7: Runtime Security
運行時安全監控] L7 --> Audit[Audit Logging
審計日誌 + 告警] style Internet fill:#ff6b6b,stroke:#c0392b,stroke-width:3px style L1 fill:#2ecc71,stroke:#27ae60,stroke-width:2px style L2 fill:#2ecc71,stroke:#27ae60,stroke-width:2px style L3 fill:#3498db,stroke:#2980b9,stroke-width:2px style L4 fill:#3498db,stroke:#2980b9,stroke-width:2px style L5 fill:#9b59b6,stroke:#8e44ad,stroke-width:2px style L6 fill:#9b59b6,stroke:#8e44ad,stroke-width:2px style L7 fill:#e74c3c,stroke:#c0392b,stroke-width:2px style Audit fill:#f39c12,stroke:#e67e22,stroke-width:2px
Layer 1 — WAF / API Gateway
你的API Gateway已經做得很好(全數擋下401),但還可以強化:
- 啟用OWASP Core Rule Set (CRS) 來阻擋已知攻擊模式
- 設定IP信譽過濾,阻擋已知惡意來源
- 對
.env、/debug、/admin等敏感路徑直接回傳404而非401(讓攻擊者無法確認路徑是否存在)
Layer 2 — Rate Limiting
這在K8s環境中可以透過多種方式實現:
# 使用 NGINX Ingress 的速率限制配置範例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/limit-rps: "10"
nginx.ingress.kubernetes.io/limit-rpm: "100"
nginx.ingress.kubernetes.io/limit-whitelist: "你的辦公室IP"
spec:
rules:
- host: api.yourdomain.com
http:
paths:
- path: /auth
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 80
對於 POST /auth/signin 這類高風險端點,建議每IP每分鐘不超過5~10次請求。
Layer 3 — Authentication + JWT/OAuth
從你的日誌可以看到,缺少JWT的請求都被擋下了——這很好!但要確保:
- JWT使用非對稱加密(RS256/ES256)而非對稱加密(HS256)
- Token有效期不要太長(建議15~30分鐘)
- 實作Refresh Token機制
Layer 4 — Authorization (RBAC)
很多人問:「K8s本身的RBAC不是只能管K8s資源嗎?應用層的授權也要管?」
對,但如果你把K8s RBAC做好,至少可以防止Pod被攻擊後橫向擴散:
# 禁止Pod存取K8s API的Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
name: restricted-sa
namespace: production
automountServiceAccountToken: false # 關鍵!關閉自動掛載
---
# 如果非要用API,只給最小權限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"] # 只允許讀取,不允許寫入
Layer 5 — NetworkPolicy(微隔離)
這是最多人忽略的一層!預設情況下,K8s叢集內所有Pod可以互相通訊——這代表只要入侵一個Pod,攻擊者就能掃描整個叢集。
# 預設拒絕所有流量(最安全)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 只允許前端Pod存取API Pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api-service
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Layer 6 — Pod Security Standards
K8s v1.25+ 推薦使用 Pod Security Admission 來取代舊的 PodSecurityPolicy:
# 在Namespace層級設定Pod安全標準
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
restricted 等級會禁止privileged容器、禁止host network、禁止root權限執行等——這些正是挖礦軟體最常用的手法。
Layer 7 — Runtime Security(Falco + Audit Logging)
最後一層,也是你的最後一道防線。當前面六層都被突破了,Runtime Security是你的救命稻草。
推薦使用 Falco — 雲原生運算基金會(CNCF)的運行時安全專案:
# Falco 規則範例:偵測容器內執行Shell
- rule: Terminal shell in container
desc: A shell was spawned in a container
condition: >
spawned_process
and container
and shell_procs
and not user_expected_terminal_shell_in_container_conditions
output: >
Shell spawned in container (user=%user.name
%container.info
shell=%proc.name
cmdline=%proc.cmdline)
priority: WARNING
tags: [container, shell, mitre_execution]
K8s Audit Logging 也要啟用——這可以讓你在攻擊發生後完整還原現場:
# kube-apiserver 啟動參數
--audit-log-path=/var/log/k8s-audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100
六、結論:從被動防禦到主動狩獵
回到一開始的情境——5月8號下午4點23分,你的API Gateway擋下了第一次攻擊。
接下來的三天,攻擊者換了四種劇本、發出了超過170次請求、輪換了多種User-Agent、鎖定了從Inngest到Flowise的現代技術棧——但你的系統始終回傳401。
這代表你的基礎防護做得不錯。但真正的問題是:
- 你知道攻擊者是誰嗎? — 有沒有IP信譽分析?
- 你知道他們從哪裡來的嗎? — 有沒有GeoIP阻擋?
- 如果哪天401變成了200,你多久會發現? — 有沒有即時告警?
- 你的Pod被入侵後,能在幾分鐘內擴散到整個叢集? — 你的NetworkPolicy有設嗎?
K8s安全不是一個配置、一個工具就能搞定的事。它是從程式碼到基礎設施、從開發到維運、從人為政策到自動化防禦的完整閉環。
最後送你一句話:安全不是一個產品,而是一個過程。
你的API Gateway很棒,日誌記錄也很完整——但真正的安全,是從這些日誌中學習、調整、進化。下一次攻擊來臨時,你會比這一次準備得更充分。
準備好了嗎?你的K8s安全升級,就從今天開始。
