티스토리 뷰
1. 문제
아래의 금고를 해제하라!
// 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;
}
}
}
2. 해법
인스턴스를 생성할 때 선택한 네트워크의 블록 탐색기(ex. sepolia etherscan)를 열고 인스턴스 주소를 검색합니다.
Internal Transaction 탭에서 To가 Contract Creation으로 되어 있는 트랜잭션의 부모 해시를 클릭합니다.
Transaction Details 상단의 State 탭을 클릭합니다. 이 탭에서는 이 트랜잭션으로 인해 블록체인 상에서 어떤 상태 변화가 발생했는지 확인할 수 있습니다. 인스턴스 주소 왼쪽의 화살표를 클릭하여 탭을 펼칩니다.
인스턴스 스토리지의 두 번째 슬롯의 값에 주목합니다. 이 값이 바로 금고의 비밀번호입니다.
확인한 비밀번호를 그대로 복사하여 unlock 함수의 매개변수로 넣고 함수를 실행합니다.
트랜잭션이 컨펌되고 locked 값을 확인하면 false로 변한 것을 확인할 수 있습니다.
3. private은 secret이 아니다
원본 컨트랙트에서 password의 가시성은 private입니다. 이더리움과 같은 퍼블릭 블록체인은 누구나 블록체인에 저장되어 있는 데이터를 확인할 수 있습니다. 따라서 private은 나만의 작고 소중한 비밀이 될 수 없습니다. private은 그저 다른 컨트랙트에서 해당 값이나 함수에 직접 접근하는 것을 방지해줄 뿐입니다.
굳이 블록체인 상에 비밀을 저장하고 싶다면, commit-reveal 방식을 사용하여 저장하고자하는 값의 해시값을 만들어 저장하고 나중에 원본값을 공개할 수 있습니다. 그러나 이 방법도 결국은 트랜잭션을 생성할 때 값이 드러나기 때문에 공격자가 동일한 트랜잭션을 더 높은 가스비를 지불하고 생성하여 먼저 마이닝되도록 하는 프론트 러닝(front-running)과 같은 문제에 여전히 취약할 수 있습니다.
4. 결론
퍼블릭 블록체인에서 비밀은 없다.
'Solidity > Hacking' 카테고리의 다른 글
[Ethernaut] 10. Re-entrancy (0) | 2024.01.22 |
---|---|
[Ethernaut] 9. King (0) | 2024.01.20 |
[Ethernaut] 7. Force (0) | 2024.01.17 |
[Ethernaut] 6. Delegation (0) | 2024.01.16 |
[Ethernaut] 5. Token (0) | 2024.01.15 |