Tyojong

[The Ethernaut] Fallback 본문

web3/The Ethernaut

[The Ethernaut] Fallback

Tyojong 2025. 9. 13. 20:01

문제 설명


이 문제는 Fallback, receive 함수가 잘못 설정되었을 때 발생할 수 있는 취약점을 학습할 수 있다.

이 문제를 해결하기 위해서는 컨트랙트의 소유권을 획득하고 컨트랙트 잔고를 0으로 만든다.(모든 이더를 빼낸다.)

 

코드 분석


배포자를 owner로 설정하고 owner의 초기 기여금을 1000 ETH로 설정한다.

 

contribute() 함수는 0.001 ETH 미만의 금액만 받을 수 있고 받은 기여금을 저장한다.

호출자의 기여금이 소유자의 기여금보다 많으면 owner(소유권)을 이전한다.

 

호출자의 현재 기여금을 알려주는 읽기 전용 함수이다.

 

호출자가 소유자인지 확인하는 제한자이다.

 

제한자가 적용되어 있는 함수로 소유자만 호출 가능하다.
소유자 주소를 payable 타입으로 캐스팅하고 (ETH를 전송할 수 있는 주소로 바꾸고) 현재 컨트랙트가 보유한 전체 ETH 잔액을 소유자에게 전송한다.

 

receive() 함수는 컨트랙트에 직접 ETH가 전송될 때 자동으로 호출되는 함수로 외부에서만 호출 가능하고 ETH를 받을 수 있다.

전송된 ETH가 0보다 크고 호출자의 기여금이 0보다 커야 한다. (호출자가 기여한 적이 있어야 한다.) 이 조건을 만족하면 호출자를 소유자로 변경한다.

 

익스플로잇


contribute() 함수에 따르면 현재 owner는 1000ETH 를 가지고 있고 호출자는 0.001ETH 씩 받을 수 있기 때문에 소유권을 이전 받으려면 백만번 요청을 해야한다.

하지만 contribute() 함수에 ETH를 보내 기여도를 조금이라도 높이고 거래를 통해 ETH를 조금 보내게 되면 receive함수 조건을 만족하기 때문에 owner 소유권을 가져올 수 있게 된다.

문제를 해결하면서 사용할 수 있는 명령어들이다.

 

소유자와 호출자의 주소를 각각 확인해보면 다른 것을 알 수 있다.

 

호출자의 컨트랙트 기여도를 뽑아 Wei를 ether단위로 나타낸다.

현재는 기여도가 0인것을 알 수 있다.

 

컨트랙트의 contribute함수에 0.00001 이더를 wei로 변환하여 value로 트랜잭션을 보낸다.
그러면 contribute함수에서 msg.value로 값을 받아 처리를 한다.

요청 후 호출자의 기여도를 확인해보면 증가한 것을 볼 수 있다. 소유자를 가져오기 위한 첫 번째 조건이 완성되었다.

 

getBalance를 사용해 instance의 잔액을 확인해보면 0.00001가 채워져있다.

 

함수를 지정하지 않고 트랜잭션을 보낸다.

처리할 함수와 data가 없을 경우 receive함수가 실행된다.

이때 기여도는 0 이상이고 value값이 0 이상이기 때문에 조건을 만족해 소유권이 변경된다.

 

소유자를 확인해보면 호출자와 동일해진것을 알 수 있다.

 

이렇게 쌓여있는 잔액을 withdraw함수를 통해 오너에게 모두 전송하면 인스턴스의 잔액이 0이 된것을 확인할 수 있다.

 

'web3 > The Ethernaut' 카테고리의 다른 글

[The Ethernaut] Hello Ethernaut  (0) 2025.09.08