[Day34] OpenZeppelin 이더너트 문제풀이 — (9) Vault
이번 포스팅은 Vault 문제입니다.
미션은 간단합니다. 아래 Vault 문제에서 password 를 알아내서 unlock을 하면 되는 문제입니다.
pragma solidity ^0.4.18;contract Vault {
bool public locked;
bytes32 private password;function Vault(bytes32 _password) public {
locked = true;
password = _password;
}function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
어떻게 할 수 있을까요 ? ㅎㅎ 바로 web3 API중 getStorageAt 이라는 함수를 사용하여 가져올 수 있습니다. 먼저 EVM (Ethereum Virtual Machine)을 살펴보면 메모리 슬롯 이라는 2²⁵⁶개의 우주의 원자만큼 많은 슬롯이 존재합니다. 해당 공간의 구성은 스택과 EVM 메모리 공간과 트랜잭션들을 전송했을 때 전송되는 데이터들의 기록을 하는 부분으로 구성이 되어있는데요. 위의 상태변수인 불리언 값으로 되어잇는 locked과 bytes32는 getStorageAt(‘컨트랙트주소', ‘인덱스’, ‘latest’) 로 호출하여 값을 가지고 올 수 있습니다.
아마 컨트랙트에 선언된 변수에 Visibility가 프라이빗인데도 불구하고 가져올 수 있다는 사실에 놀라신 분들도 있으실텐데요.. 내부적으로 프라이빗 데이터 또한 외부적으로 호출만 할 수 없지 EVM 메모리 슬롯에 저장되어 있는 값을 가지고 올 수 있다는 것이 이번 문제의 솔루션입니다.
web3js 를 통해 해당 함수를 호출해서 가져올 수 있지만 Ropsten Network를 통해 이더너트를 수행하고 있으니 클라우드 서비스인 Infura의 HTTP API 콜을 통해 가져오도록 하겠습니다.
먼저 불리언 값을 가져와 보겠습니다.
result에 0으로 32바이트의 메모리 슬롯을 출력하는 것을 보실 수 있습니다. 현재 0으로 되어있어 locked는 상태가 false인 상태입니다. 저는 먼저 문제를 풀었기 때문에 이렇게 나오는 것입니다.
두 번째, password 상태변수를 통해 가져와 보도록 하겠습니다.
result가 나왔는데요 이 값을 복사하여 unlock 함수의 파라미터로 던지게 되면 locked가 false로 풀리게 되어있습니다.
이 문제가 시사하는 바는 컨트랙트 내부에 패스워드성 정보를 저장하지 말라는 경고의 문제로 해석 되는데요. Visibility만 믿고 저장해서 해킹 당하는 일이 없도록 해야겠습니다!
끄읏~
- 저는 블록체인 개발사 (주)34일에서 블록체인 엔지니어로 일하고 있습니다.
- 880만 팔로워 전세계 1위 한류 미디어 케이스타라이브(KStarLive)와 함께 만든 한류 플랫폼에서 사용되는 케이스타코인(KStarCoin) 프로젝트를 진행 중입니다. 팬 커뮤니티 활동을 하면서 코인을 얻을 수 있으며, 한류 콘텐츠 구매, 공연 예매, 한국 관광 상품 구매, 기부 및 팬클럽 활동 등에 사용 될 계획입니다.