Contents

nodejs event stream被植入比特幣小記

2018 年 11 月,npm 生態系爆發了一起重大的供應鏈攻擊事件:知名套件 event-stream 被植入惡意程式碼,針對特定比特幣錢包竊取私鑰。這起事件引發了整個開源社群對軟體供應鏈安全的重視。

事件背景

event-stream 是一個用於處理 Node.js 資料流的工具套件,週下載量超過千萬次,被大量專案依賴。

攻擊時間線(2018 年)

  1. 9 月:原作者 Dominic Tarr 因為忙碌,將套件的維護權轉交給一個名為 right9ctrl 的新帳號
  2. 10 月:新維護者發布了惡意版本 3.3.6,加入了 flatmap-stream 這個依賴套件
  3. 11 月:研究者 FallingSnow 在 GitHub 上發現並公開了這個問題
  4. 同日:npm 緊急下架惡意版本,發布修復版本

攻擊手法

攻擊者的手法非常精巧,分為幾個層次:

  1. 取得維護權:透過社交工程,讓原作者相信自己可以接手維護
  2. 加入惡意依賴:在 event-stream 中悄悄加入 flatmap-stream 套件
  3. 混淆惡意程式碼:惡意程式碼藏在 flatmap-stream 中,且為加密形式,只有在特定條件下才會執行
  4. 定向攻擊:只針對 copay(Bitpay 的比特幣錢包應用)的使用者,竊取私鑰

惡意程式碼的觸發條件(偽代碼):

1
2
3
4
// 只有在特定套件(copay-dash)存在時才執行惡意邏輯
if (process.env.npm_package_description === "A Secure Bitcoin Wallet") {
    // 竊取錢包私鑰並傳送到遠端伺服器
}

如何確認是否中標

使用以下指令檢查專案是否使用了被污染的版本:

1
2
3
4
5
# 檢查本地專案的依賴樹
npm ls event-stream flatmap-stream

# 檢查全域安裝的套件
npm ls -g event-stream flatmap-stream

若輸出結果包含 flatmap-stream,則可能受影響。被污染的版本是 event-stream@3.3.6flatmap-stream@0.1.1

1
2
3
4
5
# 使用 npm audit 掃描已知漏洞
npm audit

# 自動修復(若有可用的安全版本)
npm audit fix

供應鏈安全防護措施

這起事件提醒了開發者幾個重要的安全實踐:

1. 使用 lock file

提交 package-lock.json(npm)或 yarn.lock 到版本控制,確保所有人安裝的都是完全相同的版本:

1
2
# 安裝時嚴格遵守 lock file
npm ci  # 比 npm install 更嚴格,適合 CI/CD 環境

2. 定期執行 npm audit

1
2
# 在 CI/CD pipeline 中加入安全掃描
npm audit --audit-level=high

3. 使用 Snyk 或 Dependabot

自動監控依賴套件的安全漏洞,發現問題時自動提 PR。

4. 最小化依賴

  • 評估每個依賴的必要性,避免引入不需要的套件
  • 考慮將功能用少量程式碼自行實現,而非依賴外部套件

5. 監控套件的維護者變更

重要依賴發生維護者轉移時要特別謹慎,這是常見的攻擊入口。

參考資料