티스토리 뷰
1. 문제 설명
Unlock the vault to pass the level!
// 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로 만들면 문제가 해결됩니다.
2. 취약점 분석
locked의 값을 false로 변경하려면 올바른 password를 알아내어 unlock 함수로 전달해야 합니다. 인자로 전달한 _password는 Vault 컨트랙트의 상태변수인 password와 비교하며 이는 visibility가 private로 되어있어 외부에서 값을 확인하는 것은 불가능해 보입니다.
하지만 오랜 시간 구글링을 해보니 솔리디티에서는 private로 선언된 변수라고 할지라도 외부에서 값을 알 수가 있다는 것을 알게되었습니다. 이것을 이해하기 위해서 우선 EVM Storage에 대해서 알아보도록 하겠습니다.
EVM Storage
EVM이란 Ethereum Virtual Machine으로, 스마트 컨트랙트를 실행하고 네트워크 상태를 관리하는 분산 컴퓨팅 환경입니다. EVM은 스마트 컨트랙트를 배포할 때 반환된 바이트 코드를 실행하며 바이트 코드는 OP CODE들의 집합을 의미합니다.
EVM은 스마트 컨트랙트의 데이터를 저장하기 위해 Storage, Memory, Calldata, Stack을 사용합니다. 그 중에서 Storage는 컨트랙트의 상태 변수를 저장하며 이를 블록체인에 영구적으로 기록합니다. 또한 private 변수도 이러한 EVM Storage에 저장되고 논리적으로 접근을 제한하는 것일 뿐, 저장된 데이터가 자동으로 암호화되는 것이 아니기에 외부에서 데이터를 볼 수 있습니다. (이는 블록체인의 투명성과 탈중앙화 특성을 기반으로 합니다)
3. 공격 수행
EVM Storage 데이터 접근
EVM Storage에 저장된 데이터에 접근하는 방법은 여러 가지가 있을 수 있습니다.
- web3.js
- foundry
- solidity
- ...
1) web3.js
web3.js는 이더리움 네트워크와 상호작용할 수 있도록 다양한 메소드를 제공하는 js 라이브러리이며. 이더넛에서도 web3.js를 사용하고 있습니다. web3.js에서는 getStorageAt이라는 메소드가 존재하는데, 이 메소드를 사용해 특정 컨트랙트의 EVM Storage 값을 조회할 수 있습니다. 사용 방법은 다음과 같습니다.
await web3.eth.getStorageAt(<Addr>, <slot>);
EVM Storage에서 slot 하나의 크기는 32 바이트이며 locked와 password는 각각 0번째 슬롯, 1번째 슬롯에 위치합니다. 따라서 아래와 같이 조회하면 password의 값을 얻을 수 있을 것입니다.
(0: locked, 1: password)
2) foundry
foundry는 스마트 컨트랙트 개발을 도와주는 하나의 프레임워크이며 컴파일, 테스트, 배포, 조회 등등 여러가지 기능을 제공합니다. (foundry에 대한 설명은 제대로 정리해서 포스팅해보도록 하겠습니다 🫡)
foundry의 도구 중에서 cast storage라는 명령어를 사용하여 특정 컨트랙트의 EVM Storage를 조회할 수 있습니다. 사용 방법은 다음과 같습니다.
cast storage <Addr> <slot> --rpc-url <RPC_URL>
위에서 설명한 대로 password는 slot 1에 위치하므로 아래와 같은 명령어를 사용하여 값을 조회해보았습니다.
3) solidity
솔리디티 코드를 사용해서도 다른 컨트랙트의 EVM Storage 값을 조회할 수 있습니다. foundry 프로젝트에서 사용하는 테스트와 디버깅을 위한 표준 라이브러리 forge-std를 import하여 Script 컨트랙트를 상속받으면 vm이라는 변수를 사용해 유용한 기능을 사용해볼 수 있습니다. 그 중에서 vm.load 라는 메소드를 사용하면 특정 컨트랙트의 EVM Storage 값을 조회할 수 있습니다. 아래의 코드와 같이 사용할 수 있습니다.
pragma solidity ^0.8.0;
import "forge-std/Script.sol";
contract Solve is Script {
function run() external returns(bytes32) {
address target = 0x65f41D434f09DE6E7A9ff43FbB70fBef2916ba4d;
bytes32 slot = bytes32(uint256(uint160(0x1)));
bytes32 data = vm.load(target, slot);
return data;
}
}
unlock 함수 호출
위에서 여러가지 방법을 통해 password 값을 알아내었으니 unlock 함수에 전달하여 호출해보도록 하겠습니다. 간단하게 web3.js를 사용하여 호출하였습니다.
locked 변수의 값이 false로 변경되었습니다.
✌️
4. 문제 보충 설명
It's important to remember that marking a variable as private only prevents other contracts from accessing it. State variables marked as private and local variables are still publicly accessible.
To ensure that data is private, it needs to be encrypted before being put onto the blockchain. In this scenario, the decryption key should never be sent on-chain, as it will then be visible to anyone who looks for it. zk-SNARKs provide a way to determine whether someone possesses a secret parameter, without ever having to reveal the parameter.
상태 변수를 private로 선언하였다고 할지라도 여전히 공개적으로 액세스할 수 있음을 인지하고 있어야 합니다. 또한 데이터를 정말 공개하고 싶지 않다면, 블록체인에 올리기 전에 암호화해야 합니다. zk-SNARK는 매개변수를 공개하지 않고도 누군가가 비밀 매개변수를 가지고 있는지 확인할 수 있는 방법을 제공한다고 합니다.
감사합니다!
5. 참고자료
Solidity accessing private variable
currently, I'm practicing solidity. However, I'm a little confused about accessing a private variable in a contract. For example here; address private a; address private b; mapping (bytes32 =>...
stackoverflow.com
[20.08.10] 6주차 블록체인 - EVM storage에는 변수가 어떻게 저장될까?
저는 이번 교제 258페이지에 내부호출이 가능한 public함수의 매개변수가 모두 메모리로 저장된다는 부분을 보고 어떻게 저장되는지 궁금하여 간단한 실습과 함께 이번 내용을 준비해보았습니다.
cordingdiary.tistory.com
솔리디티 문법 (EVM과 저장 위치)
솔리디티 문법 (EVM과 저장 위치) 정리
velog.io
EVM, Solidity 란?, what is EVM and Solidity? — Steemit
discussion (kr,en) 암호화폐시장에 비가내린 하루였다. 암호화폐의 시가총액은 90B 달러까지 떨어졌다. 하지만 가격이 떨어진것이지 가치가 떨어진것은 아니다. 가치평가에 대한 확신은 누구든 하기
steemit.com
'Web3 > Wargame' 카테고리의 다른 글
[Ethernaut] Level 9 - King 풀이 (0) | 2025.01.14 |
---|---|
[Ethernaut] Level 7 Force 풀이 (0) | 2024.12.10 |
[Ethernaut] Level 6 Delegation 풀이 (0) | 2024.12.04 |
[Ethernaut] Level 5 Token 풀이 (1) | 2024.12.03 |
[Ethernaut] Level 4 Telephone 풀이 (0) | 2024.11.22 |
- Total
- Today
- Yesterday
- forensic
- writeup
- Python
- YISF
- 프로그래머스
- Ethernaut
- 오블완
- blockchain
- 이더넛
- Los
- 코딩테스트
- Write up
- 디스코드 봇
- 웹해킹
- misc
- Crypto
- 정렬
- 티스토리챌린지
- 디지털 포렌식
- 이세돌
- 파이썬
- smart contract
- 워게임
- Lord of SQL injection
- CTF
- Ethereum
- ctftime
- web3
- 알고리즘
- solidity
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |