Re-Entrancy Attack?
재진입 공격(Re-Entrancy Attack)이란 재귀적인 방법을 통해 컨트랙트에서 자금을 빼내는 방법이다.
간단하게 작성된 자금을 출금하는 함수가 있는 컨트랙트 A와 re-entrancy 공격을 실행하는 컨트랙트 B가 다음과 같이 작성되어 있다.
pragma solidity ^0.8.7;
contract A {
mapping(address => uint256) balances;
.
.
.
function withdraw() public{
msg.sender.call{value :balances[msg.sender]}("");
balances[msg.sender] = 0;
}
}
contract B {
A a;
constructor(address _a) {
a = A(_a);
}
function attack() public{
a.withdraw();
}
fallback() external payable {
a.withdraw();
}
}
먼저 B에서 attack함수를 실행한다. attack 함수가 호출되면 컨트랙트 A의 withdraw함수가 실행돼서 balances[msg.sender] 만큼의 이더를 컨트랙트 B로 전송하게 되는데 이때 B의 fallback 함수가 실행된다. fallback 함수에서 withdraw함수가 다시 호출되는데 이때 withdraw함수에서 balances[msg.sender] = 0 라인은 실행되지 않았기 때문에 또다시 이더를 B로 전송하게 된다. 재귀적으로 이 동작이 반복되기 때문에 balances[msg.sender] 만큼이 아닌 컨트랙트가 가진 모든 이더를 전송받는 것이 가능해진다.
예방법
재진입 공격의 예방법으로 대표적인 방법은 전송함수를 실행하기 전에 상태 변수를 변경해놓는 것이다.
function withdraw() public{
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0;
msg.sender.call{value : amount}("");
}
'블록체인 > 이더리움' 카테고리의 다른 글
트랜잭션의 유효성 (0) | 2022.08.12 |
---|---|
[Hardhat] Invalid hex string ... 에러 (0) | 2022.08.05 |
머클트리 (0) | 2022.06.30 |
업그레이드 가능한 컨트랙트 작성해보기 (0) | 2022.06.27 |
솔리디티 프록시 패턴(Proxy Pattern) (0) | 2022.06.25 |