サイバー攻撃手法・脆弱性分析 重要度:★★出題: AM2・PM1
競合状態 (Race Condition / TOCTOU) と トランザクション排他制御
きょうごうじょうたい / とぅくとぅー / Race Condition / Time-of-Check to Time-of-Use (TOCTOU)
「条件のチェック(Time-of-Check)」から「実際の使用・更新(Time-of-Use)」までの微小な時間差に複数リクエストを同時並列送信し、残高不足のまま二重出金やクーポン重複取得を行う攻撃。
3行速習ポイント
- TOCTOU(Time-of-Check to Time-of-Use):「①残高や利用済みフラグをSELECTで確認する処理」と「②残高を減算・フラグを更新するUPDATE処理」の間に別スレッドが割り込むことで整合性が破綻
- Webアプリではポイント交換・EC在庫引当・クーポン適用APIに対して複数リクエストをミリ秒単位で同時送信(Single-Packet Attack等)して不正利益を得る手口が多発
- 対策はDBのトランザクション分離レベルの設定と「SELECT ... FOR UPDATE(悲観的排他ロック)」または「UPDATE文のWHERE条件に残高・未利用条件を含めてアトミック(不可分)に更新し更新件数を確認する(楽観的ロック)」
図解
図TOCTOU(競合状態)の発生メカニズムと DB トランザクション排他制御
脆弱な実装:非排他の確認(Check)➔ 更新(Use)TOCTOU 脆弱性
SELECT確認とUPDATE更新の隙間に並列リクエストが割り込む
スレッドAとBがほぼ同時に「残高1,000円以上か?」「クーポン未利用か?」をSELECTした際、双方とも条件クリアと判定され二重出金・重複利用が成立
安全な実装:SELECT FOR UPDATE または 条件付きアトミックUPDATE排他制御・アトミック化
悲観的排他行ロック、または1文での不可分更新と影響行数確認
トランザクション内で SELECT ... FOR UPDATE により対象行をロックするか、UPDATE ... WHERE used = 0 のように条件判定と更新を1つのSQL文で不可分に実行
💡 午後問題の決済・ポイント・クーポン処理で「チェック(SELECT)と更新(UPDATE)が別クエリでロックされておらず、同時リクエストで二重適用される欠陥」として頻出
概要と本質
単一のリクエストで順番にテストしている段階では絶対にバグが出ないにもかかわらず、本番環境で並列リクエストを送られた瞬間に突破される論理脆弱性(ビジネスロジックの欠陥)の代表例です。午後試験のソースコード・設計診断でも狙われます。
重要ポイント・コア概念
- ファイルシステム上のTOCTOU:特権プログラムが「ファイルのアクセス権を確認(access関数)」してから「ファイルを開く(open関数)」までの間に、攻撃者がそのファイルを重要ファイルへのシンボリックリンクに差し替える攻撃
- DB排他制御(悲観的ロック):トランザクションを開始し、SELECT ... FOR UPDATE で対象行をロックしてからチェックと更新を行い、COMMITするまで他トランザクションを待機させる
- アトミックな条件付きUPDATE:UPDATE coupons SET used = 1 WHERE coupon_id = ? AND used = 0 のように1つのSQL文で検証と更新を不可分に実行し、影響行数(Affected Rows)が1件であることを確認する
午後記述・情報セキュリティ対策での攻略ポイント
午後試験のWebアプリ・決済システム問題で「なぜ1回しか使えないはずのクーポンが複数回適用できたのか(チェックと更新が別クエリで排他制御されておらず、同時リクエストで両方とも未利用と判定されたため)」「修正方法(SELECT FOR UPDATEによる行ロック)」が問われます。
午後記述で使える加点キーワード(クリックでコピー)
関連する重要用語
この用語が出題された過去問を解く(1分演習)
即時アウトプットで定着情報処理安全確保支援士 過去問演習で実践力を鍛える