소개
이더리움의 NFT 생태계 번영과 관련 보안 문제의 증가에 따라, 저희는 이러한 보안 문제들을 소개하고 개발자들이 컨트랙트를 안전하게 보호할 수 있도록 몇 가지 제안을 담은 블로그 시리즈를 게시할 예정입니다. 이번 블로그에서는 NFT 컨트랙트의 재진입 문제와 관련 취약점을 완화하는 방법을 소개합니다.
재진입이란 무엇인가
위키피디아에 따르면
컴퓨팅에서, 여러 번의 호출이 다중 프로세서에서 또는 단일 프로세서 시스템에서 안전하게 동시에 실행될 수 있을 때, 즉 재진입 가능한 프로시저가 실행 도중 중단되었다가 이전 호출이 완료되기 전에 다시 안전하게 호출("재진입")될 수 있을 때, 해당 컴퓨터 프로그램 또는 서브루틴을 재진입 가능하다고 합니다.
스마트 컨트랙트에서 재진입은 함수가 다른 컨트랙트의 외부 호출을 실행할 때 발생할 수 있으며, 원래의 호출이 반환되기 전에 해당 외부 호출이 다시 원래 함수(또는 다른 함수)를 호출하는 경우에 해당합니다. 외부 호출이 신뢰할 수 없는 주체(예: 악의적인 컨트랙트)에 의해 제어되는 경우 예상치 못한 결과로 이어질 수 있습니다. 이는 일부 함수에서 결과가 컨트랙트 상태에 의존하기 때문입니다. 컨트랙트 상태는 외부 호출 이후에 업데이트됩니다. 그러나 함수의 재진입 호출은 업데이트된 상태 대신 이전 상태를 사용하게 됩니다.
재진입은 스마트 컨트랙트에서 만연한 문제로, 예를 들어 MakerDAO 공격, Uniswap의 ERC777, 그 외 다수가 있습니다(BlockSec Academy에서 재진입 검색).
NFT의 재진입

NFT 컨트랙트에는 개발자들이 간과할 수 있는 암묵적인 외부 함수 호출이 존재합니다. 여기에는 onERC721Received와 onERC1155Received 함수가 포함됩니다. 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 스마트 컨트랙트 개발자들을 위한 몇 가지 제안입니다.
- 코드에서 검사-효과-상호작용 패턴을 사용하세요.
- 외부 호출을 유발하는 서드파티 라이브러리를 사용할 때 주의하세요. NFT 컨트랙트의 경우
onERC721Received와onERC1155Received함수의 암묵적인 콜백에 주의하세요.
이 시리즈의 다른 글 읽기
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



