NFTコントラクトにおけるコード再入:セキュアなスマートコントラクト開発

NFTスマートコントラクトの重要なセキュリティ懸念事項、特にリエントランシー脆弱性とEthereumエコシステムへの影響を探ります。

NFTコントラクトにおけるコード再入:セキュアなスマートコントラクト開発

はじめに

EthereumにおけるNFTエコシステムの隆盛と、それに伴うセキュリティ問題の増加を鑑み、本シリーズではこれらのセキュリティ問題を紹介し、開発者向けにコントラクトを安全に保つための提案を行います。本稿では、NFTコントラクトにおけるリエントランシー問題と、関連する脆弱性の軽減策について解説します。

リエントランシーとは

Wikipediaによると

コンピューティングにおいて、コンピュータプログラムまたはサブルーチンは、複数の invoc者が複数のプロセッサで安全に並行して実行できる場合、または単一のプロセッサシステムで、リエントラントなプロシージャは、その実行の途中で中断され、以前の invoc者が実行を完了する前に安全に再度呼び出される(「再入力」される)ことができる場合、リエントラントであると呼ばれます。

スマートコントラクトでは、関数が別のコントラクトの外部呼び出しを実行し、その外部呼び出しが元の関数呼び出しが返される前に元の関数(または他の関数)をさらに呼び出す場合に、リエントランシーが発生する可能性があります。外部呼び出しが信頼できないエンティティ(例:悪意のあるコントラクト)によって制御されている場合、予期せぬ結果につながる可能性があります。これは、一部の関数では結果がコントラクトの状態に依存するためです。コントラクトの状態は、外部呼び出しの後に更新されます。しかし、関数のリエントラントな呼び出しは、更新された状態ではなく、古い状態を使用します。

リエントランシーは、スマートコントラクトにおける一般的な問題です。例えば、MakerDAO攻撃や、Uniswap上のERC777などが挙げられます(BlockSec Academyでリエントランシーを検索)。

NFTにおけるリエントランシー

NFTコントラクトでは、開発者が見落としがちな暗黙的な外部関数呼び出しが存在する場合があります。これには onERC721Received および onERC1155Received 関数が含まれます。onERC721Received 関数は、受信側コントラクトがNFTを処理できるかどうかを確認するために設計されています(NFTが永久にロックされるのを防ぐため)。この関数は、ERC721コントラクトsafeTransferFrom および _safeMint で呼び出されます。ERC1155コントラクトにも同様のものが存在します。これらの外部関数呼び出しにより、コントラクト開発者に気づかれずにリエントランシーが発生する可能性があります。

シングルファンクションリエントランシー

シングルファンクションリエントランシーは、リエントランシー攻撃のより単純な形態です。この種のリエントランシー攻撃では、再入力される関数は元の関数と同じです。攻撃者は、関数の最初の呼び出しが完了する前に、関数を繰り返し呼び出すことができます。NFTコントラクトでは、これは通常 mint 操作に関連する関数で発生します。

例えば、一部のNFTプロジェクトでは、各ユーザーに無料でNFTをミントする機会を与えたり、プロジェクト全体の最大供給量を設定したり、1人のユーザーが保有できるNFTの最大量を設定したりする場合があります。通常、これらの制約は実際のミント操作の前にチェックされます。しかし、これらの制約に関連する状態が safeMint 関数の後に更新される場合、攻撃者はこのミント関数に再入力して制約を回避できます。これは、関連する状態がこの関数の最初の呼び出しと同じであるためです。以前のブログで投稿されたHypeBearsのリエントランシー攻撃がその例です。

より複雑なシングルファンクションリエントランシーは、safeMint 関数がループ内で使用され、制約がループの開始前にチェックされる場合に発生します。このシナリオでは、一部の状態が外部呼び出しの前に自動的に更新されるとしても、ループがすでに開始され、検証がループの開始前に行われるため、ループ内の残りの safeMint 関数呼び出しは引き続き検証を回避できます。

例えば、別の投稿で示されている例では、mintNFT 関数は、ユーザーがミントしたいNFTの数と現在の供給量を合計しても最大供給量を超えないかどうかをチェックします。safeMint 関数は、onERC721Received 外部呼び出しの前に総供給量を更新します。攻撃者は、safeMint 関数が一度に総供給量を1ずつしか増やさないため、依然としてこれを悪用できます。したがって、攻撃者がループ内の safeMint の最初の関数呼び出しで mintNFT 関数に再入力すると、総供給量は、mintNFT の最初の呼び出しでミントされるNFTの量ではなく、古い供給量に1を加えたものになります。

クロスファンクションリエントランシー

攻撃者は、同じ関数に入力する代わりに、元の関数と状態を共有または依存する別の関数に入力できます。以前のブログでは、RevestケースOMNIケースでいくつかのケースを詳細に説明しました。

まとめと提案

NFTスマートコントラクト開発者がリエントランシーの脅威を軽減するための提案を以下に示します。

  1. コードでChecks-Effects-Interactionsパターンを使用してください。
  2. 外部呼び出しを導入するサードパーティライブラリを使用する際は注意してください。NFTコントラクトでは、onERC721Received および onERC1155Received 関数の暗黙的なコールバックに注意してください。

本シリーズの他の記事を読む

BlockSecについて

BlockSecは、2021年に世界的に著名なセキュリティ専門家チームによって設立された、先駆的なブロックチェーンセキュリティ企業です。当社は、Web3の普及を促進するために、新興のWeb3世界のセキュリティとユーザビリティの向上に尽力しています。この目的のため、BlockSecはスマートコントラクトおよびEVMチェーンのセキュリティ監査サービス、セキュリティ開発と脅威のプロアクティブなブロックのためのPhalconプラットフォーム、資金追跡と調査のためのMetaSleuthプラットフォーム、そしてWeb3開発者が仮想通貨の世界を効率的にサーフィンするためのMetaSuites拡張機能を提供しています。

現在までに、MetaMask、Uniswap Foundation、Compound、Forta、PancakeSwapなど300社以上の著名なクライアントにサービスを提供し、Matrix Partners、Vitalbridge Capital、Fenbushi Capitalなどの有力な投資家から2回の資金調達ラウンドで数千万米ドルを獲得しています。

公式ウェブサイト:https://blocksec.com/

公式Twitterアカウント:https://twitter.com/BlockSecTeam

Sign up for the latest updates