Coldcard 駭客事件解析:RNG 缺陷、受影響韌體與遷移方案

閱讀時長 5 分鐘

Coldcard 駭客事件解析:RNG 缺陷、受影響韌體與遷移方案

首頁>Industry Insights>Coldcard 駭客事件解析:RNG 缺陷、受影響韌體與遷移方案
分享

沒有人動過任何裝置。

沒有釣魚郵件。沒有惡意應用程式。沒有被竊的筆電,沒有外洩的備份,沒有輸入到假冒支援頁面的助記詞。7 月 31 日在 Coldcard 駭客事件中損失比特幣的人,按照標準建議做對了每一件事:私鑰離線生成、使用專用硬體、使用一台完全建立在「不信任任何其他東西」這一聲譽之上的裝置。

在 01:31 至 01:56 UTC 之間,CoinDesk 測得第一波掃蕩:594 BTC 在三個區塊的時間窗口內、透過 1,324 筆交易、從約 500 個錢包中被轉走。總共二十五分鐘。隨後幾天又出現更多波掃蕩。

其中有一點會改變你接下來的作法:攻擊者從來不需要存取任何人的 Coldcard。他們是從零推導出助記詞的。

Coldcard 駭客事件中真正被攻破的是什麼

先從助記詞是什麼說起,因為整個故事都建立在這一個事實上。

你的 12 或 24 個單字並不是密碼。它們是一個非常大的數字,以人類抄寫時不易出錯的格式寫下。保護你的正是這個數字。而這個數字之所以安全,唯一的原因是它從一個大到沒有人能搜尋的池子中、以無法預測的方式被選出。

這個池子以位元衡量。每增加一個位元,池子就擴大一倍。一個正確生成的種子攜帶 128 位元的不可預測性,約合 340 undecillion(3 後面跟 38 位數字)種可能。任何現有的機器、或任何工程路線圖上的機器,都無法窮舉這麼大的池子。這就是自託管之所以安全的全部基礎。

因此,硬體錢包最重要的工作發生在它生命的最初幾秒、在你簽署任何東西之前:它必須生成一個真正無法預測的數字。Coldcard 為此配備了專用硬體——一個從物理雜訊取樣的真亂數產生器。

而在受影響的韌體上,五年時間裡,這個硬體從未被呼叫過。

一個編譯旗標如何把硬體錢包變成可預測的錢包

起因小到一句話就能說完,而這正是它值得理解的原因。

Coldcard 的程式碼定義了一個名為 MICROPY_HW_ENABLE_RNG 的設定並將其設為零,因為他們使用的是自己的硬體產生器,而不是 MicroPython 內建的那個。一個在 2021 年遷移期間引入的配套密碼學函式庫,檢查的是該設定是否存在,而不是它是否被開啟。它存在,值為零。檢查通過了,本應阻止建置的安全錯誤從未觸發,程式碼便悄悄落到 MicroPython 的軟體後備路徑上。

Coinkite 自己的話說:"The guard used #ifndef, which tests whether MICROPY_HW_ENABLE_RNG is defined, rather than whether its value is nonzero. We defined that macro as zero, so the #error did not stop the build."(該防護使用了 #ifndef,它檢測的是 MICROPY_HW_ENABLE_RNG 是否被定義,而非其值是否非零。我們將該巨集定義為零,因此 #error 並未阻止建置。)

這個軟體後備並不隨機。Block 的分析顯示,它由晶片的硬體 ID 加上一個計時器值啟動,再由即時時鐘暫存器補充,而這些值只讀取一次、從不更新。Coinkite 對此的描述是種子「主要來自裝置與計時狀態」。這些沒有一樣是秘密。給這樣的產生器輸入相同的起始值,它每次都會可靠地、按設計產出相同的輸出。

於是池子縮小了。在 Mk2 和 Mk3 裝置上,它塌縮到大約 40 位元,約合 1.1 兆種可能。一兆聽起來很大,其實不然:一台還不錯的筆電就能窮舉完,一個 GPU 叢集幾小時就能搞定。

Mk4、Mk5 和 Q 會混入來自安全元件的額外熵,而已公開的兩份分析正是在這裡出現分歧。Coinkite 估計這些型號的有效搜尋空間約為 72 位元。Block 發現重新播種只從安全元件取四個位元組,僅替換產生器內部狀態的一個字、其餘原封不動,按其估算「最多留下 2^32 條可安全區分的輸出流」。Block 謹慎表示尚未完成完整的實證測試來確認可利用性,並建議讀者等待 Coinkite 一旦發布的最終報告。

請把這一分歧當作仍在進行中的爭論。如果你持有 Mk4、Mk5 或 Q,較穩妥的作法是採用較悲觀的假設。

接下來的攻擊就是機械性的了。生成候選種子,推導每個種子會產生的比特幣地址,把這些地址與公開區塊鏈比對,然後掃走有餘額的地址。區塊鏈是公開的,因此這一切不需要碰到任何錢包、任何網路連線或任何人。

螢幕上沒有任何東西能提醒你

這個細節值得你記得比韌體版本號更久。

一個弱的亂數產生器產出的結果看起來並不弱。設定過程中 Coldcard 螢幕上顯示的單字看起來和正確生成的種子一模一樣,因為它們格式正確、校驗和正確、統計上毫無異常。可預測產生器的輸出可以輕鬆通過隨機性測試。它看起來是隨機的,只是它的結果早已被一個任何人都能重建的起始值決定。

你再小心也發現不了這個問題。檢查備份、驗證地址、先試一小筆交易——這些都發現不了。所有這些檢查都會通過。

該漏洞由 Block 的比特幣工程與安全團隊發現,他們透過韌體分析追蹤到它,並在公開發布前向 Coinkite 披露。它自 2021 年 3 月的韌體 4.0.1 起就一直隨產品發布。

Coldcard 駭客事件究竟影響哪些人

這比頭條數字更重要,因為該漏洞只會波及在受影響韌體上生成的種子。根據 Coinkite 的公告

受影響,請遷移種子:

  • Mk2 和 Mk3,韌體 4.0.1 至 4.1.9。約 40 位元。請視為緊急。
  • Mk4 和 Mk5,低於 5.6.0。約 72 位元。
  • Q,低於 1.5.0Q。約 72 位元。

不受此漏洞影響:

  • TAPSIGNER、OPENDIME 和 SATSCARD,它們執行不同的程式碼庫。
  • Mk1。Coinkite 的公告沒有列出它的歸屬,但 Block 的分析發現 Mk1 至 v3.2.2 直接使用 STM32 硬體產生器,該回歸直到 v4.0.0 才引入。
  • 使用至少 50 次公平、獨立、私密擲骰生成的種子。Coinkite 表示這些「僅就這一 RNG 問題而言」沒有風險,並要求你在遷移前閱讀其另行提供的指引,而不是想當然地認為自己沒事。

在另一台裝置上生成並匯入 Coldcard 的種子應當也不在此列,因為該漏洞位於生成環節而非儲存或簽署環節。Coinkite 的公告並未直接談及匯入的種子,所以這是機制推斷而非官方的安全確認。

更新韌體無法修復已經存在的種子。那個弱數字多年前就已一次性生成,而它現在仍然是保護你幣的數字。修補程式阻止的是新種子被錯誤生成,它無法追溯。

持有 Coldcard 該怎麼做

Coinkite 的指引,按順序:

  1. 先從官方來源更新到修復後的韌體,然後再生成任何新內容。Mk2 和 Mk3:4.2.0 或更高版本。Mk4 和 Mk5 Standard:5.6.0 或更高版本。Q Standard:1.5.0Q 或更高版本。Edge 版本:6.6.0X,Q 為 6.6.0QX。
  2. 在更新後的裝置上生成一個全新的種子。在 Mk4、Mk5 和 Q 上,修復後韌體自身的種子生成已足夠,擲骰可選。
  3. 記錄並核驗新的備份、錢包指紋和一個收款地址。如果你設定了通關密語(passphrase),請與助記詞分開存放。
  4. 在轉移剩餘資金之前,先發送一筆小額測試交易。
  5. 保留舊備份,直到遷移完成並確認。

最後這一步值得讀兩遍。發生此類事件後的本能是立刻銷毀舊備份,而如果在遷移中途出任何差錯,這種本能會讓你損失資金。舊種子已外洩,但在資金確認進入新錢包之前,它仍是唯一能觸及資金的東西。事後再淘汰它,而不是在過程中。

如果你的 Mk3 上的種子是 2021 年以來任何時候生成的,請在今天、而不是這個週末完成第一和第二步。四十位元真的很低。

關於你見過的那些報導數字,說一句。Galaxy Research 統計到,截至 8 月 4 日,約 7,300 個地址共被取走 1,596 BTC。TRM Labs 公布的數字約為 1,816 BTC(約合 1.16 億美元),涉及超過 5,200 個地址。兩家機構都稱數字為初步統計,各自撰寫時資金仍在流動,而 Coinkite 尚未公布自己的損失估計。預計總額還會繼續變化。上述韌體指引沒有爭議。

自託管中沒有人能檢查的部分

大多數面向持有者的安全建議針對的是你能觀察到的東西。發送前核對地址。驗證網域。不要把助記詞輸入任何東西。從製造商處購買,而不是從第三方市集購買。這些都是好建議,而它們全都關於在錯誤發生時當場抓住它。

金鑰生成不同。它只發生一次,不產生任何關於自身品質的證據,而當它出錯時,系統裡沒有任何訊號告訴你。你的錢包正常運作。你的交易正常確認。你的備份能正確恢復。這個失敗完全無聲,直到它不再無聲。

這才是這裡真正的教訓,而且它遠遠超出一家製造商的範圍。任何錢包,無論硬體還是軟體,都在就隨機性做一個你自己無法稽核的承諾。你信任的是一個你永遠看不到的建置流程。

這指向了當這種信任被錯付時,真正能減少損失的東西:一個單獨的秘密本身值多少錢。

在這次事件中損失比特幣的每一個人,都是在同一筆交易中失去全部。不是因為攻擊者多高明,而是因為一個數字就是整個安全模型。猜中數字,就擁有錢包。沒有第二道關卡需要越過。

當沒有任何單一秘密等於整個錢包時,什麼改變了

CoinWallet 支持多方安全計算(MPC)。不是一條助記詞承載一切,而是把簽署能力拆成由不同地方持有的多個分片,必須有一定數量的分片湊齊,交易才能被批准。

任何單一分片都無法動用你的加密資產。需要所需數量的分片協同運作,才能批准任何交易。一把私鑰、一台裝置、一個被竊的分片,永遠不夠。

在實務上,這意味著你可以建立 MPC 錢包並與他人共同管理資產、透過邀請碼加入錢包、匯入既有的金鑰分片,並透過閾值門控流程更換遺失的裝置,而不是依靠一條能解鎖一切的單一恢復短語。

現在是誠實的部分,因為這個事件值得誠實:MPC 並沒有取消隨機性要求。金鑰分片也要生成,生成品質依然重要。拆分做到的,是消除那個可被猜出的單一秘密。推導出一個分片的攻擊者只擁有一個分片,而一個分片簽不了名。失敗必須發生在不止一處你才會有損失,而要安排這一點,比一個弱數字困難得多。

比特幣上的多重簽名透過另一條路徑給你類似的性質:幾把獨立金鑰、要求一定數量的簽名,沒有一條交出一切的短語。

建議其實沒有變,只是向前挪了一步。多年來給持有者的訊息是把你的金鑰從交易所移到自己的硬體上,那個訊息是對的。這次事件補上了下一句:把金鑰放到自己的硬體上值得做,但這不等於安全,因為你只是把信任從一家可能被駭的公司,轉移到了一個五年來廠商之外無人讀過的建置流程上。

CoinsDo Team

作者

CoinsDo Team

business@coinsdo.com