🍁 金秋送福,大獎轉不停!Gate 廣場第 1️⃣ 3️⃣ 期秋季成長值抽獎大狂歡開啓!
總獎池超 $15,000+,iPhone 17 Pro Max、Gate 精美週邊、大額合約體驗券等你來抽!
立即抽獎 👉 https://www.gate.com/activities/pointprize/?now_period=13&refUid=13129053
💡 如何攢成長值,解鎖更多抽獎機會?
1️⃣ 進入【廣場】,點頭像旁標識進入【社區中心】
2️⃣ 完成發帖、評論、點讚、社群發言等日常任務,成長值拿不停
100% 必中,手氣再差也不虧,手氣爆棚就能抱走大獎,趕緊試試手氣!
詳情: https://www.gate.com/announcements/article/47381
#成长值抽奖赢iPhone17和精美周边# #BONK# #BTC# #ETH# #GT#
智能合約中的重入攻擊:理解這種脆弱性並實施預防策略
重入攻擊代表了智能合約安全中最臭名昭著的漏洞之一,導致數百萬的資金在各種區塊鏈協議中被盜。本文探討了重入漏洞背後的機制,並提出了安全意識強的開發者應該實施的全面預防技術。
什麼是重入攻擊?
在其核心,重入攻擊發生在智能合約中的一個函數在其之前的執行完成之前被重復調用。當智能合約在解決自己的狀態變化之前調用外部合約時,就會產生根本的脆弱性,從而創造出被利用的機會。
在典型場景中,合約A通過調用合約B的某個函數進行交互。當合約B獲得在合約A仍在執行其原始函數時回調合約A的能力時,關鍵的安全漏洞就出現了。這種遞歸交互模式爲潛在的攻擊創建了基礎。
重入攻擊是如何工作的:逐步解析
考慮這種情況:合約A總共持有10個ETH,其中合約B已向合約A存入1個ETH。當合約B試圖通過以下序列提取其資金時,漏洞變得可被利用:
關鍵漏洞在於 餘額更新發生在 ETH 轉移之後,這使得攻擊者可以在餘額被設置爲零之前多次利用相同的餘額。
攻擊的解剖:技術實現
讓我們來檢查一下脆弱的代碼模式:
固態性 // 易受攻擊的 EtherStore 合約 合約 EtherStore { mapping(address => uint) 公共餘額;
函數 deposit() public payable { balances[msg.sender] += msg.value; }
函數 withdrawAll() public { uint bal = 餘額[msg.sender]; require(bal > 0);
(bool發送,) = msg.sender.call{value: bal}(“”); require(sent, "發送以太幣失敗");
餘額[msg.sender] = 0; } }
現在,讓我們看看攻擊者如何利用這個漏洞:
固態性 // 利用重入漏洞的攻擊合約 合約攻擊 { EtherStore 公有 etherStore;
constructor(address _etherStoreAddress) { etherStore = EtherStore(_etherStoreAddress); }
etherStore.withdrawAll019283746574839201(; } }
函數 attack)( external payable { 需求019283746574839201msg.value >= 1 ether);
etherStore.deposit{value: 1 ether}();
etherStore.withdrawAll019283746574839201(; } }
攻擊序列在攻擊者調用 attack)( 時開始。這將存入 1 ETH 以建立餘額,然後調用 withdrawAll)(。當 EtherStore 發送 ETH 回來時,它會觸發 Attack 合約中的 receive)( 函數,該函數在餘額更新之前再次調用 withdrawAll)(。這一循環持續進行,直到 EtherStore 的資金被抽空。
全面預防技術
注重安全的開發者可以實施三種強大的技術來防止重入漏洞:
) 1. 功能級保護:非重入修飾符
在個別功能級別上最常見的保護措施是實現重入保護:
智能合約語言 合約 ReentrancyGuard { bool private locked = false;
修飾符 nonReentrant() { require###!locked, “可重入調用”(; 鎖定 = true; _; 鎖定 = false; }
function withdrawFunds)( public nonReentrant { // 函數代碼防止重入 } }
這種方法有效地鎖定合約在函數執行期間,防止任何遞歸調用,直到函數完成並解鎖狀態。
) 2. 跨功能保護:檢查-效果-互動模式
這個基礎安全模式重構代碼,以消除多個函數中的漏洞:
堅固 // 易受攻擊的實現 函數 withdrawAll() public { uint bal = 餘額[msg.sender]; require###bal > 0(;
)bool發送,( = msg.sender.call{value: bal})“”(; require)sent, "發送以太幣失敗"(;
餘額[msg.sender] = 0;交互後的狀態更新 }
// 安全實施 函數 withdrawAll)( public { uint bal = 餘額[msg.sender]; require)bal > 0(;檢查
餘額[msg.sender] = 0;效果 )state changes(
)bool發送,( = msg.sender.call{value: bal})“”(;相互 作用 require)sent, "發送以太幣失敗"(; }
通過遵循 檢查-效果-交互 模式,合約在任何外部交互之前更新其狀態,確保即使攻擊者試圖重入,他們也會遇到更新後的狀態 )零餘額(。
) 3. 項目級保護:全球重入保護
對於具有多個交互合同的復雜項目,實現全局重入保護可以提供系統範圍的保護:
固態性 合約 GlobalReentrancyGuard { bool 私有 _notEntered = true;
修飾符 globalNonReentrant() { require###_notEntered, “ReentrancyGuard: reentrant call”(; _notEntered = false; _; _notEntered = 真; } }
// 項目中的所有合約都繼承自 GlobalReentrancyGuard 合約 SecureContract 是 GlobalReentrancyGuard { function vulnerableOperation)( public globalNonReentrant { // 保護整個項目免受重入攻擊 } }
這種方法在保護DeFi協議中的跨合約重入攻擊方面尤其有價值,因爲多個合約相互之間進行交互。
重入漏洞的現實影響
重入漏洞導致了區塊鏈歷史上最具破壞性的攻擊之一。臭名昭著的2016年DAO黑客事件導致約360萬ETH被盜,當時價值約)百萬,最終導致以太坊硬分叉,創造了以太坊經典。
最近,在2020年,Lendf.Me協議因重入攻擊損失了大約(百萬,突顯出盡管人們的意識有所提高,這些漏洞仍然對智能合約安全構成重大風險。
安全最佳實踐
除了提到的具體技術,開發者還應遵循以下額外的安全實踐:
通過實施這些防御技術和遵循安全最佳實踐,開發者可以顯著降低重入攻擊的風險,並爲區塊鏈應用構建更安全的智能合約。