這篇文章要來談重複計數(multiple counting)的漏洞,其包括了兩個變種。這篇文章的目標是對上述的漏洞提供完整的細節,解釋這是如何被用來攻擊線上服務、商家與交易所,並且 Monero (開發)社群是如何處理這個漏洞。
重複計數漏洞的兩個變種存在於子地址(subaddress)功能中,這功能用了個不同的交易金鑰程式碼架構。第一個漏洞的變種簡單來說就是沒有對重複的公鑰進行檢查,因此攻擊者可以重複將同份交易公鑰包含在交易中,這結果導致了接收者的錢包會回報收到了x倍於其真正收到的的交易數量(x是代表收到幾次交易金鑰的一個整數),所有用來回報收到交易的指令(如show_transfers (CLI), get_transfers (RPC))都被此漏洞影響。但是餘額並沒有受到影響,錢包依舊會回報正常的資金餘額。可惜的是,大多數的交易所都是利用 get_transfers 或 get_payments RPC指令在運作,因此重複的交易公鑰將會導致計算出錯誤的金額。
不幸的是,這個漏洞的變種非常容易被使用,攻擊者可以輕易的利用在 src/cryptonote_core/cryptonote_tx_utils.cpp 中的 add_tx_pub_key_to_extra(tx, txkey_pub) 來附加重複的交易公鑰。實際上的運作如下: 攻擊者在 src/cryptonote_core/cryptonote_tx_utils.cpp 中附加了譬如三次的金鑰,因此在他的交易中就會出現四筆相同的交易公鑰。這導致了當攻擊者將一筆 1 XMR 的交易發送至目標交易所的時候,交易所很有可能就會計帳給攻擊者 4 XMR 的餘額,於是攻擊者就可以領出4 XMR的資金而惡意盜取了交易所 3 XMR 的資金。若交易所沒有進行對餘額與進出交易金額的核對或檢查熱錢包的異常狀況,那麼攻擊者基本上可以重複上述攻擊直到交易所的熱錢包被領空或更慘的是到整個交易所的資金耗盡為止。
本漏洞的第二個變種,在 HackerOne 上有完整的報告,原理是程式碼沒有對假冒的交易公鑰進行檢查。因此攻擊者可以利用變造後的交易公鑰欺騙錢包使其將交易輸出計算為實際收到的兩倍,而與第一個變種類似,錢包餘額並不會受到此漏洞影響。 本漏洞的第一個變種最早是在 GitHub 上被提出並迅速地在這份 PR 中被 moneromooo 修正。 不幸的是,這個漏洞的嚴重性被低估,直到 (i) 一個交易所的 Monero 分叉幣被利用此手法攻擊 (ii) 在 HackerOne 上的一位資安研究員(jagerman)提供了完整報告關於如何利用此漏洞竊取交易所資金。而漏洞的第二變種是由 HackerOne 上的 phiren 所提出,並也被快速的在此份PR中修正。兩份修正都已由 fluffypony 合併在 v0.12.3.0 的發布版本中。
在 v0.12.3.0 定版之後,筆者(dEBRUYNE)與其他開發者們私下地盡可能通知了所有的交易所、線上服務、與商家。但顯然這不是個最好的方法: (i)這不可避免地排除了與我們沒有聯絡管道但又是 Monero 生態中重要的對象。(ii) 這可能導致差別待遇的觀感。此外,這個漏洞消息應該要於公開地郵件列表中發布,但可惜的是並沒有,我們應要能從這樣的疏忽中記取教訓。我們是一個 Monero 的社群,應該要找出一個更順暢的資安弱點處理流程(譬如回報重要漏洞給交易所、線上服務與商家的的流程),一個只提供給交易所、線上服務與商家的”祕密”郵件列表或許符合這個概念。加上需要一些繁瑣的認證程序或許會比公開的郵件列表安全,因為聰明的攻擊者會毫不猶豫地訂閱這份郵件列表。
總而言之,在錢包中的一個重要漏洞,在初期被低估其嚴重性,導致在攻擊者得以在 Monero 生態中的竊取交易所的資金。幸好,這個漏洞僅限於影響錢包軟體中的計帳功能,而在交易協定和貨幣發行量上沒有受到影響。我們必須在此次事件中記取教訓去改進使我們在未來遇到類似漏洞時能夠阻緩其帶來的影響。此外,這個事件也是一個重要的提醒,加密貨幣與其軟體都還是在發展中階段,容易出現(重大)漏洞。因此對於提供服務的單位,盡可能納入完整性檢查是比較好的(替如檢查交易總和是否吻合真實帳戶餘額),此外,Monero 開發社群也正在研究加入這類核對功能至 RPC 錢包中的可行性。
註記: 1. 一份包含著50份相同交易公鑰的交易範例: (01ede13f013833f8aef14a9397b83fd5171833ab55bc480104dd6ba86ca8f13558) 可以在此查看這份交易內容。
本篇消息譯自核心開發團隊網站: https://getmonero.org/2018/09/05/a-post-mortum-of-the-multiple-counting-bug-2018-09-05.html