간단하게 Bank 스마트 컨트랙트의 witdhraw 함수를 변경해주면 됩니다.
기존의 witdhraw 함수는 아래와 같습니다.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Bank {
...
function withdraw() external {
uint currentBalance = balances[msg.sender];
(bool result,) = msg.sender.call{value:currentBalance}("");
require(result, "ERROR");
balances[msg.sender] = 0;
}
...
}
재진입 공격이 시작되는 코드는 "(bool result,) = msg.sender.call{value:currentBalance}("");" bank가 attacker에게 예치된금액을 주는 순간이라 생각할 수 있습니다.
그렇다면, attacker에게 예치된 금액을 보내기전에, 보낼 금액을 차감하고 나서 보낸다면 재진입 공격에서 벗어 날 수 있을 것입니다.
다음과 같은 코드가 될 수 있겠네요.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Bank {
...
function withdraw() external {
uint currentBalance = balances[msg.sender];
balances[msg.sender] = 0;
(bool result,) = msg.sender.call{value:currentBalance}("");
require(result, "ERROR");
}
...
}
위와 같이 balances[msg.sender] = 0; 을 먼저 만들어주고나서, 예치된 금액을 보냈으므로, 다시 attacker가 재진입 한다해도, attacker의 예치된 금액은 0이기에 줄수가 없겠죠.
추가적으로 transfer,send를 쓰면 재진입공격을 막을 수 있으나, 이스탄불 하드포크이후 call을 쓰는것을 권장하고 있습니다. 그러므로 재진입공격을 잘 막아주는게 좋겠죠.
더 자세한 내용 유튜브를 통해서 확인 부탁드립니다.
솔리디티 깨부수기 - Security 1-4강 재진입 공격(re-entrancy attack) 해결법 2 (1) | 2022.09.04 |
---|---|
솔리디티 깨부수기 - Security 2강 재진입 공격(re-entrancy attack) 구현하기 (0) | 2022.07.31 |
솔리디티 깨부수기 - Security 1강 재진입 공격(re-entrancy attack) 이란? (0) | 2022.07.30 |