Ethernaut 8. Vault

독수리박박·2024년 7월 9일
0
post-thumbnail

Ethernaut level8 Vault

Problem


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Vault {
    bool public locked;
    bytes32 private password;

    constructor(bytes32 _password) {
        locked = true;
        password = _password;
    }

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

문제는 위 컨트랙트의 locked 변수를 false로 만들어야 합니다. 즉 금고를 잠금해제 시키면 되는 문제입니다. 하지만 unlock 함수를 통해 잠금을 해제하기 위해서는 private 변수인 password를 알아내야 합니다.

문제는 password가 private 변수라는 것 입니다. 얼핏보면 private라는 키워드 때문에 접근이 불가능한 것 처럼 보입니다.

Storage Data


컨트랙트는 소스코드 이외에도 스토리지를 가지고 있고 여기에 데이터를 저장합니다. 따라서 password도 스토리지에 저장되어 있고 스토리지에 접근만 가능하다면 문제 해결이 가능합니다.

private이란 가시성은 다른 컨트랙트에서 해당 변수에 대해 접근을 못하게 하는 것일 뿐(상속 받은 컨트랙트에서도 접근 X..!) 스토리지를 통해 접근하면 값을 알아낼 수 있습니다.

Solution


Solution1. Etherscan

이더스캔을 통해 컨트랙트의 스토리지를 조회할 수 있습니다.

  1. 이더스캔(연결된 테스트넷)에 접속한 뒤 instance의 주소로 검색합니다.
  2. internal transaction에서 parent Tx hash로 들어갑니다.
  3. state를 클릭하면 해당 컨트랙트에서 어떤 변화가 일어났는지 확인할 수 있습니다.


첫번째 슬롯에는 locked 변수의 true가 저장되어 있고 두번째로 password가 저장되어 있습니다. 해당 값을 공격 컨트랙트에 넣고 unlock을 진행하면 됩니다.

Solution2. web3.eth.getStorageAt(target, slot)

web3.eth.getStorageAt(vaultAddress, 1)를 사용하면 바로 1번 slot에 저장되어 있는 값을 불러올 수 있습니다.

Conclusion


private 같은 가시성 키워드들은 다른 컨트랙트들에게 해당 변수에 대한 접근 범위 설정을 할 뿐 아예 접근 불가능한 데이터로 만드는 것이 아닙니다.

온체인상에서 접근 못하는 데이터는 없습니다. 하지만 중요한 데이터라면 난독화 같은 과정을 통해서 조금은 남들로부터 비밀로 할 수 있습니다.

0개의 댓글