用語辞典7分で読める

TOCTOUとは:確認してから使うまでの隙に状態が変わってしまう問題

TOCTOU(time-of-check to time-of-use)は、確認した後、使うまでの間に状態が変わる競合状態です。仕組みと、確認と使用を一体にする防ぎ方を解説します。

本文を読む
公開日
更新日
目次

TOCTOU(time-of-check to time-of-use)は、「確認した時点」と「使う時点」の間に状態が変わってしまう問題です。仕組みと防ぎ方を解説します(攻撃手順は載せません)。

TOCTOUとは

プログラムは「確認して、問題なければ使う」という順序で動くことがよくあります。たとえば「このファイルは書き込んでよいものか確認し、よければ開いて書く」です。ところが、確認と使用の間には小さな時間差があります。その間に別のプログラムや別のリクエストが対象を変えると、確認の結果はもう成り立ちません。

MITREのCWE-367は、これを「資源の状態を確認してから使うまでの間に、確認の結果が成り立たなくなる形で状態が変わる」場合として説明しています。CWE(Common Weakness Enumeration)は、脆弱性の原因となる弱点を分類した共通の一覧です。TOCTOUは、同時に動く処理のタイミングで結果が変わる「競合状態(race condition)」の一種です。

なぜ起きるか(仕組み)

① 確認:このファイルは書き込んでよいものか → OK
② 隙間:別の処理が、同じ名前の指す先を差し替える
↓ 確認の結果は、もう今の状態に当てはまらない
③ 使用:確認していない対象に、そのまま書き込んでしまう
確認と使用が別の操作に分かれていると、その間に対象が入れ替わり、確認の結果が古くなる。

CWE-367によると、この問題が起きると、本来使えない資源に読み書きできてしまう、資源が意図しない形で変更される、ログが残らなくなる、といった影響が出ることがあります。隙間は短くても、大量の処理が同時に動く環境では、偶然ではなく繰り返し起こり得ます。

よく出る場所

場所確認使用起きること
ファイル操作存在・権限の確認開く・書く確認後に別のファイルに差し替わる
Webアプリの在庫・残高SELECTで残数を確認UPDATEで減らす同時の2件が両方とも確認を通り、残数を超えて処理される
決済・申込未処理かを確認処理を実行二重送信で同じ処理が2回走る
ファイルのアップロード内容を検査保存・公開検査した後に内容が変わる

アップロードの検査については、ファイルアップロード脆弱性も参照してください。

防御:確認と使用を切り離さない

1

確認してから使う形をやめる

CWE-367の最も基本的な助言は、使う前に確認をしないことです。確認を挟まずに使い、失敗したらエラーを処理する形にすると、隙間そのものがなくなります。

2

パスではなくファイルディスクリプタで扱う

ファイルは、まず開いて、開いたファイルディスクリプタに対して状態の確認や書き込みを行います。同じパス名を何度も引くと、そのたびに別の対象を指す可能性があります。シンボリックリンクをたどらない O_NOFOLLOW や、ディレクトリを基準に開く openat も役に立ちます(使える機能はOSにより異なります)。

3

データベースは条件付き更新とトランザクションで

「確認のSELECT→更新のUPDATE」ではなく、条件を含めた1回のUPDATE(例:残数が1以上のときだけ減らす)にします。複数の文にまたがる場合は、トランザクションと適切な分離レベル、行のロックを使います。

4

ロックは確認の前にかける

ロックを使うなら、CWE-367のとおり確認より前に行います。確認の後にかけても、確認した対象と使う対象が同じとは限りません。

5

二重実行は冪等キーで止める

決済や申込のような処理は、リクエストごとに一意のキー(冪等キー)を持たせ、同じキーの処理は1回しか実行しないようにします。

自分のコードで確認する方法

自分が開発・管理するコードで行います。

  1. 「確認する処理」と「使う処理」が別の呼び出しになっている箇所を探す(ファイルの存在確認→オープン、SELECT→UPDATEなど)
  2. 見つけたら、確認を外して1つの操作にできるかを考える
  3. 同じ要求を同時に複数回送るテストを書き、結果が1回分だけ反映されることを確かめる
  4. 他人のサービスに対して試してはいけません。必ず自分の環境で行います

当サイトの視点:『確認』は『使用』と同じ操作の中に入れる

TOCTOUは「確認を忘れた」問題ではなく、「確認はしているのに、確認と使用が離れている」問題です。そのため、確認のコードを増やしても直りません。直す方向は、確認を別の手順として足すことではなく、確認を使用と同じ不可分な操作の中に入れることです。IDORと並べて、「チェックはあるのに効いていない」型の脆弱性として覚えておくと、レビューで見つけやすくなります。

出典(一次情報)

  • MITRE CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition — cwe.mitre.org(定義、影響、緩和策)
  • 具体的な手法(O_NOFOLLOW、openat、冪等キー、トランザクション)は、一般的な実装上の手法として記載しています。使える機能はOSやデータベースにより異なるため、各製品の公式ドキュメントで確認してください

次に読む

分類番号

CWE は脆弱性の原因となる弱点の種類を、MITRE ATT&CK は攻撃者の手口を分類した番号体系です。どちらも MITRE が管理し、脆弱性情報や検知ルールの分類に広く使われています。

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

よくある質問

QTOCTOUとは何ですか?
A

Time-of-check to time-of-use の略で、『確認した時点』と『使う時点』の間に、対象の状態が変わってしまう問題です。MITREのCWE-367は、資源の状態を確認してから使うまでの間に状態が変わり、確認の結果が成り立たなくなる場合と説明しています。競合状態(race condition)の一種です。

QTOCTOUはどんな場所で起きますか?
A

代表的なのはファイルの操作です。『ファイルが存在するか/書いてよいか』を確認した後、別の呼び出しで開くと、その間にファイルが差し替えられることがあります。ほかにも、『在庫があるか確認→購入を確定』『残高を確認→引き落とし』のように、確認と更新が分かれているWebアプリのデータベース処理でも起きます。

Q一番の防ぎ方は何ですか?
A

確認と使用を1つの不可分な操作にまとめることです。CWE-367も、最も基本的な助言は『使う前に確認をしない』ことだとしています。ファイルなら、開いた後にそのファイルディスクリプタに対して確認や操作を行います。データベースなら、条件付きの更新や、トランザクションとロックを使います。

Qロックをかければ必ず安全ですか?
A

ロックは確認より前にかける必要があります。CWE-367も、ロックは確認の後ではなく前に行うよう勧めています。確認の後でロックしても、確認した対象と使う対象が同じである保証にならないためです。また、ロックの範囲が狭すぎたり、他のプログラムがロックを守らなかったりすると、効果がありません。

QTOCTOUはWebアプリにも関係しますか?
A

あります。ファイルアップロードの検査後に保存する処理、クーポンや在庫の残数を確認してから減らす処理、二重実行を防ぎたい決済処理などが該当します。同じ要求が同時に2回届くと、両方が確認を通ってしまうことがあります。更新を条件付きの1回の操作にする、冪等キーで二重実行を防ぐ、といった対策が有効です。

Q自分のコードにTOCTOUがないか、どう探しますか?
A

コードの中で『確認する処理』と『使う処理』が別の行や別の呼び出しになっている箇所を探します。ファイルなら、存在確認や権限確認の後にパスで開いている箇所です。DBなら、SELECTで確認してからUPDATEしている箇所です。見つけたら、確認を外して1つの操作にまとめられないかを考え、同時実行のテストを自動テストに入れます。