728x90
Description
Claim ownership of the contract below to complete this level.
Things that might help
- Solidity Remix IDE
Code
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "openzeppelin-contracts-06/math/SafeMath.sol";
contract Fallout {
using SafeMath for uint256;
mapping(address => uint256) 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 (uint256) {
return allocations[allocator];
}
}
Scenario
owner를 msg.sender로 바꾸기 위해서는 그냥 Fal1out()을 호출하면 된다.
아니 이렇게 간단하다고…?
Exploit
Purpose
아니 문제가 이렇게 간단할 리 없잖아…
찾아보니 예전 솔리디티 버전에서는 contract이름과 같은 이름을 가진 function은 현재의 constructor()의 역할을 하여 배포될 때 한 번만 실행되었다고 한다. 그런데 개발자의 오타 또는 코드 업데이트 과정에서 contract 이름과 function 이름이 달라지게 되면 그냥 함수가 되는 것이다. 여기에서도 contract 이름은 fallout이지만 함수 이름은 fal1out이어서 함수가 constructor가 아닌 일반 함수 역할을 하여 외부에서 호출 가능했던 것이다.
Rubixi 사태 또한 마찬가지로 원래 컨트랙트 이름이 DynamicPyramid여서 DynamicPyramid 함수가 constructor 역할을 했는데 컨트랙트 이름을 Rubixi로 바꾸면서 함수 이름을 같이 바꿔주지 않아서 생긴 취약점이다.
728x90