智能合約安全——delegatecall (1)

  • 文章探討智能合約安全中的delegatecall特性,重點在於其修改存儲變量時是根據插槽位置而非變量名。
  • 通過合約A和合約B的例子說明,當使用delegatecall調用外部函數時,修改的是對應插槽位置的數據,而非變量名稱。
  • 分析一個漏洞案例:攻擊者利用delegatecall調用Lib合約的pwn函數,修改HackMe合約的owner變量,從而控制合約。
  • 攻擊步驟包括觸發fallback函數、通過delegatecall調用pwn函數,最終修改目標合約的擁有者。
  • 提出修復建議:避免讓被調用合約地址可控,並注意變量聲明順序和存儲位置,以防止非預期的變量覆蓋。
  • 文章最後推薦讀者到CHAINPIP社區學習更多智能合約和區塊鏈知識。
總結

在之前的內容中,學習到了storage中是使用插槽存儲數據的。而delegatecall函數有個有趣的特點當使用delegatecall 函數進行外部調用涉及到storage 變量的修改時是根據插槽位置來修改的而不是變量名

舉個例子:

合約A

智能合約安全——delegatecall (1)

合約B

智能合約安全——delegatecall (1)

當合約B調用testDelegatecall ()函數時,合約B的地址c的值會變為合約A的地址,而地址a則是不變。因為合約A的函數test()改變的是插槽slot 1的值,同樣的在合約B中運行時,改變的也是插槽slot 1的值,即地址c的值。

目標合約

智能合約安全——delegatecall (1)

漏洞分析

我們可以看到有兩個合約, Lib 合約中只有一個pwn 函數用來修改合約的owner,在HackMe 合約中存在fallback 函數,fallback 函數的內容是使用delegatecall 去調用Lib 合約中的函數。我們需要利用HackMe.fallback() 觸發delegatecall 函數去調用Lib.pwn() 將HackMe 合約中的owner 改成自己。

攻擊合約

智能合約安全——delegatecall (1)

現在我們來看看整個攻擊的邏輯:

1.攻擊者調用attack()發起攻擊,attack 函數首先去調用HackMe.pwn();

2.HackMe 合約中並沒有pwn 函數,此時觸發HackMe.fallback();

3.HackMe.fallback() 使用deldegatecall 調用Lib 合約中的函數,函數名取的是msg.data 也就是"pwn()",而Lib 合約中恰好有名為pwn 的函數,於是便在HackMe 合約中運行了pwn函數;

4.pwn函數修改了插槽slot0位置(即HackMe 合約的擁有者)的值為msg.sender(即攻擊者),最終導致了HackMe 合約的擁有者變成了攻擊者。

修復建議

1. 在使用delegatecall 時應注意被調用合約的地址不能是可控的;

2. 在較為複雜的合約環境下需要注意變量的聲明順序以及存儲位置。因為使用delegatecall 進行外部調時會根據被調用合約的數據結構來用修改本合約相應slot 中存儲的數據,在數據結構發生變化時這可能會造成非預期的變量覆蓋。

如果想了解更多的智能合約和區塊鏈知識,歡迎到區塊鏈交流社區CHAINPIP社區,一起交流學習~

社區地址: https://www.chainpip.com/

分享至:

作者:fingernft

本文為PANews入駐專欄作者的觀點,不代表PANews立場,不承擔法律責任。

文章及觀點也不構成投資意見

圖片來源:fingernft如有侵權,請聯絡作者刪除。

關注PANews官方賬號,一起穿越牛熊
推薦閱讀
4小時前
5小時前
6小時前
16小時前
20小時前
20小時前

熱門文章

行業要聞
市場熱點
精選讀物

精選專題

App内阅读