본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

재진입 공격(Reentrancy Attack)은 스마트 계약이 외부 계약을 호출한 순간 제어권을 넘겨받은 악성 계약이, 원래 함수의 실행이 끝나 상태가 갱신되기 전에 그 함수를 다시 호출해 같은 동작(주로 출금)을 되풀이하게 만드는 공격이다.

이더리움 같은 블록체인의 스마트 계약은 다른 계약의 함수를 호출하거나 이더를 보낼 수 있다. 이더를 받는 쪽이 계약이면 받는 순간 그 계약의 코드(fallback·receive 함수)가 실행된다. 즉 외부 호출은 실행 흐름을 상대에게 넘기는 일이다. 이더리움 재단은 신뢰할 수 없는 계약에 흐름을 넘기면 재진입 같은 문제가 생긴다고 경고하며, 재진입 공격을 악성 계약이 원래 함수 호출이 끝나기 전에 취약한 계약을 다시 불러 들어오는 것으로 설명한다.[1] 스마트 계약 취약점 분류(SWC Registry)는 이를 SWC-107 로 두고 재귀 호출 공격이라고도 부른다.[2]

취약한 출금 함수가 다음 순서로 되어 있다고 하자.

  1. 호출자의 잔액이 0 보다 큰지 확인한다(검사)
  2. 호출자에게 잔액만큼 이더를 보낸다(외부 호출)
  3. 호출자의 잔액을 0 으로 만든다(상태 변경)

공격 계약은 2단계에서 이더를 받는 순간 실행되는 자기 receive 함수 안에서 출금 함수를 다시 호출한다. 이때 3단계가 아직 실행되지 않아 잔액이 그대로 남아 있으므로 1단계 검사를 또 통과하고, 같은 잔액을 또 받는다. 이 과정이 가스가 떨어지거나 계약의 이더가 바닥날 때까지 되풀이된다.

2016년 6월 이더리움 위의 투자 조직 계약 The DAO 가 이 방식으로 공격당해 약 360만 ETH 가 빠져나갔고, 이를 되돌리려는 하드포크로 이더리움과 이더리움 클래식이 갈라졌다.

  • 검사-효과-상호작용(Checks-Effects-Interactions) 패턴 - 조건을 검사하고, 잔액 같은 내부 상태를 먼저 바꾼 뒤, 마지막에 외부 호출을 한다. 위 예에서는 3단계를 2단계 앞으로 옮긴다.[2]
  • 재진입 잠금(뮤텍스) - 함수에 들어올 때 잠금 변수를 세우고 나갈 때 푼다. 실행 중에 다시 들어오면 거부한다. OpenZeppelin 의 ReentrancyGuard 가 대표적이다.
  • 출금 분리(pull payment) - 계약이 직접 보내지 않고 받을 사람이 따로 출금하게 해 외부 호출 지점을 줄인다.
  • 정적 분석 도구와 보안 감사로 외부 호출 뒤에 상태를 바꾸는 코드를 찾는다.

블록체인의 다른 공격과 구별하기

편집 원본 편집
공격 대상 계층 핵심
재진입 공격 스마트 계약 코드 상태 갱신 전 재호출로 반복 인출
이중 지불 거래·합의 같은 자산을 두 번 쓰는 거래를 모두 받아들이게 함
이클립스 공격 P2P 네트워크 한 노드의 피어를 모두 공격자로 채워 고립
51% 공격 합의 과반 해시 파워로 체인을 다시 씀
시빌 공격 P2P 네트워크 가짜 신원을 대량으로 만들어 영향력 확보
  • 스머프 공격은 블록체인 공격이 아니다. ICMP Echo 요청을 출발지를 피해자로 위조해 브로드캐스트 주소로 보내, 응답이 피해자에게 몰리게 하는 일반 네트워크의 서비스 거부 공격이다.
  1. ↑ 「Smart contract security」, ethereum.org, https://ethereum.org/en/developers/docs/smart-contracts/security/, 확인일: 2026-11-04.
  2. ↑ 2.0 2.1 「SWC-107 Reentrancy」, Smart Contract Weakness Classification Registry, https://swcregistry.io/docs/SWC-107/, 확인일: 2026-11-04.