我剛剛完成了一篇關於重入攻擊(reentrancy)——一個許多開發者在構建智能合約時仍然忽視的安全問題——的分析。



簡單來說,重入攻擊是指一個智能合約在完成第一次調用之前,被多次調用的情況。可以這樣想像:ContractA 正在執行一個函數,它調用了 ContractB,而 ContractB 又在 ContractA 尚未完成時反向調用它。這就是攻擊者可以利用的漏洞。

具體例子:EtherStore 有 10 Ether,ContractB 已經存入了 1 Ether。當 ContractB 調用提款函數時,它會檢查餘額是否大於 0,如果是,就將 Ether 發送回去。但這裡的危險點在於——更新餘額為 0 的操作是在發送 Ether 之後才進行的。因此,攻擊者可以設計一個 fallback 函數,當收到 Ether 時,會再次調用提款函數。這個循環會一直持續,直到 Ether 被全部提取完畢。

我將介紹三種防止重入攻擊的方法:

第一是使用 nonReentrant 修飾符。這個方法在函數執行時鎖定合約,防止重入。簡單但有效,適用於單一函數。

第二是採用 Checks-Effects-Interactions 模式。即在發送 Ether 之前先更新餘額。這樣即使發生重入,餘額已經是 0,檢查也會失敗。

第三是建立一個獨立的 GlobalReentrancyGuard 合約。這個方法使用一個全域狀態變數來控制多個合約的重入問題。特別適合你的專案中有多個合約相互作用的情況。與其在每個合約中檢查,不如集中管理。

重入攻擊的問題並不新穎,但它仍然是最常見的漏洞之一。我看到許多開發者尚未一致性地採用這些措施。如果你在使用 Solidity,務必要理解這個問題,並在你的專案中至少應用其中一種方法。智能合約的安全性不是選擇題,而是必須的。
查看原文
此頁面可能包含第三方內容,僅供參考(非陳述或保證),不應被視為 Gate 認可其觀點表述,也不得被視為財務或專業建議。詳見聲明
  • 打賞
  • 回覆
  • 轉發
  • 分享
回覆
請輸入回覆內容
請輸入回覆內容
暫無回覆