智能合約安全分析,Vyper 重入鎖漏洞全路徑分析
事件背景
7 月 30 日 21:10 至 7 月 31 日 06:00 鏈上發(fā)生大規(guī)模攻擊事件,導致多個 Curve 池的資金損失。漏洞的根源都是由于特定版本的 Vyper 中出現(xiàn)的重入鎖故障。
攻擊分析
通過對鏈上交易數(shù)據(jù)初步分析,我們對其攻擊的交易進行整理歸納,并對攻擊流程進一步的分析,由于攻擊涉及多個交易池。
pETH/ETH 池子被攻擊交易:
https://etherscan.io/tx/0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c
msETH/ETH 池子被攻擊交易:
https://etherscan.io/tx/0xc93eb238ff42632525e990119d3edc7775299a70b56e54d83ec4f53736400964
alETH/ETH 池子被攻擊交易:
https://etherscan.io/tx/0xb676d789bb8b66a08105c844a49c2bcffb400e5c1cfabd4bc30cca4bff3c9801
CRV/ETH 池子被攻擊交易:
https://etherscan.io/tx/0x2e7dc8b2fb7e25fd00ed9565dcc0ad4546363171d5e00f196d48103983ae477c
https://etherscan.io/tx/0xcd99fadd7e28a42a063e07d9d86f67c88e10a7afe5921bd28cd1124924ae2052
由于其攻擊流程基本一致所以我們主要對其中 pETH/ETH 池子 攻擊交易進行詳細的分析:
0xa84aa065ce61dbb1eb50ab6ae67fc31a9da50dd2c74eefd561661bfce2f1620c
交易由 0x6ec21d1868743a44318c3c259a6d4953f9978538
調用攻擊合約 0x9420F8821aB4609Ad9FA514f8D2F5344C3c0A6Ab ,并由該合約創(chuàng)建一次性攻擊合約
0x466b85b49ec0c5c1eb402d5ea3c4b88864ea0f04,并通過在一次性攻擊合約的構造函數(shù)中進行接下來的攻擊流程;
攻擊者通過閃電貸從 Balancer 處獲取 80,000 WETH ,并將其通過合約全部提取為 ETH。
隨后立即向 Curve 的 pETH/ETH 池提供了 40000 ETH 流動性,并收到了約 32,431.41 個 pETH-ETH LP Token
隨后在攻擊合約中調用移除流動性函數(shù),但在其合約函數(shù)調用棧中我們可以看出,該合約在執(zhí)行移除流動性時又返回調用了合約本身的回退函數(shù),并在回退函數(shù)中又調用了交易對的添加流動性操作。
根據(jù) pETH/ETH 交易對合約源碼分析,其中在轉賬時使用合約的回退函數(shù)再次調用該合約,此處發(fā)生合約重入,但該 LP 合約添加流動性以及移除流動性都有使用重入鎖,如下圖所示:
但實際調用棧中還是發(fā)生了重入了,導致后續(xù)通過攻擊者合約又一次向 LP Token 添加了 40,000 ETH 并獲取了約 82,182.76 個 pETH/ETH Lp Token, 并在攻擊合約的回調函數(shù)結束繼續(xù)移除最開始添加的 32,431.41 pETH/ETH Lp Token 獲得了約 3,740.21 pETH 和 34,316 ETH。
隨即又調用移除流動性函數(shù),移除約 10,272.84 pETH/ETH LP Token 獲得約 1,184.73 pETH 和 47,506.53 ETH。
其剩余的 7 萬多 pETH/ETH LP Token 依舊留在攻擊者合約中,如下圖:
接下來攻擊者通過 Curve pETH/ETH 池將約 4,924.94 pETH 交換為的 4,285.10 ETH。
最后攻擊者將約 86,106.65 ETH 兌換為 WETH,并向 Balancer 歸還閃電貸資金 80,000 WETH,并將 獲利資金約 6,106.65 WETH 轉移至 0x9420f8821ab4609ad9fa514f8d2f5344c3c0a6ab 地址。
至此,針對 pETH/ETH 池子的攻擊流程分析完畢,是一個很經典的重入獲利操作,但是我們通過對被攻擊合約的源碼進行分析,其合約是存在相應的重入鎖機制,正常來說可以防止重入操作,但是并沒有拒絕攻擊者的重入操作;
我們回顧一下 Vyper 中對重入鎖的說明,知道了該重入鎖實現(xiàn)是在函數(shù)起始部位使用指定的插槽存儲是否鎖定的操作。
我們將被攻擊 LP 合約的字節(jié)碼進行反編譯查看:
https://library.dedaub.com/ethereum/address/0x466b85b49ec0c5c1eb402d5ea3c4b88864ea0f04/decompiled
可以看到其兩個函數(shù)中存儲重入鎖的插槽并不一致,所以導致其重入鎖失效,進而導致被攻擊者利用進行獲利。
Vyper 項目方官方也發(fā)推說明,其某些版本中確實存在重入鎖故障。
通過對其 0.2.14 版本以及 0.2.15 版本對比,發(fā)現(xiàn)其在 Vyper 對應的重入鎖相關設置文件 data_positions.py 中存在改動,其改動后的代碼對重入鎖的存儲 key 進行單獨設置,并且,每一個重入鎖都會占用一個不同存儲插槽,從而導致合約的重入鎖功能不可用。
該錯誤已在 PR 中修復:#2439 和 #2514
其中修復了添加多個重入存儲插槽的問題,詳見下圖:文章來源:http://www.zghlxwxcb.cn/news/detail-708014.html
事件總結
此次攻擊事件涉及的攻擊范圍較廣,其根本原因是因為智能合約的基礎設施 Vyper 的 0.2.15、0.2.16、0.3.0 版本存在重入鎖設計不合理,從而導致后期使用這些版本的項目中重入鎖失效,最終遭受了黑客攻擊。文章來源地址http://www.zghlxwxcb.cn/news/detail-708014.html
- 建議在項目開發(fā)時選擇穩(wěn)定的技術棧以及對應版本,并對項目進行嚴格的測試,防止類似風險。
到了這里,關于智能合約安全分析,Vyper 重入鎖漏洞全路徑分析的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!