2 月 3 日上午(時區 +8),我們的系統監測到針對 HypeBears NFT 合約的一筆攻擊交易 0xfa97c3476aa8aeac662dae0cc3f0d3da48472ff4e7c55d0e305901ec37a2f704。經調查發現,這是一起由 ERC721 的 _safeMint 函數引起的重入攻擊。
根本原因
該項目對帳戶可鑄造的 NFT 數量有限制。基本上,它使用一個 addressMinted 映射來記錄帳戶是否已經鑄造過 NFT。
在鑄造 NFT 時,代碼使用了 OpenZeppelin (OZ) 參考實現中的 _safeMint 函數。之所以稱此函數為「安全 (safe)」,是因為它會檢查接收者是否具備接收 ERC721 代幣的能力,這能防止將 NFT 鑄造到無法處理 ERC721 代幣的合約地址。根據 文檔 說明:
如果
to參數指向一個智能合約,則該合約必須實現IERC721Receiver.onERC721Received接口,以便在安全轉帳時被調用。下圖展示了 OZ 對_safeMint函數的實現。

然而,這個外部函數調用產生了一個安全漏洞。具體來說,攻擊者可以在 onERC721Received 回調中執行重入調用。例如,在 易受攻擊的 HypeBears 合約中,攻擊者可以在 onERC721Received 回調中再次調用 mintNFT 函數(因為 addressMinted 狀態尚未更新)。

攻擊過程
下圖展示了這筆 攻擊交易。

教訓
SafeMint 帶來的風險已被多位安全研究人員討論過(連結 1,連結 2)。然而,我們仍然能在現實中看到此類易受攻擊的代碼與攻擊事件。正如 QBridge 安全事件 中 safeTransfer 的情況一樣,使用一個名為「安全」的函數並不保證合約本身就是「安全」的 😃。



