舊文整理
面向非技術人員
用戶可利用Mt.Gox系統的漏洞重復提取比特幣到個人錢包,所以Mt.Gox 暫停比特幣提款。
舉個例子:
用戶張三在Mt.Gox有50個比特幣,張三提取這50個幣到自己的本地錢包。Mt.系統發出一個支付交易,約10分鐘后,交易完成。張三的錢包余額多了50個幣,MT的錢包余額少了50個幣。但是在這個支付交易在中途被修改了交易的ID號。現在張三再次請求提取50個幣,Mt竟然不檢查自己的錢包是否少了幣,僅依據自己記錄的交易ID號沒有被確認,就認為上次交易失敗,從而再次發給張三50個幣。
這聽取來很搞笑,但這就是MT出現的問題。現在Mt.Gox在忙于檢查自己的賬本,看看那些支付交易受騙了,同時也看看哪些用戶是騙子,看看能否通過法律追回被騙的幣。
面向技術人員
事件的起因是:比特幣的一個被稱為“交易可鍛性”(Transaction Malleability)的瑕疵。
這是比特幣系統的一個小問題,不影響比特幣網絡的完整性,不算是一個漏洞,兩年多前就被提出并討論過,技術上有相應的應對措施。Mt.Gox顯然忽視了這個問題,沒有采取相應的技術措施,導致了此事件。
比特幣世界很多名詞都是比喻,如挖礦,礦機,礦工等,這里的“可鍛性”也是個比喻,
在討論“交易可鑄鍛性”前,我們先看看“金幣的可鑄鍛性”,一個金幣在使用中,被人用錘子砸了幾下,凹了幾處,變得不是很圓。這個金幣的本質含金量沒變,只是外觀看上去與標準的金幣有些不同,這個金幣依舊是一個被認可的金幣。這就是“金幣的可鍛性”。
“交易可鍛性”指的是,比特幣支付交易發出后、確認前可被修改(準確說是被偽造復制),用戶簽名過的信息不能更改。
原因是:用戶簽名的內容不是整個交易的信息,只是交易信息中的核心重要信息,如發送方,接受方,金額等。在不改變用戶簽名內容的前提下,對交易信息做些微調,可產生一個全新的交易字符串,由此產生新的交易HASH值,也就是交易ID Transaction ID, 由于簽名內容沒有更改,修改過的“交易”可通過挖礦程序確認寫入塊鏈(block chain)。
對交易信息的微調有兩種方式,
第一,修改簽名字符串本身。首先,多數挖礦程序是用openssl 庫校驗用戶簽名,而openssl兼容多種編碼格式,還有,就是橢圓曲線數字簽名算法(ECDSA)本身,簽名(r,s) 和 簽名(r,-s(mod n))都是有效的。所以,對簽名字符串本身的表現方式做些調整,依舊是有效簽名。
第二,修改交易信息中的scriptSig的值,scriptSig中含有簽名字符串,scriptSig本身不含在簽名內容里。scriptSig做些適當的修改,也不影響交易信息的驗證。
注意,以上兩種調整,都不會改變簽名的核心內容,但是卻產生一個新的交易字符串,由此產生新的交易HASH值。交易的本質內容(發方、收方、金額)沒變,外觀看上去確變了。
從交易信息發出到最終確認通常有約10分鐘的時間,時間上,偽造的交易信息產生于正品交易信息之后。由于挖礦程序的確認過程是一個隨機的過程,后產生的偽造的交易信息可能首先通過確認,這時正品交易信息反而被認為是重復支付被丟棄。發送方看到自己發的正品交易沒通過校驗,誤以為支付失敗(其實已成功支付),再次發送交易,支付方就支付了多余的幣。
Mt.Gox通過公司的錢包對用戶的比特幣集中管理,同時通過總賬本記錄每個用戶比特幣的存取,依據這個賬本計算每個用戶賬戶上的比特幣余額。
而其記賬依據是基于交易HASH值,也就是交易ID (Transaction ID)。這就導致其可被攻擊者重復提幣。
Mt.Gox發現其錢包的幣在不斷減少,而支付交易又常常失敗。意識到有點不對勁,只有暫停提幣。
攻擊細節:
1,攻擊者需要一個性能普通的礦機聯入比特幣網絡,以便獲取和發送交易信息(比特幣網絡是開放的,誰都可以聯入)
2,登錄Mt.Gox平臺上,請求提幣到個人錢包。Mt.Gox隨后向網絡廣播支付交易信息。
3,Mt.Gox發出的支付交易信息,通常要等約10分鐘才能被確認。攻擊者得到這個待確認的交易信息,偽造出一個簽名內容不變而ID不同的支付交易,隨后向網絡廣播這個偽造交易。如果正品交易先通過挖礦確認,則攻擊失敗。如果偽造交易先通過挖礦確認,則正品交易被丟棄,攻擊成功。
事實上,如果攻擊者太過招搖,可以偽造多個交易信息,增加率先通過確認的幾率。
4,向Mt.Gox請求再次提幣,Mt.Gox看到正品交易沒有成功寫入(block chain)。誤以為支付失敗,再次發送交易。攻擊者行騙成功。
啟示
無論是交易平臺還是個人,不能僅依靠交易的HASH值判斷一個交易是否成功。
最可靠的辦法是:每筆交易后,檢查錢包余額的增減來判斷支付交易成功與否。
啟示更新(2017年3月)
從技術角度看:
1. 寫入區塊鏈,經過多次確認的交易ID,不會變,可信賴。(至于確認次數是另一個話題)
2. 未寫入區塊鏈的交易ID,可能發生變化,不可信賴。
站在用戶的角度看:
1,對收款方沒有影響。
2,對于支付方,如果是人工手動支付,通常也沒有影響,因為人工操作,發生異常會被警覺。
如果允許用戶自動提款,這個時候就要注意這個“交易可鍛性”的問題。這個主要影響交易所,普通用戶通常不會讓他人自動提款。經過Mt.Gox 事件后,很多交易所都使用人工操作來處理用戶提款。