04 月 11 日凌晨 00:17,PeckShield 態勢感知平臺監測到 TCX1Cay… 開頭的黑客,創建了名爲 BTTx, token id 爲 1002278 的 TRC10 token,並於凌晨 00:25 至 01:00 之間向多個地址轉入 4,000 萬個 BTTx 代幣,這多個地址對 TXHFhq… 開頭的 BTTBank 理財類合約實施攻擊。

原文標題:《波場假幣攻擊全過程:BTTBank 理財合約遭黑客假 BTT 攻擊》

BTTBank 項目介紹

BTTBank 又名 TronBank BTT, 是屬於 TronBank 旗下的一款專屬於 BitTorrent (BTT) – The token that will enable blockchain mass adoption BTT token 的投資產品,根據官網 TronBank 介紹:

TronBank BTT 的智能合約將爲您產生每天 3.6 – 6.6%的投資收益(取決於你購買的產品計劃),自動發放到你的收益餘額中。舉例,購買 4.6% 收益計劃,21 天你即可獲得超過 100% 收益。收益每秒都會計算,你甚至每秒都可以提取收益或重新投資。當您重新投資收益時,投資金額會增加,可以更快的獲得更多收益。

其產品界面如下(由於當前 BTTBank 在維護中,主站無法打開,援引 TronBank 明星產品 TRX 的投資圖片,詳見 TronBank):

PeckShield 深入代碼層面分析,黑客究竟如何盜走 1.7 億 BTT?

其理財過程大致如下:

1、用戶根據收益率和投資期限購買相應的理財產品;
2、投資期限到期之後,用戶提現理財產品到自己的錢包。

使用上,和當前的各類 P2P 理財產品類似,用戶的使用門檻僅在於一個 TRON 錢包,但從產品收益率來看,這個資產回報率還是相當可觀的。

攻擊回溯

攻擊事件簡述

去年年底,波場孫宇晨發起 12 號提議,即符合波場 TRC10 規範的 Native token 的名字將不再唯一,涉及到 TRC10 token 的轉賬等操作將使用 ID 來代替。這使得波場創建 token 的流程變得簡單易上手,然而卻帶來一個潛在的威脅,一旦合約疏於檢查 token id 的匹配性,就會存在假幣攻擊的可能。簡而言之,本次 BTTBank 遭受攻擊正是因爲缺乏 token id 的一致性驗證造成的。

背景知識

TRON 中的 token 分爲幾種規範:

  • TRX
  • TRC20
  • TRC10

其中,TRX 爲 TRON 的平臺幣,類似於 Ethereum 中的 ETH。

而 TRC20 是與 Ethereum ERC20 兼容的 token,實質是一種可編程的智能合約,由用戶通過智能合約創建 token 之後,其 token 的轉賬、發送等操作均在智能合約內部完成,對於一般的小白用戶來說,ERC20/TRC20 使用過於複雜,不便於上手使用。

故此,TRON 中引入了 TRC10 token, 這是一種可以由用戶直接操控的 token,每一個自然用戶支付 1024 TRX 便可創建一個 TRC10 token,同時一個用戶只能創建一個 TRC10 token。每一個 TRC10 token 在創建之後,由系統分配一個唯一 ID (即 token id),這是一個從 1,000,001 開始往後自增的整數,一個 tokenId 標識一個唯一的 token,當前 TRON 平臺上共有 1850+(2019-04-12)個 TRC10。

爲了提高 TRC10 的流動性和使用價值,TRON 平臺在 Odyssey 3.2 版本之後,使能了在智能合約內部轉賬 TRC10 token 的功能,參考 TRC10 Transfer in Smart Contracts, 其示例代碼如下所示:

640 (1).jpeg

上述代碼簡單解釋如下:

1、transferTokenTest() 接口內部用於轉賬 TRC10 token,接口調用方可以通過 address.transferToken(uint256 tokenValue, trcToken tokenId) 往 address 轉賬數量爲 tokenValue 的 token id 爲 token id 的 TRC10 token;
2、msgTokenValueAndTokenIdTest() 接口表明,調用者可以直接在發送的 message 中加入 token id 和 tokenvalue 字段,這也說明了 TRC10 是 TRON 平臺上的一等公民,屬於內置類型,與 TRC20 通過函數參數的形式來表徵 token 價值是完全不同的;
3、getTokenBalanceTest() 通過 token id 獲取賬號的餘額。

由此可知,TRC10 token 可以在智能合約內部通過 token id 完成轉賬,TRC10 token 作爲價值承載者,在智能合約內部即反映在 token id 的差異上。

因此,合約開發者在處理 TRC10 轉賬相關邏輯時,需要特別注意 token Id 的有效性和真實性。

攻擊事件

PeckShield 安全人員在分析 BTTBank 合約時,發現其合約源碼實現中存在致命漏洞,可導致項目方資金受損。

下圖爲黑客攻擊的原過程:

640 (2).jpeg

1、黑客先行創建一個名爲 BTTx 的 TRC10 token;
2、黑客往一批自己控制的賬號中轉入 4,000 萬個 BTTx token;
3、通過控制的賬號往 BTTBank 合約發起數次攻擊;
4、最後順序將 BTT 提取到控制的賬號中。

下文從 BTTBank 投資及贖回的過程還原本次 BTT 假幣攻擊的全過程。

投資

投資的核心代碼如下:

640 (3).jpeg

public 接口的 invest( ) 提取 msg.tokenvalue ,並調用 private 的 invest( ) 函數完成投資的過程,invest( ) 內部計算並保存用戶這一次的投資數量、時間等信息到合約的內部資產賬單上。值得注意的是,這裏 invest( ) 只提取了 msg.tokenvalue,這裏並沒有提取 msg.tokenid,也沒有驗證 msg.tokenid 是否屬於 BTT Token 的 token id(爲 1002000)。

前面我們提到 BTTBank 是一款投資理財類 DApp,用戶存入 BTT token,資產到期之後,再贖回投資的 BTT 和對應的利息,在這裏並沒有檢查是否是真正的 BTT,也就是不論你投資的阿貓阿狗幣,都被認爲是 BTT token。

提現

提現的核心代碼如下:

640 (4).jpeg

贖回的過程比較簡單,先從合約的內部投資賬單上計算用戶已經到期的投資金額,並將這一部分投資金額轉回給用戶,注意:msg.sender.transferToken(withdrawalAmount, BTT_ID) 中是固定的 BTT_ID 即 1002000.

至此,用戶投入 BTT,收穫 BTT;而黑客投入 BTTx, 收穫 BTT,一個完美的『狸貓換太子』過程。

防禦策略

PeckShield 安全人員在此提醒廣大開發者,雖然 TRC10/TRC20 都是 token, 但兩者在 TRON 平臺上有着本質的差異性,若要在智能合約內部轉賬 TRC10,一定要檢查所轉移的 TRC10 對應的 token id 是否爲預期值。針對上例,可將投資代碼增強如下:

640 (5).jpeg

另外,PeckShield 安全人員根據上述的代碼樣式分析 TRON 平臺上其它類 BTTBank 合約時,也發現了相似的問題。在此,PeckShield 安全人員提醒在進行智能合約開發的時候,雖然複用現有代碼可能會帶來開發功能上面的便利,但也須注意可能帶來的安全風險。