본문 바로가기
Write Up/Ethernaut - 블록체인 워게임

Ethernaut - 2단계 (Fallout)

by p6rkdoye0n 2023. 11. 6.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import 'openzeppelin-contracts-06/math/SafeMath.sol';

contract Fallout {
  
  using SafeMath for uint256;
  mapping (address => uint) allocations;
  address payable public owner;


  /* constructor */
  function Fal1out() public payable {
    owner = msg.sender;
    allocations[owner] = msg.value;
  }

  modifier onlyOwner {
	        require(
	            msg.sender == owner,
	            "caller is not the owner"
	        );
	        _;
	    }

  function allocate() public payable {
    allocations[msg.sender] = allocations[msg.sender].add(msg.value);
  }

  function sendAllocation(address payable allocator) public {
    require(allocations[allocator] > 0);
    allocator.transfer(allocations[allocator]);
  }

  function collectAllocations() public onlyOwner {
    msg.sender.transfer(address(this).balance);
  }

  function allocatorBalance(address allocator) public view returns (uint) {
    return allocations[allocator];
  }
}

 

Claim ownership of the contract below to complete this level.

  Things that might help

  • Solidity Remix IDE

 

단순한 owner의 소유권을 탈취하는 문제이다. 해당 목표를 달성하기 위해 실행할 수 있는 공격 벡터를 살펴보면 Fallout 함수, 아니 Fal1out 함수밖에 없다. 내가 이렇게 말한 이유는  0.4.23 이전에는 컨트랙트 명과 함수명을 같게 하면 생성자처럼 정의 시킬 수 있었다. 그렇지만 해당 함수는 Fallout이 아닌 Fal1out 이므로 생성자가 아니라 단순 함수로써 작용한다. 그리고 어차피 해당 솔리디티를 0.6.0으로 컴파일 하므로 같은 함수명으로 생성자를 생성하게 된다면 컴파일 조차도 안된다.

 

 

 

생성자 였으면 owner의 값이 해당 인스턴스 컨트랙트의 주소였어야 하지만 해당 값에 아무 값이 안 들어가있는 것을 볼 수 있다.

 

await contract.Fal1out()

 

그래서 해당 페이로드를 입력하게 된다면 owner의 권한을 탈취할 수 있다.

 

 

이렇게 문제를 해결하였다.

 

🚩