2월 3일 오전 (+8 시간대)에, 저희 시스템은 HypeBears NFT 컨트랙트를 대상으로 한 공격 트랜잭션 0xfa97c3476aa8aeac662dae0cc3f0d3da48472ff4e7c55d0e305901ec37a2f704을 감지했습니다. 조사 결과, ERC721의 _safeMint 함수로 인해 발생한 재진입(re-entrancy) 공격임을 확인했습니다.
근본 원인
해당 프로젝트는 계정당 민팅할 수 있는 NFT 수에 제한을 두고 있습니다. 기본적으로 계정이 NFT를 민팅했는지 여부를 기록하는 addressMinted라는 맵을 가지고 있습니다.
NFT를 민팅할 때, 코드는 OZ 참조 구현체의 _safeMint 함수를 사용합니다. 이 함수가 safe한 이유는 수신자가 ERC721 토큰을 받을 수 있는지 확인하기 때문입니다. 이는 ERC721 토큰을 처리할 수 없는 컨트랙트로 NFT가 민팅되는 경우를 방지할 수 있습니다. 문서에 따르면:
만약 수신자가 스마트 컨트랙트를 참조하는 경우, 안전한 전송 시 호출되는 IERC721Receiver.onERC721Received를 구현해야 합니다. 다음 코드는
_safeMint함수의 OZ 구현체를 보여줍니다.

그러나 이 외부 함수 호출은 보안 허점을 만들어냅니다. 구체적으로, 공격자는 onERC721Received 콜백 내부에서 재진입 호출을 수행할 수 있습니다. 예를 들어, 취약한 HypeBears 컨트랙트에서, 공격자는 onERC721Received 콜백 내에서 mintNFT 함수를 다시 호출할 수 있습니다 (addressMinted가 아직 업데이트되지 않았기 때문입니다).

공격 과정
다음 스크린샷은 공격 트랜잭션을 보여줍니다.

교훈
SafeMint로 인한 위험성은 보안 연구자들에 의해 이미 논의된 바 있습니다 링크1 링크2. 그러나 여전히 취약한 코드와 실제 공격 사례를 볼 수 있습니다. QBridge 보안 사고에서의 safeTransfer에서 보여주듯이, safe 함수를 사용한다고 해서 안전한 컨트랙트가 보장되는 것은 아닙니다 😃.



