ソフトウェア開発において、チェック時と使用時(TOCTOU、TOCTTOU、またはTOC/TOU )とは、システムの一部(セキュリティ認証情報など)の状態をチェックすることと、そのチェック結果を使用することに関わる競合状態によって引き起こされるソフトウェアバグの一種です。
TOCTOU の競合状態は、Unixではファイルシステムの操作間でよく発生しますが、[ 1 ]ローカルソケットやデータベーストランザクションの不適切な使用など、他のコンテキストでも発生する可能性があります。1990 年代初頭、BSD 4.3 UNIX のメールユーティリティは、[ 2 ]関数を使用していたため、一時ファイルに対して悪用可能な競合状態がありました。[ 3 ] OpenSSH の初期バージョンには、 Unix ドメインソケットに対して悪用可能な競合状態がありました。[ 4 ]これらは現代のシステムでも問題であり、2019 年現在、Dockerの TOCTOU 競合状態により、ホストプラットフォームのファイルシステムへの root アクセスが可能になります。[ 5 ] 2023 年にバンクーバーで開催されたPwn2Ownコンペティションでは、ハッカーのチームがこのバグを使用して、更新されたTesla Model 3のゲートウェイを侵害することができました。[ 6 ] 2025 年に、 Amazon Web ServicesのDynamoDB用DNS管理システム の TOCTOU 競合状態により、US-EAST-1 リージョン全体で大規模な障害が発生しました。この事件は、新しいDNSプランが既にクリーンアップされた後に古いDNSプランが適用されたことが原因で、エンドポイントIPアドレスの削除と広範囲にわたるサービス障害が発生した。[ 7 ]mktemp()
プログラムは、以下の場合にTOCTOUの競合状態に対して脆弱である。
そして、以下のケースが該当します。
そして、もし別のプロセスがステップ1とステップ2の間で実際にプロパティを変更した場合、ステップ2は古い情報に基づいて実行されることになり、意図しない結果を招く可能性があります。
実行中のプログラムが特権を持ち、かつ非特権プロセスがそのプロパティに影響を与えることができる場合、非特権プロセスは事実上、特定の特権タスクを実行できてしまう。
特に、プロパティが何らかのアクションが許可されているかどうかをチェックし、それによって権限チェックなどのセキュリティ境界を実装している場合、この権限チェックを完全にバイパスすることができ、さまざまな特権アクションをこのようにして実行できます(権限昇格)。
Unix環境では、以下のC言語コードをプログラムで使用するとsetuid、TOCTOUバグが発生します。
if ( access ( "file" , W_OK ) != 0 ) {終了(1 )}fd = open ( "file" , O_WRONLY );write ( fd , buffer , sizeof ( buffer ));ここでのアクセスは、プログラムを実行した実際のユーザーがsetuid通常ファイルへの書き込みを許可されているかどうかを確認することを目的としています(つまり、実効ユーザーIDではなく、実際のユーザーIDaccessを確認します)。
この競合状態は、以下の攻撃に対して脆弱です。
accessこの例では、攻撃者はとの間の競合状態を利用して、被害者openをだましてシステムパスワードデータベースのエントリを上書きさせることができます。TOCTOU の競合は、権限昇格に利用され、マシンへの管理者権限を取得するためsetuidに使用できます。
この一連の出来事には正確なタイミングが求められるものの、攻撃者にとってはそれほど困難なくこのような状況を作り出すことが可能である。
つまり、アプリケーションは、オペレーティングシステムによって管理される状態(この場合はファイルシステムの名前空間)がシステムコール間で変化しないと想定することはできないということだ。
TOCTOUの競合状態を悪用するには、攻撃者の操作が被害者の操作と適切にインターリーブされるように、正確なタイミングが求められます。上記の例では、攻撃者はsymlinkシステムコールをaccessとの間に正確に実行する必要がありますopen。最も一般的な攻撃では、攻撃者は被害者による各操作の後に実行されるようにスケジュールする必要があり、これは被害者の「シングルステップ」とも呼ばれます。
BSD 4.3 のメールユーティリティの場合mktemp()、[ 2 ]攻撃者は単に 1 つのプロセスでメールユーティリティを起動し続け、一時ファイル名を推測し続け、別のプロセスでシンボリックリンクを作成し続けることができます。この攻撃は通常 1 分以内に成功します。
被害者プログラムをシングルステップ実行するための手法には、ファイルシステム迷路[ 8 ]やアルゴリズム複雑性攻撃[ 9 ]などがあります。どちらの場合も、攻撃者はOSの状態を操作して被害者のスケジューリングを制御します。
ファイルシステムの迷路攻撃では、被害者はOSキャッシュに存在しないディレクトリエントリを読み込まざるを得なくなり、OSはディスクからディレクトリを読み込んでいる間、被害者をスリープ状態にします。アルゴリズムの複雑性攻撃では、被害者はカーネルのキャッシュされたファイル名のハッシュテーブルを走査する単一のシステムコール内でスケジューリング量子全体を消費せざるを得なくなります。攻撃者は、被害者が検索するファイルと同じハッシュ値を持つ名前のファイルを大量に作成します。
概念的には単純であるにもかかわらず、TOCTOU の競合状態は回避および排除が困難です。一般的な手法の 1 つは、事前チェックの代わりにエラー処理を使用することです。これは、「許可を求めるより許しを請う方が簡単」という EAFP の哲学に基づき、「軽率な行動は避ける」という LBYL の哲学とは異なります。この場合、チェックは行われず、仮定が成り立たないことはエラーが返されることで通知されます。[ 10 ]
ファイルシステムのTOCTOU競合状態に関して、根本的な課題は、2つのシステムコール間でファイルシステムが変更されないことを保証することです。2004年に、Unixaccessとopenファイルシステムのコールを使用する場合にTOCTOU競合状態を回避するための移植可能で決定論的な手法は存在しないことを示す不可能な結果が発表されました。[ 11 ]
この不可能な結果以来、研究者たちはファイルディスクリプタを追跡し、正当性を保証するためのライブラリを提案してきた。[ 12 ]
研究コミュニティで提案されている代替ソリューションは、Unix システムでファイルシステムまたは OS カーネルにトランザクションを採用することです。トランザクションは OS に並行性制御の抽象化を提供し、TOCTOU レースを防ぐために使用できます。まだ実用化された Unix カーネルでトランザクションを採用しているものはありませんが、Valor ファイルシステム[ 13 ]や TxOS カーネル[ 14 ] など、Linux 向けの概念実証研究プロトタイプが開発されています。Microsoft Windows はNTFSファイルシステムにトランザクションを追加しましたが[ 15 ]、Microsoft はトランザクションの使用を推奨しておらず、将来のバージョンの Windows で削除される可能性があることを示唆しています[ 16 ] 。
ファイルロックは、単一ファイルにおける競合状態を防ぐための一般的な手法ですが、ファイルシステムの名前空間やその他のメタデータには適用されず、ネットワークファイルシステムではうまく機能せず、TOCTOU競合状態を防ぐこともできません。
バイナリの場合、システムコールを使用して実効ユーザーを変更してから呼び出しを実行するというsetuid解決策が考えられます。オペレーティングシステム間の違いが問題となる場合があります。[ 17 ]seteuid()open()setuid()
TOCTOUの脆弱性により、大規模システムで重大な障害が発生しました。2025年10月、AWSはDynamoDBのDNS管理システムにおける競合状態により、大きな障害に見舞われました。このインシデントでは、新しいDNSプランが既にクリーンアップされた後に古いDNSプランが適用され、エンドポイントIPの削除と広範囲にわたるサービス障害が発生しました。[ 18 ]
{{cite web}}: CS1メンテナンス: アーカイブサービスは非推奨になりました (リンク)