希望該最佳實踐可以幫助更多的開發者打造安全可靠的智慧合約。
作者: Johan, 慢霧安全團隊
編輯: Lisa
排版: Liz
封面: Photo by Eyestetix Studio on Unsplash
TON(The Open Network) 是一個由 Telegram 團隊最初設計和開發的去中心化區塊鏈平台,一經上線就獲得了關注。 TON 的目標是提供一個高效能和可擴展的區塊鏈平台,以支援大規模的去中心化應用 (DApps) 和智能合約,關於 TON 的基礎知識可查閱初識 TON:帳號、Token、交易與資產安全。
值得注意的是,TON 與其他區塊鏈有著截然不同的架構,TON 的智能合約除了主要使用 FunC 語言來編程,也有使用更高級的 Tact,或更底層的 Fift。這些都是原創程度很高的語言,因此,確保智慧合約的安全性是關鍵。
慢霧安全團隊整合吸收了 TON 社區分享的安全開發實踐,並結合自身多年積累的安全審計經驗,發布 “Toncoin 智能合約安全最佳實踐”,旨在幫助開發者更好地理解 Toncoin 智能合約的安全風險,並提供實用的解決方案,以降低潛在的安全威脅。
由於篇幅限制,本文僅羅列「Toncoin 智能合約安全最佳實踐」的部分內容,歡迎大家在 GitHub 上 Watch、Fork 及 Star:https://github.com/slowmist/Toncoin-Smart-Contract-Security-Best -Practices。
Toncoin 智能合約常見陷阱
1. 缺少 impure 修飾符
- 嚴重性:高
- 描述:攻擊者可能會發現"authorize" 函數未標記為 "impure"。缺少此修飾符將允許編譯器在函數沒有傳回值或傳回值未使用時跳過函數的呼叫。
- 攻擊場景:
- 建議:確保函數使用"impure" 修飾符。
2. 錯誤使用修改/非修改方法
- 嚴重性:高
- 描述:"udict_delete_get?" 被錯誤地用"." 而不是"~" 調用,因此實際的字典未被修改。
- 攻擊場景:
- 建議:始終檢查方法是否為修改/非修改方法。
3. 錯誤使用有符號/無符號整數
- 嚴重性:高
- 描述:投票權以整數形式儲存在訊息中。因此攻擊者可以在權力轉移期間發送負值並獲得無限投票權。
- 攻擊場景:
- 建議:在某些場景下,無符號整數更安全,因為它們在發生溢位時會拋出錯誤。僅在確實需要時使用有符號整數。
4. 不安全的隨機數
- 嚴重性:高
- 描述:種子來自交易的邏輯時間,攻擊者可以透過暴力破解當前區塊中的邏輯時間來獲勝(因為邏輯時間在一個區塊的邊界內是連續的)。
- 攻擊場景:
- 建議:在進行"rand()" 之前始終隨機化種子,最好是永遠不要使用鏈上隨機數,因為驗證者可以控製或影響種子。
5. 在鏈上發送私人數據
- 嚴重性:高
- 描述:請記住,所有資料都會儲存在區塊鏈上。
- 攻擊場景:錢包受密碼保護,其雜湊值被儲存在合約資料中。然而,區塊鏈會記錄一切—— 密碼會出現在交易歷史中。
- 建議:不要在鏈上發送私人資料。
6. 漏掉對退回訊息的檢查
- 嚴重性:高
- 描述:使用者傳送"check" 請求時,Vault 沒有退回處理程序或代理訊息至資料庫。我們可以在資料庫中將 "msg_addr_none" 設定為獎勵位址,因為"load_msg_address" 允許這樣做。我們請求 Vault 檢查,資料庫嘗試使用"parse_std_addr" 解析"msg_addr_none",但解析失敗。訊息從資料庫退回 Vault,且操作不是"op_not_winner"。
- 攻擊場景:Vault 在資料庫訊息處理器中包含以下程式碼:
- 建議:始終檢查退回的訊息,不要忘記標準函數引起的錯誤,使您的條件盡可能嚴格。
7. 在競爭條件下銷毀帳戶的風險
- 嚴重性:高
- 描述:不要輕易銷毀帳戶。
- 攻擊場景:你可以存錢,然後嘗試在並發訊息中兩次提款。由於無法保證保留資金的消息會被處理,因此合約帳號可以在第二次提款後關閉。攻擊者之後可以重新部署合約,然後任何人都可以提取未擁有的資金。
- 建議:使用"raw_reserve" 而不是向自己發送資金。考慮可能的競爭條件。小心使用 hashmap 的氣體消耗。
8. 避免執行第三方程式碼
- 嚴重性:高
- 描述:開發者沒有辦法在合約中安全地執行第三方程式碼,因為 CATCH 不能處理 gas 不足的問題,而攻擊者只需提交合約的任何狀態並引發氣體不足即可實現攻擊。
- 攻擊場景:
- 建議:避免在您的合約中執行第三方程式碼。
9. 名稱衝突
- 嚴重性:中
- 描述:Func 變數和函數可能包含幾乎任何合法字元。
- 攻擊場景:"var++"、"~bits"、"foo-bar+baz" 及逗號 "," 都是有效的變數和函數名稱。
- 建議:編寫和檢查 Func 程式碼時,應該使用 Linter 工具。
10. 檢查 throw 的值
- 嚴重性:中
- 描述:每次 TVM 執行正常停止時,它會以退出代碼"0" 或"1" 停止。雖然它是自動完成的,但如果"throw(0)" 或"throw(1)" 命令直接拋出退出代碼"0" 和 "1",TVM 執行可以在意外方式下直接中斷。
- 攻擊場景:
- 建議:不要使用"0" 或"1" 作為 throw 的值。
11. 讀/寫正確類型數據
- 嚴重性:中
- 描述:讀取意外變數的值,並在不應有此類方法的資料類型上呼叫方法(或其返回值未正確儲存)是錯誤的,不會作為「警告」或「通知」被跳過,而是導致無法取到程式碼。
- 攻擊場景:請記住,儲存意外值可能是可以的,但是讀取它可能會導致問題。例如,對於整數變量,錯誤代碼 5(整數超出預期範圍)可能被拋出。
- 建議:密切追蹤程式碼的操作和它可能的返回值。請記住,編譯器僅關心程式碼及其初始狀態。
12. 合約代碼可以更新
- 嚴重性:中
- 描述:TON 完全實作了 Actor 模型,這意味著合約的程式碼可以更改。程式碼可以透過"SETCODE" TVM 指令永久更改,或在執行時間設定 TVM 程式碼暫存器為新的單元值,直到執行結束。
- 攻擊場景:不道德的開發者可能會惡意更新程式碼以竊取資金。
- 建議:注意合約程式碼是可以更新的,確保任何更新都遵循安全實踐,並使用例如治理模型或多簽章批准等機制進行更改。
13. 交易和階段
- 嚴重性:中
- 說明:計算階段執行智慧合約程式碼,然後執行操作(如傳送訊息、修改程式碼、變更程式庫等)。與基於以太坊的區塊鏈不同,如果你預期發送的訊息會失敗,你將看不到計算階段的退出程式碼,因為訊息並不是在計算階段執行的,而是在稍後的操作階段執行。
- 攻擊場景:在操作階段訊息失敗時產生意外行為,導致對交易狀態的錯誤假設。
- 建議:了解每個交易最多包含五個階段:儲存階段、信用階段、運算階段、操作階段和反彈階段。
14. 不能從其他合約拉取數據
- 嚴重性:中
- 描述:區塊鏈上的合約可以駐留在不同的分片上,並由不同的驗證者處理。因此,開發者無法按需從其他合約中拉取資料。通訊是異步的,透過發送訊息進行。
- 攻擊場景:
- 建議:圍繞非同步訊息設計合約邏輯,避免同步資料可用性的假設。
15. 兩個預先定義的 method_id
- 嚴重性:中
- 描述:有兩個預先定義的 method_id:一個用於接收區塊鏈內的消息"(0)",通常命名為"recv_internal",另一個用於接收來自外部的消息"(-1)",命名為"recv_external"。
- 攻擊場景:
- 建議:使用如 "force_chain(to_address)" 的方法來驗證位址是否在正確的鏈上。
16. 使用可反彈訊息
- 嚴重性:高
- 描述:TON 區塊鏈是非同步的,訊息不必依序到達。失敗的訊息應正確處理。
- 攻擊場景:
- 建議:始終使用可反彈訊息("0x18")來正確處理訊息失敗。
17. 重播保護
- 嚴重性:高
- 描述:為錢包(儲存用戶資金的合約)實現重播保護,可以使用序號("seqno")來確保訊息不被重複處理,或使用帶有到期的唯一交易識別碼。
- 攻擊場景:
- 建議:使用類似序號或訊息唯一識別碼的重播保護方法,以防止重播攻擊。
18. 訊息的競態條件
- 嚴重性:高
- 描述:訊息級聯可以跨多個區塊處理,攻擊者可能會啟動一個並行流,從而導致競態條件。
- 攻擊場景:攻擊者可能會利用時間差異來操縱合約行為。
- 建議:透過在每個步驟驗證狀態並不假設訊息流中的狀態一致性來預防競態條件。
19. 使用攜帶值模式
- 嚴重性:高
- 說明:在代幣轉帳(例如 TON Jetton)中,餘額應使用攜帶值模式進行轉帳。發送方扣減餘額,接收方將其加回或反彈回去。
- 攻擊場景:如果處理不當,Jetton 餘額可能被操縱。
- 建議:使用攜帶值模式以確保正確的值轉移。
20. 小心退還多餘的燃料費
- 嚴重性:高
- 描述:如果未將多餘的燃料費退還給發送者,資金可能會隨著時間的推移在合約中累積。原則上,這並不可怕,但這是一種次優的做法。可以添加一個功能來清除多餘的費用,但像 TON Jetton 這樣的流行合約仍然會向發送者返回多餘的費用訊息"op::excesses"。
21. 檢查函數回傳值
- 嚴重性:高
- 描述:函數總是會傳回值或錯誤,如果忽略傳回值的檢查,可能會導致邏輯上的致命錯誤。
- 攻擊場景:
- 建議:始終檢查函數的回傳值。
22. 檢查假冒的 Jetton 代幣
- 嚴重性:高
- 描述:Jetton 代幣由兩部分組成:"jetton-minter" 和"jetton-wallet"。如果保險庫合約沒有正確驗證,攻擊者可能會透過存入假代幣並提取有價值的代幣來耗盡保險庫中的資金。
- 攻擊場景:
- 建議:透過計算用戶的 jetton 錢包地址,檢查發送者是否發送了假冒的 Jetton 代幣。
寫在最後
對開發者而言,遵循這些最佳實踐,可以有效提升智能合約的安全性,並減少潛在的安全風險。在區塊鏈技術日新月異的今天,安全永遠是重中之重。希望這個最佳實踐可以幫助更多的開發者打造安全可靠的智慧合約,推動區塊鏈技術的健康發展。
參考連結:
[1] https://dev.to/dvlkv/drawing-conclusions-from-ton-hack-challenge-1aep [2] https://docs.ton.org/develop/smart-contracts/security/ton-hack-challenge-1 [3] https://docs.ton.org/learn/tvm-instructions/tvm-overview [4] https://docs.ton.org/develop/smart-contracts/messages [5] https://docs.ton.org/develop/smart-contracts/security/secure-programming [6] https://docs.ton.org/develop/smart-contracts/security/things-to-focus免責聲明:作為區塊鏈資訊平台,本站所發布文章僅代表作者及來賓個人觀點,與 Web3Caff 立場無關。文章內的資訊僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。