---
title: "Solidity의 재진입 공격(Reentrancy Attack)이란?"
description: "정의, 작동 방식, 스마트 컨트랙트 보호 방법"
---

# Solidity의 재진입 공격(Reentrancy Attack)이란?

**재진입 공격(reentrancy attack)**은 [Solidity](https://www.alchemy.com/overviews/solidity)에서 스마트 컨트랙트로부터 자금을 반복적으로 인출하여 승인되지 않은 컨트랙트로 전송하는 것으로, 자금이 소진될 때까지 계속됩니다. 이 공격은 악의적 행위자가 취약한 스마트 컨트랙트를 발견했을 때 블록체인의 실행 주기(execution cycle) 동안 발생합니다. 재진입 공격으로 인해 [DAO](https://www.alchemy.com/dapps/top/daos) 및 블록체인 프로토콜에서 수백만 달러가 유출되었습니다.

이 글에서는 재진입 공격의 작동 원리, 두 가지 유형의 재진입 공격, 그리고 **Solidity 개발자**가 Ethereum 및 Solana 블록체인에서 스마트 컨트랙트를 취약점으로부터 보호하기 위해 취할 수 있는 예방 조치를 설명합니다.

## 재진입 공격이란?

재진입 공격은 스마트 컨트랙트 함수가 외부 컨트랙트를 호출하면서 트랜잭션의 제어 흐름을 일시적으로 넘길 때 발생합니다. 이때 호출되는 컨트랙트는 알 수 없거나 악의적인 행위자가 작성한 것일 수 있습니다. 이를 통해 해당 컨트랙트는 자금을 빼내기 위해 원래의 [**스마트 컨트랙트 함수**](https://www.alchemy.com/overviews/solidity-functions)를 재귀적으로 다시 호출할 수 있습니다.

Ethereum 블록체인에서 스마트 컨트랙트의 실행 주기는 잔액을 확인하고, 자금을 전송한 후, 잔액을 업데이트합니다. 스마트 컨트랙트가 에스크로 상태에 있는 동안, 악의적 행위자는 [또 다른 호출을 수행](https://www.alchemy.com/overviews/solidity-call)하여 자금을 인출할 수 있습니다. 이 주기는 모든 자금이 사실상 소진될 때까지 반복됩니다.

## 재진입 공격은 어떻게 작동하는가?

**재진입 공격은 취약한 컨트랙트와 악의적인 컨트랙트, 이 두 스마트 컨트랙트 사이에서 자금을 이동시키는 재귀적 프로세스를 만듭니다.** 재진입 공격의 단계는 다음과 같습니다:

1. 악의적 행위자는 취약한 컨트랙트 "X"를 호출하여 자금을 악의적인 컨트랙트 "Y"로 전송합니다.
1. 컨트랙트 X는 공격자가 필요한 자금을 보유하고 있는지 확인한 후, 자금을 컨트랙트 Y로 전송합니다.
1. 컨트랙트 Y가 자금을 받으면, 잔액이 업데이트되기 전에 컨트랙트 X를 다시 호출하는 _콜백(callback)_ 함수를 실행합니다.
1. 이 재귀적 프로세스는 모든 자금이 소진되어 전송될 때까지 계속됩니다.

**아래 다이어그램은 이러한 공격 시나리오를 보여줍니다:**

<ImageBlock
  src="https://media.alchemy.com/1704184186-reentrancy-attack-scenario.png"
  alt="재진입 공격 다이어그램: 악성 컨트랙트가 잔액 업데이트 전에 재귀적으로 콜백을 호출하는 과정"
  width={752}
  height={481}
  caption="재진입 공격 시나리오 | 이미지 출처: CryptoMarketPool"
/>

## **재진입 공격의 유형에는 어떤 것들이 있는가?**

**재진입 공격에는 단일 함수(single function) 공격과 크로스 함수(cross-function) 공격, 두 가지 유형이 있습니다.**

### **1. 단일 재진입 공격**

단일 재진입 공격은 취약한 함수가 공격자가 재귀적으로 호출하려는 함수와 동일할 때 발생합니다. 단일 재진입 공격은 크로스 함수 재진입 공격보다 단순하고 방지하기 쉽습니다.

### **2. 크로스 함수 공격**

크로스 함수 재진입 공격은 취약한 함수가 공격자에게 유리한 효과를 갖는 다른 함수와 상태를 공유할 때만 가능합니다. 크로스 함수 공격은 탐지가 더 어렵고 방지하기도 더 까다롭습니다.

### **3. 크로스 컨트랙트 공격**

크로스 컨트랙트 재진입 공격은 한 컨트랙트의 상태가 완전히 업데이트되기 전에 다른 컨트랙트에서 호출될 때 발생합니다. 크로스 컨트랙트 재진입 공격은 일반적으로 여러 컨트랙트가 동일한 변수를 수동으로 공유하고 일부 컨트랙트가 해당 공유 변수를 안전하지 않게 업데이트할 때 발생합니다.

## **Solidity 재진입 공격 사례**

다음의 주요 재진입 공격 사례들은 악의적 행위자가 블록체인 프로토콜의 취약점을 어떻게 악용했는지 잘 보여줍니다: The DAO 해킹, Lendf.me, 그리고 [Cream Finance](https://www.alchemy.com/dapps/cream-finance).

### 1. DAO 해킹 \(2016\)

Ethereum의 DAO는 약 6천만 달러 상당의 Ether를 해킹당했습니다. Ethereum의 DAO는 네트워크 참여자들이 투자 결정에 직접 투표할 수 있는 투자 펀드로 설계되었습니다.

DAO는 약 1억 5천만 달러를 모금했지만, 전문가와 커뮤니티 참여자들은 자금을 보관하는 스마트 컨트랙트의 보안에 대해 우려를 제기했습니다. 소스 코드의 재귀 호출 버그로 인해 해당 자금은 재진입 공격에 취약한 스마트 컨트랙트에 잠겨 있었습니다. 개발팀이 문제를 해결하기 전에, 해커가 공격을 실행하여 컨트랙트를 고갈시켰습니다.

### **2. Lendf.me 프로토콜 \(2020\)**

2020년 4월, 악의적 행위자가 Ethereum 네트워크의 탈중앙화 대출 프로토콜인 Lendf.me 프로토콜에서 재진입 공격을 통해 2,500만 달러를 탈취했습니다.

프로토콜 개발자들은 ERC-777 토큰이 자금 송수신을 사용자에게 알리는 콜백 함수를 포함하고 있다는 사실을 간과했습니다. 해커들은 이 취약점을 악용하여 악의적인 스마트 컨트랙트를 수신자로 설정하고 Lendf.me 프로토콜 자금의 99.5%를 유출했습니다.

### **3. Cream Finance 해킹 \(2021\)**

2021년 10월, 악의적 행위자는 프로토콜의 '플래시 론(flash loan)' 기능에 재진입 공격을 사용하여 1억 3천만 달러 이상 상당의 ERC-20 및 CREAM 유동성 프로토콜(LP) 토큰을 탈취했습니다. 이 공격의 근본 원인은 AMP를 CREAM finance 프로토콜에 잘못 통합한 데 있었습니다.

## **재진입 공격을 예방하는 방법**

**엄격한 블록체인 보안 프레임워크를 구축하는 것은 재진입 공격을 예방하고 잠재적 피해를 완화하는 데 매우 중요합니다.** 다음의 재진입 방지 모범 사례들은 개발자와 넓은 web3 커뮤니티가 자금을 보호하는 데 도움이 될 것입니다: 체크-이펙트-인터랙션(checks, effects and interactions, CEI), 재진입 가드(reentrancy guard), 풀 페이먼트(pull payment), 가스 한도(gas limit).

### **체크, 이펙트, 인터랙션 \(CEI\)**

CEI 방식은 재진입을 방지하기 위한 기본적인 방법입니다. 체크(checks)는 조건의 참/거짓 여부를, 이펙트(effects)는 상호작용의 결과로 발생하는 상태 변경을, 인터랙션(interactions)은 함수 또는 컨트랙트 간의 트랜잭션을 의미합니다.

인터랙션보다 이펙트를 먼저 배치할 때 발생할 수 있는 잠재적 보안 위험과 허점은 개발자가 반드시 고려해야 할 중요한 사항입니다.

### **재진입 가드 또는 뮤텍스**

재진입 가드 또는 뮤텍스는 함수 또는 [함수 수정자(function modifier)](https://www.alchemy.com/overviews/solidity-modifier)로 만들 수 있습니다. 재진입에 취약한 함수 호출 주변에 불리언(boolean) 잠금을 배치합니다. 즉, 'locked'의 초기 상태는 false이지만, 취약한 함수 실행이 시작되기 직전에 true로 설정되고, 실행이 종료된 후 즉시 다시 false로 되돌려집니다.

### **풀 페이먼트**

보다 안전한 종단 간(end-to-end) 트랜잭션을 위해서는 풀 페이먼트 방식을 사용할 수 있습니다. 풀 페이먼트 프로세스는 자금을 전송할 때 중개 에스크로를 사용하도록 요구하며, 잠재적으로 악의적인 상대방과의 직접적인 접촉을 피합니다.

중개 에스크로를 통해 자금을 전송함으로써, 스마트 컨트랙트의 자금은 재진입 공격으로부터 보호됩니다. 다만 에스크로가 여러 계정의 자금을 관리하는 경우 재진입에 취약할 수 있습니다. 이 경우 적절한 곳에 CEI 패턴과 재진입 가드를 함께 구현해야 합니다.

### **가스 한도**

가스 한도는 공격자를 막는 최적의 방법이 아닙니다. 가스 비용은 변경될 수 있는 Ethereum의 opcode에 따라 달라지기 때문입니다. 반면 스마트 컨트랙트 코드는 변경할 수 없습니다.

[_send_, _transfer_, _call_ 함수](https://www.alchemy.com/overviews/solidity-functions)의 차이를 이해하는 것이 중요합니다. _send_와 _transfer_는 사실상 동일하지만, 트랜잭션이 실패할 경우 _transfer_는 되돌려지는(revert) 반면 _send_는 그렇지 않습니다.

_send_ 및 _transfer_와 달리, _call_ 함수는 가스 한도가 없으며 멀티 컨트랙트 트랜잭션을 실행하기 위해 가스를 전달합니다. 안타깝게도 이는 재진입 공격이 가능해진다는 의미이기도 합니다.

## **Alchemy University에서 재진입 공격에 대해 더 알아보기**

Ethereum에서 스마트 컨트랙트의 실행 주기는 완벽하게 안전한 프로세스가 아닙니다. 악의적 행위자들은 [재진입 공격](https://solidity-by-example.org/hacks/re-entrancy/)을 실행하여 취약한 스마트 컨트랙트에서 자금을 전송하고 빼내는 방식으로 블록체인을 악용합니다. 예방 조치를 취하는 것은 Solidity 개발자에게 더 안전한 실행 주기와 블록체인 프로토콜 보호를 보장해 줄 것입니다.

Solidity 스마트 컨트랙트 개발 모범 사례를 배우려면, Alchemy의 무료 [7주 Ethereum 개발자 부트캠프](https://www.alchemy.com/university/courses/ethereum?a=c1cf9a376f)에 참여하세요. 원래 3,000달러 상당의 인증 과정이었던 Alchemy University의 부트캠프는 [Solidity를 무료로 배울](https://www.alchemy.com/overviews/learn-solidity) 수 있는 최고의 곳입니다.

개발을 처음 접하는 분이라면, Alchemy의 **3주 JavaScript 속성 과정**이 Ethereum 부트캠프를 시작하기 전 좋은 사전 준비 과정이 될 것입니다.
