Back to Blog

안전한 스마트 계약 개발 — NFT 계약의 코드 재진입 취약점

Code Auditing
August 5, 2022
3 min read

소개

이더리움의 NFT 생태계 번영과 관련 보안 문제의 증가에 따라, 저희는 이러한 보안 문제들을 소개하고 개발자들이 컨트랙트를 안전하게 보호할 수 있도록 몇 가지 제안을 담은 블로그 시리즈를 게시할 예정입니다. 이번 블로그에서는 NFT 컨트랙트의 재진입 문제와 관련 취약점을 완화하는 방법을 소개합니다.

재진입이란 무엇인가

위키피디아에 따르면

컴퓨팅에서, 여러 번의 호출이 다중 프로세서에서 또는 단일 프로세서 시스템에서 안전하게 동시에 실행될 수 있을 때, 즉 재진입 가능한 프로시저가 실행 도중 중단되었다가 이전 호출이 완료되기 전에 다시 안전하게 호출("재진입")될 수 있을 때, 해당 컴퓨터 프로그램 또는 서브루틴을 재진입 가능하다고 합니다.

스마트 컨트랙트에서 재진입은 함수가 다른 컨트랙트의 외부 호출을 실행할 때 발생할 수 있으며, 원래의 호출이 반환되기 전에 해당 외부 호출이 다시 원래 함수(또는 다른 함수)를 호출하는 경우에 해당합니다. 외부 호출이 신뢰할 수 없는 주체(예: 악의적인 컨트랙트)에 의해 제어되는 경우 예상치 못한 결과로 이어질 수 있습니다. 이는 일부 함수에서 결과가 컨트랙트 상태에 의존하기 때문입니다. 컨트랙트 상태는 외부 호출 이후에 업데이트됩니다. 그러나 함수의 재진입 호출은 업데이트된 상태 대신 이전 상태를 사용하게 됩니다.

재진입은 스마트 컨트랙트에서 만연한 문제로, 예를 들어 MakerDAO 공격, Uniswap의 ERC777, 그 외 다수가 있습니다(BlockSec Academy에서 재진입 검색).

NFT의 재진입

NFT 컨트랙트에는 개발자들이 간과할 수 있는 암묵적인 외부 함수 호출이 존재합니다. 여기에는 onERC721ReceivedonERC1155Received 함수가 포함됩니다. onERC721Received 함수는 수신자 컨트랙트가 NFT를 처리할 수 있는지 확인하기 위해 설계되었습니다(NFT가 영구적으로 잠기는 것을 방지하기 위함). 이 함수는 ERC721 컨트랙트safeTransferFrom_safeMint에서 호출됩니다. 유사한 함수가 ERC1155 컨트랙트에도 존재합니다. 이러한 외부 함수 호출로 인해 컨트랙트 개발자들이 인지하지 못한 채 재진입이 발생할 수 있습니다.

단일 함수 재진입

단일 함수 재진입은 재진입 공격의 더 단순한 형태입니다. 이 유형의 재진입 공격에서는 재호출되는 함수가 원래 함수와 동일합니다. 공격자는 첫 번째 함수 호출이 완료되기 전에 해당 함수를 반복적으로 호출할 수 있습니다. NFT 컨트랙트에서는 일반적으로 mint 작업과 관련된 함수에서 이러한 일이 발생합니다.

예를 들어, 일부 NFT 프로젝트는 각 사용자에게 무료로 NFT를 민팅할 기회를 제공하거나, 전체 프로젝트의 최대 공급량을 설정하거나, 한 사용자가 보유할 수 있는 최대 NFT 수량을 설정할 수 있습니다. 일반적으로 이러한 제약 조건은 실제 민팅 작업 전에 확인됩니다. 그러나 이러한 제약 조건과 관련된 상태가 safeMint 함수 이후에 업데이트된다면, 공격자는 관련 상태가 첫 번째 호출과 동일하기 때문에 이 민팅 함수에 재진입하여 제약 조건을 우회할 수 있습니다. 이전 블로그에서 게시된 HypeBears 재진입 공격이 그 예시입니다.

더 복잡한 단일 함수 재진입은 safeMint 함수가 루프 내에서 사용되고 제약 조건이 루프 시작 전에 확인될 때 발생합니다. 이 시나리오에서는 일부 상태가 외부 호출 전에 자동으로 업데이트되더라도, 루프 내의 나머지 safeMint 함수 호출은 루프가 이미 시작되었고 유효성 검사가 루프 시작 전에 이루어지기 때문에 유효성 검사를 우회할 수 있습니다.

예를 들어, 다른 게시물에 나와 있는 예시에서 mintNFT 함수는 사용자가 민팅하려는 NFT 수와 현재 공급량의 합이 최대 공급량을 초과하는지 확인합니다. safeMint 함수는 onERC721Received 외부 호출 전에 총 공급량을 업데이트합니다. 공격자는 safeMint 함수가 매번 총 공급량을 1씩만 증가시키기 때문에 이를 악용할 수 있습니다. 따라서 공격자가 루프 내 첫 번째 safeMint 함수 호출에서 mintNFT 함수에 재진입하면, 총 공급량은 첫 번째 mintNFT 호출로 민팅될 NFT 수만큼 증가한 이전 공급량이 아닌, 이전 공급량에 1을 더한 값이 됩니다.

교차 함수 재진입

동일한 함수에 진입하는 대신, 공격자는 원래 함수와 상태를 공유하거나 의존하는 다른 함수에 진입할 수 있습니다. 저희는 이전 블로그에서 Revest 사례OMNI 사례에 대해 자세히 설명한 바 있습니다.

요약 및 제안

다음은 재진입 위협을 완화하기 위한 NFT 스마트 컨트랙트 개발자들을 위한 몇 가지 제안입니다.

  1. 코드에서 검사-효과-상호작용 패턴을 사용하세요.
  2. 외부 호출을 유발하는 서드파티 라이브러리를 사용할 때 주의하세요. NFT 컨트랙트의 경우 onERC721ReceivedonERC1155Received 함수의 암묵적인 콜백에 주의하세요.

이 시리즈의 다른 글 읽기

BlockSec 소개

BlockSec은 2021년 전 세계적으로 저명한 보안 전문가 그룹에 의해 설립된 선구적인 블록체인 보안 회사입니다. 이 회사는 대중적 채택을 촉진하기 위해 신흥 Web3 세계의 보안과 사용성을 향상시키는 데 전념하고 있습니다. 이를 위해 BlockSec은 스마트 컨트랙트 및 EVM 체인 보안 감사 서비스, 보안 개발 및 위협 선제 차단을 위한 Phalcon 플랫폼, 자금 추적 및 조사를 위한 MetaSleuth 플랫폼, 그리고 Web3 빌더들이 크립토 세계를 효율적으로 탐색할 수 있도록 돕는 MetaSuites 확장 프로그램을 제공합니다.

현재까지 이 회사는 MetaMask, Uniswap Foundation, Compound, Forta, PancakeSwap 등 300개 이상의 저명한 고객사에 서비스를 제공했으며, Matrix Partners, Vitalbridge Capital, Fenbushi Capital을 포함한 저명한 투자자들로부터 두 차례의 파이낸싱 라운드를 통해 수천만 달러를 조달했습니다.

공식 웹사이트: https://blocksec.com/

공식 트위터 계정: https://twitter.com/BlockSecTeam

Sign up for the latest updates
~$160만 손실: Moke 토큰, LpdFi 익스플로잇 | BlockSec 위클리
Security Insights

~$160만 손실: Moke 토큰, LpdFi 익스플로잇 | BlockSec 위클리

2026년 8월 3~9일, BNB 체인에서 2건의 보안 사고가 발생해 총 약 160만 달러의 손실이 발생했으며, 모두 가격 조작이 원인이었습니다. LpdFi(약 69.7만 달러)는 PancakeSwap 유동성 풀을 주문 평가와 이자 정산에 동시 사용해 공격자가 원금을 부풀리고 과도한 이자를 탈취했습니다. Moke Token(약 90.6만 달러)은 조작 가능한 현물 가격과 중복 LP 배당 회계를 결합해 MOKE를 부풀려 BNB 배당을 반복 수령했습니다.

COLDCARD 사건: 지갑의 "무작위" 시드가 무작위가 아니었을 때
Security Insights

COLDCARD 사건: 지갑의 "무작위" 시드가 무작위가 아니었을 때

COLDCARD 펌웨어의 빌드 통합 버그로 비트코인 시드 생성이 취약한 소프트웨어 RNG로 라우팅되어 지갑 시드가 오프라인 복구 가능해졌습니다. 시드 자체의 취약점이므로 펌웨어 업데이트로 해결 불가하며, 2026년 8월 7일 기준 확인된 피해는 1,405 BTC(~9,100만 달러), 비공개 추정치는 최대 2,055 BTC입니다.

~$88M 손실: COLDCARD 및 LULA 익스플로잇 | BlockSec 위클리
Security Insights

~$88M 손실: COLDCARD 및 LULA 익스플로잇 | BlockSec 위클리

2026년 7월 27일~8월 2일, 비트코인과 BNB 체인에서 약 8,800만 달러 손실을 유발한 두 건의 보안 사고가 발생했습니다. COLDCARD 사고는 하드웨어 지갑 펌웨어의 엔트로피 오류로, RNG 매크로 활성화 여부 미확인으로 결정론적 폴백이 실행되어 약 1,370 BTC(~8,800만 달러)가 탈취됐습니다. BNB 체인의 LULA 토큰은 비즈니스 로직 취약점으로 `recycle()` 함수가 악용되어 PancakeSwap V2 유동성에서 약 57만 8천 달러가 유출됐습니다.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit