脅威モデリングとアビュースケース設計
翻訳についての注記: 本ドキュメントは英語原文
10-security/08-threat-modeling-and-abuse-cases.mdを日本語に翻訳したものです。コードブロックおよびMermaidダイアグラムは原文のまま維持しています。
TL;DR
コードより先に存在できる唯一のセキュリティ成果物が脅威モデルであり、それは同時にチームがスキップする理由であり、見返りが大きい理由でもある。成果物は図でも、怖い可能性を並べただけのスプレッドシートでもなく、「このシステムが誤用される具体的な方法」の順序付きリストだ。各項目には名前のある担当者と、名前のある制御または文書化された受け入れ、そして制御が消えたときに落ちるテストが必要になる。文書化済み: 障害後レビューで繰り返される失敗は、その攻撃クラスが業界に知られていなかったことではない。意思決定をした本人に知られていなかっただけで、通常は誰が何に到達できるかを誰も書き残さなかったことが原因だ。
価値の大半は2つの実践が担う。1つ目は想像力ではなく構造に対して列挙すること。データフロー要素と信頼境界を命名し、そこへ1つの標準的な分類法(STRIDE、またはその環境での同等物)を横断させる。これでカバレッジは「部屋にいる人の経験値」ではなく手法の性質になる。2つ目は、受け入れた各脅威を実行可能なテストとしてのアビュースケースへ変換すること。アクター・予算・目標・経路・対象となる制御・証拠。これが「セキュリティは考えた」を、レビュアーが実行できリグレッションが黙って消せないものに変える。
脅威モデリングは露出でスコープすれば安く、野心でスコープすれば高い。1つのサービスについて新たに外部へ公開した表面だけで行う90分のセッションは、実装詳細が固まる前に実施するかぎり、本書に登場するどの下流活動よりも時間あたりで多くの悪用可能な欠陥を見つける。6週間をかけた全社モデルは、誰も行動に移せない文書を生む。推論: 息の長い見返りは個々の指摘ではなく、信頼境界・ケイパビリティ・アビュースケース・残存リスクという共通語彙だ。エンジニアとレビュアーと経営者が同じ対象について議論できるようになる。
脅威モデルの目的
ツールベンダーの宣伝文句を剥がすと、脅威モデルは4つの問いに順番に答える。
| 問い | 答える成果物 | 合意が必要な人 |
|---|---|---|
| 何を作っているのか | 信頼判断の粒度でのデータフロー図と仮定リスト | エンジニアリングリード、所有チーム |
| 何が起き得るか | 分類ラベルを付けた脅威の列挙リスト | セキュリティチャンピオン、隣接チームのレビュアー |
| どう対処するのか | 脅威ごとの処遇: 名前のある制御で緩和、移転、または期限付きで明示的に受け入れ | プロダクトオーナーとセキュリティオーナー |
| 機能したのか | パイプラインに入ったアビュースケーステストと、自動化できない制御の検証証拠 | コードを出すチーム |
この実践が退化するパターンの大半は、3つの明確化で防げる。
- 脅威モデルは設計活動であり監査ではない。レバレッジは「変更がまだ設計文書の一行の文章であるうちに設計を変える」ことから生まれる。リリース後に見つかった指摘も役に立つが、マイグレーション付きで届く。
- 脆弱性スキャンでもペネトレーションテストでもコンプライアンスチェックリストでもない。それらは「今あるもののどこが壊れているか」を問う。脅威モデルは「これがリリースされた後何が可能になるか」を問う。まだデプロイされていないので、どのスキャナにも答えられない問いだ。
- 敵対的かつ経済的な判断であり、網羅ではない。攻撃は常に存在する。出力は「どの攻撃なら誰かが手を動かすほど安く、狙われるほど価値があり、そしてそのスプリントで閉じるのが正しい使い道か」という判断である。
参照設計: システムごとに1つの成果物を保ち、対応する設計文書の隣でバージョン管理する。構成はこの順序の4セクション。スコープと仮定、信頼境界付きデータフロー図、脅威レジスタ、アビュースケース索引。レジスタの各行には安定したIDを振り、プルリクエストが「TM-14 を閉じた」と書けるようにする。レビュアーは2年後に TM-14 が何だったか調べられる。
モデルのスコープ設定
組織図ではなく露出でスコープする。有用な単位は信頼判断の表面だ。システムが「誰が尋ねているか」「何を許されるか」「この入力を信じてよいか」を決める1つの場所。具体的には「公開注文APIとその依存呼び出し」「オペレーターコンソールとそこから到達できるすべて」「パートナーのウェブフックからウェアハウスのテーブルまでの取り込み経路」が良いスコープ。「プラットフォーム」「全マイクロサービス」「そのクラウドアカウント」は悪いスコープだ。
詳細度は、まだ決まっていないもので決める。
- 概念レベル(外部システム、データクラス、誰が何を所有するか): アーキテクチャレビューの直前。答える問いは「この設計は顧客データを第三者の爆発半径の中に入れていないか」
- 設計レベル(プロセス、ストア、フロー、境界、ケイパビリティ): 既定であり本章の主役。答える問いは「どのフローが、呼び出し元のテナントを認証せずに境界を越えているか」
- 実装レベル(具体的なエンドポイント、ライブラリ、依存バージョン): リリース直前。主役は計画されなかったコード経路で、デバッグ用エンドポイント、入力をそのまま返すヘルスチェック、自動生成クライアントなど
仮定は番号付きの文として、担当者とレビュー日を付けて書く。「アイデンティティプロバイダはaudienceに紐づいた改ざん不可能なトークンを発行する」「オペレーターは顧客データの平文フィールドを読めない」「パートナー通信は署名されている」。仮定リストはセキュリティエンジニアリングで最も安い成果物だ。暗黙の信頼主張を、誰かが反論できる形に変える。暗黙の仮定がモデルの主要な壊れ方で、図は完成して見え、境界の内側の箱は静かに信頼されたままになる。
時間は厳しく区切る。設計レビュー1時間あたり20分のモデリングなら続く。数日かかる別枠の儀式は続かない。次のいずれかが変わった時点でモデルをやり直す: 外部から到達できる新しいポート、境界を越える新しいデータクラス、アクター型の追加(パートナー、エージェント、自動処理)、トラフィックの10倍変化、買収、新しい規制上の足跡。
信頼境界とデータフロー要素
4種類の要素と1本の特別な線でシステムを描く。プロセスは作業をする。データストアはリクエストをまたいで状態を持つ。データフローは境界をまたいでデータを運ぶ。外部エンティティは自分が制御できないもの。箱より線のほうが重要だ。信頼境界とは、コードが受け取ったものを信じ続けるのをやめ、信念を積み直さなければならなくなる点、または特権が変わる点である。
customer browser partner callback operator
| | |
v v v
[ TLS / CDN ]============TRUST BOUNDARY #1==============(untrusted client)
|
v
edge gateway --authn--> api service --authz+tenant--> order store
| | ^
| | |
| +====TRUST BOUNDARY #2========+
| (service to datastore: is the
v tenant predicate inside the query?)
[ logs, traces, metrics ]=====TRUST BOUNDARY #3=====
(unvalidated strings become HTML, SQL, and shell in dashboards)4つの境界ファミリーは、どの図にも明示的な線として引く価値がある。
| 境界 | よくある権限昇格 | 積み直す必要がある信念 |
|---|---|---|
| クライアントからエッジ | 未認証の呼び出し元がビジネスロジックに到達する | アイデンティティ、レート権利、ペイロードの有効性、順序保証 |
| エッジからサービス | あるテナントのリクエストが別のテナントの文脈で実行される | 認証されたプリンシパル、テナントスコープ、呼び出し単位の認可判断 |
| サービスからデータストア | アプリケーションが許可範囲の外へ読み書きする | 接続が持つケイパビリティと、エンドユーザーが主張するケイパビリティの差 |
| 人間から制御プレーン | 管理ツールを通じて読み取り経路が書き込み経路になる | サポートツールがAPIと同じ認可を強制しているか |
現代的なシステムでは5番目のファミリーがほぼ必ず現れる: チーム境界をまたぐサービス間で、呼び出し元は自分がレビューしていないピアだ。ピアサービスを「稼働率が少し高い信頼できない入力」として扱え。あるチームのアイデンティティを別のチームのワークロードがそのまま使える瞬間、混乱した代理人(confused deputy)が最初の犠牲者を待つ状態になる。
成果物を正直に保つ図面の規則は2つ。第1に、境界を越えるすべてのフローに「何を主張するか(アイデンティティ、テナント、意図、完全性)」「どう主張するか(署名、ワークロードアイデンティティを固定した相互TLS、正規形に対するHMAC、帯域外グラント)」のラベルを付ける。第2に、フロー上のデータクラスを命名できなければ、その図は未完成だ。「ユーザーデータ」はデータクラスではなく、「メールアドレスと配信同意フラグ」はデータクラスである。
アイデンティティとデータのなりすまし・改ざん
スプーフィングは「この図の要素になりすませるものはあるか」を問う。要素型ごとに答えが違うので、型別に列挙する。
- 外部エンティティ: 呼び出し元が顧客・パートナー・オペレーターを名乗れるか。壊れ方は非現実的ではない。audience を検証せずに受け入れるトークン、自社フローとパートナーフローで共有した署名鍵、リクエストボディから取るモバイルクライアントのユーザーID、オペレーターがユーザーIDを入力できるサポートツール
- プロセス: あるワークロードが別のワークロードのアイデンティティで実行できるか。共有インスタンスメタデータの資格情報、全サービスのトークンを持つサイドカー、長命なクラウドキーを持つCIランナー、ダイジェスト固定なしに取得されるイメージは、すべてなりすませるプロセスを作る
- データフロー: 転送中のメッセージを再生・並べ替え・リダイレクトできるか。再生にはノンスと有効期間が要り、リダイレクトは資格情報を宛先に紐づける(audience、チャネルバインディング、正規リクエストへの署名)ことで防げる
- データストア: なりすましより「他に誰が到達資格を持つのか」の問題。開発者がアクセスできる本番データのレプリカは、「内部サービス」という主張に対するスプーフィング表面である
改ざんは、データが保存されている場所ではなく、データの受け渡しが起きる場所で完全性が強制されているかを問う。制御はいつも同じ3つのアイデアだ。搬送経路を認証する(転送またはワークロードのアイデンティティ)、ペイロードを認証する(パーサが保存した任意のバイト列ではなく、正規形に対する署名)、事後に検知する(ハッシュチェーン、追記専用ログ、リリースの透過性記録)。
アプリケーションシステムでは改ざんの2つの型が繰り返されるが、元の設計にほぼ存在しない。
- 正規化のドリフト。署名側が
{"a":1,"b":2}をハッシュし、検証側のライブラリがキーを並べ替えたりUnicodeを正規化したりする。すると署名は効かなくなる(音を立てる)か、異なる2つのペイロードが正規化後に同じハッシュになる(静かで悪用可能)。ウェブフックの署名スキームはこの形で壊れる。「JSONボディをハッシュしている」という設計で、署名対象の正確なバイト列を特定していないものはすべて同じ穴を持つ。 - 派生状態の完全性。キャッシュ、検索インデックス、マテリアライズドビュー、フィーチャーストア、埋め込みは、中身がどこかから来たデータストアだ。導出過程をエンドツーエンドで認証していなければ、原始データへ書き込める攻撃者か古いスナップショットを再生できる攻撃者が、下流すべてを改ざんできる。個々のストアは健全に見えるまま。
否認防止: 後で必要になる証拠
否認の脅威は、無視しても何も壊れないのでエンジニアが忘れる。ユーザーが操作を否定し、オペレーターが変更を否定し、システムは何が起きたかを証明できない。監査記録は後から埋め戻せない、証拠は障害の前に設計する。
使えるセキュリティイベントは最低限、次を含む: 安定したアクター識別子(人間でもワークロードでも、表示名ではない)、操作と対象、それを許可した判断と参照したポリシーのバージョン、リクエストの出所、アクターが書き換えられない源からのタイムスタンプ、そして記録そのものの完全性。紛争になる可能性のあるものは、追記専用ストレージと周期的なハッシュチェーンが最小構成で、「アグリゲータに7日間保持のログがある」では足りない。
罠は3つ。
- 自己監査。アクター自身が監査証跡を削除・編集できるなら、その証跡はせいぜい不在の証拠になる。書き込み経路と読み取り・保持経路を分離し、保持ポリシーを変更要請の下に置く
- 否定形の欠落。拒否のほうが通常は面白いイベントだ。失敗した認可チェック50件の後の成功1件は攻撃を記述するが、成功1件だけでは平凡な火曜日に見える
- 監査ログ内の個人情報。調査者が読む必要があるので監査記録は広い読み取り権限を集める。つまり漏えい表面になる。機微なペイロードは置かず、参照とハッシュを保存する
推論: たいていのプロダクトチームでは、顧客よりもサポートと内部ツールから否認リスクが来る。「とにかく返金する」ボタンを持つ人は、お金を動かすケイパビリティを持ち、その動作が高頻度でログされないアクターだ。その表面は明示的にモデル化する。
データベースを超える情報漏えい経路
各データクラスが「どこに置かれているか」ではなく、コピーとしてどこに存在するかを問う。メールアドレス1つは通常、一次ストア、読み取りレプリカ、バックアップ、検索インデックス、キャッシュ、CDNログ、アプリケーションログ、トレース、メトリクスのラベル、エラーレポート、キューのペイロード、分析ウェアハウス、サポートチケット、そして増え続けているところでモデルのコンテキストや埋め込みストアに到達する。すべてのコピーが原本の分類を受け継ぎ、たいてい原本より弱い制御で運用される。
| コピーの場所 | レビューで見つかる漏えい経路 | 閉じる制御 |
|---|---|---|
| ログとトレース | デバッグ用にキャプチャしたリクエストボディやヘッダが第三者ベンダーへ送られる | 事後のリダクションではなく、キャプチャ時のフィールド許可リスト |
| メトリクスのラベル | 顧客識別子がラベルになり、ダッシュボード閲覧全員が検索できる | パイプラインで強制するラベルのカーディナリティと内容ポリシー |
| キャッシュ | キャッシュキーにテナント述語や vary ヘッダが無く、テナントをまたいだ読み取り | キーに認可に関わる全次元を含め、テストする |
| バックアップとスナップショット | ベンダーしか復元できない、または公開ACLのバケットへエクスポート | 顧客保持鍵による暗号化と、復元できる主体のインベントリ |
| モデルのコンテキスト | プロバイダがプロンプト内容を保持し学習に再利用する | 契約上の保持制限と、クライアント側での最小化 |
| エラー経路 | 応答に含まれるスタックトレース、内部ホスト名、SQL断片、オブジェクト識別子 | 汎用エラーエンベロープ。詳細は相関ID付きログ行だけ |
すべてのモデルで名前を付けておくべき、より目立たない2つのクラスがある。列挙オラクルは挙動の差で存在を漏らす。無効なクーポンコードに対しても答える価格エンドポイント、アカウントの有無を区別するパスワードリセットフロー、競合の在庫を明かす検索ファセット。時間とサイズのチャネルは正当な応答から漏らす。識別子が存在するかに応じてレイテンシが変わるエンドポイントは、ステータスコードが何であれ存在オラクルだ。どちらも依存関係のスキャナには現れない。「2xx を1つも取らずに呼び出し元が何が分かるか」と問うモデルにだけ現れる。
設計判断としてのサービス拒否
可用性の脅威は「ただ停止させるだけ」と軽視されがちで、これが企業が金を失う経路だ。増幅としてモデル化する。攻撃者の予算を入力し、被害者のコストを出力する。1対1を超える比のものはすべてレジスタに入る。
繰り返される増幅パターン:
- リクエストあたりの無制限な作業。1つのリクエストがN個の依存先へ広がる、無制限のリストを描画する、アーカイブを展開する、フルスキャンを引き起こす。攻撃者の労力1単位を自分の容量1単位に変換する。制御は「リクエスト単位の予算を宣言し、伝播する締切を持つ」こと
- 生成は安く、保持は高い状態。未検証のサインアップ、未払いのカート、中断されたアップロード、セッション、非同期ジョブは、攻撃者には数セント、自分たちには数ドルのコストを1件ごとに課す。状態が作られた後では、エッジのレート制限は役に立たない。修正は「未検証の状態を安く、期限付きにする」こと
- リトライとサンダリングハードの結合。依存先の障害がクライアントのリトライを増幅させ、容量が消えたまさに同じ瞬間に負荷を掛ける。リトライストームは攻撃と同じ振る舞いをするので、攻撃としてモデル化する
- キャッシュとインデックスの汚染。一意キーを強制される(攻撃者制御のクエリ文字列、顧客ごとのキャッシュエントリ)とキャッシュはメモリリークになる。パージされない無効化は1人の書き手が全リーダーを汚染することを許す
- 制御プレーンの結合。運用経路がデータ経路と同じ障害ドメインにあると、可用性イベントは「修復できない可用性イベント」になる
これらの処遇の大半は「レート制限を追加」ではなく「このエンドポイントの期待単位コストを宣言して強制する」で、キャパシティプランニングと同じ算数だ。だからこそ脅威モデルの可用性の半分は、セキュリティ専門家単独よりも容量のオーナーと同席したほうがよく読める。
権限グラフにおける権限昇格
権限昇格は脅威モデルと認可設計が出会う場所なので、バグのリストではなくグラフ到達性としてモデル化する。ノードはプリンシパルとロール。エッジは「〜として振る舞える」「〜にポリシーを付与できる」「〜のシークレットを読める」「〜を呼び出せる」。昇格経路は、外部から到達できるノードから価値あるケイパビリティへの任意の連鎖で、驚く経路はほぼ必ず間接経由だ。
- 混乱した代理人(confused deputy)。特権を持つサービスが、第三者に関する指示を埋め込んだリクエストを受け入れる。古典的な例: 顧客識別子を信頼済みの内部APIへ渡す、受け手と紐づいていない署名付きURL、リンクローカルのメタデータアドレスを喜んで取りに行く画像フェッチエンドポイント
- 参照によるケイパビリティの漏れ。URL中の長命トークンはログ・referrer ヘッダ・ブラウザ履歴に残る。推測可能なオブジェクト識別子は1件の読み取りを全件の読み取りに変える。「リンクで共有」は匿名のケイパビリティを黙って鋳造する
- 書き込み経路を通じたポリシーのドリフト。サービスアカウントへロールを付与できる人は、推移的にそのロールを持つ。アクセスを変更できるエッジを明示的にモデル化する。サポートアカウント5つがクラスタ管理者になるのはこの経路だ
- 人間とマシンの境界。クラウド資格情報を持つノートパソコンは本番の制御プレーンである。開発者が本番データやリソースへアクセスするのは、設計上で受け入れられた権限昇格だ。事実として黙らせず、レジスタに書いて受け入れの担当者を付ける
レビューで経路の大半を見つける2つの問い: 「この信頼されたコンポーネントは、呼び出し元が指定した宛先をそのまま上位の特権へ転送していないか」「誰が信頼されるかを変更でき、その変更自体はどう認可されているのか」。2つ目の答えがチケットキューで人間の判断だけが制御なら、モデルはそのとおりありのままに書くべきだ。
アビュースケースと攻撃者の予算
脅威は「何が悪いのか」を言う。アビュースケースは「特定のアクターがそれをどう達成するか」を言い、この違いが指摘を実行可能にする。機能ストーリーと同じバックログに残るよう、要求仕様の形として書く。
AC-07 Actor: authenticated customer, normal client, no insider help
Goal: obtain another tenant's invoice PDFs
Path: enumerate /invoices/{id}; ids are sequential within a workspace
Control under test: authorization check binds invoice id to caller tenant
Evidence: automated test asserting 404 (not 403) for cross-tenant reads,
plus a fuzzed-id property test in CI
Cost to attacker: ~10 minutes and a script
Value if successful: regulated data disclosure, contractual breachアクタープロファイルを添付する。「攻撃者」は一人ではないし、プロファイルによって正当化される制御が違う。
| プロファイル | 予算 | 現実的な手法 | 実際に効く制御 |
|---|---|---|---|
| 機会型スキャナ | 数十セント、自動化 | クレデンシャルスタッフィング、公開されたままのエンドポイント、公表数日以内の既知脆弱性 | パッチ周期、デフォルト資格情報の禁止、妥当な既定値、資産インベントリ |
| 自動悪用者 | 数百ドル、ボットネット | スクレイピング、アカウント農場、クーポン試験、在庫の抑え込み | アイデンティティと行動単価に紐づいたレートおよび挙動制限 |
| 標的型犯罪者 | 数千ドル、忍耐 | オペレーターへのフィッシング、窃取トークンの購入、ビジネスロジックの悪用 | フィッシングに耐える認証、資金移動でのステップアップ、異常検知 |
| 資金のある敵対者 | 時間は無限、注意は希少 | サプライチェーン、ゼロデイ、内部アクセス、通信解析 | 適用範囲の縮小、エンドツーエンドの最小権限、検知と対応の成熟度 |
| 内部者または侵害されたオペレーター | 正当な資格情報 | 一括エクスポート、ログ改竄、静かなポリシー編集 | 機微なエクスポートへの二重制御、改ざん不可能な監査、読み取り量のアラート |
意思決定は経済比較にある。攻撃者にプロキシ代400ドルを課し得られるのが5ドル分のクーポンなら、不完全な制御で構わず、そのスプリントは他に使うべきだ。計算資源20ドルでアカウント乗っ取りが大規模にできるなら、高すぎる制御は存在しない。実行コストと成功時の価値を並べて記録することが、セキュリティの専門でないレビュアーが脅威の作り話について議論せずに優先順位へ同意できるようにする。
攻撃ツリーとキルチェーンによる優先付け
攻撃ツリーは優先付けを意見ではなく算数にする。目標(「全顧客レコードを読む」)を根に置き、OR分岐(エクスポートエンドポイントを突く、オペレーターを侵害する、認可されていない場所でバックアップを復元する)とAND分岐(資格情報を得る AND 内部サービスへ到達する AND 検知を回避する)に分解する。葉ごとに悪用可能性とコストを見積り、上へ伝播させる。ORノードは子の中の最小値をとり、ANDノードは掛ける。直感が取り逃す性質が2つ出てくる。冗長な経路は個々の経路がどれだけありそうになくても目標を容易にする。そしてANDの1脚を強化してもその連言しか守れない。シングルサインオンの導入でパスワードを消したなら、第二要因のフォールバックも同時に消さなければ何も達成されないのはこのためだ。
コストではなく網羅性のために、脅威を MITRE ATT&CK のようなタクティカルな表へ写す。初期アクセス、実行、永続化、権限昇格、防御回避、資格情報アクセス、発見、水平移動、収集、持ち出し、影響。この表はリスクスコアではない。誰もモデル化しなかったフェーズを晒すチェックリストで、アプリケーションチームでは「発見」と「水平移動」が確実にそれだ。全員が正面玄関ばかりモデル化するから。
生の深刻度ラベルではなく、明示的な尤度補正で採点する。
risk = P(exploitability) x detectability x blast radius x remediation cost
P(exploitability): unauthenticated remote < authenticated < insider < already inside
detectability: 0 = invisible, 1 = alert exists and is tested
blast radius: one tenant < one region < all tenants < regulated data未認証の遠隔から到達し、検知がなく、爆発半径が全テナントという指摘はリリースを止める。同じクラスの指摘でも、認証された境界が2つあり、一括読み取りにアラートが付いていれば計画的なチケットになる。DREAD のような二段階スコアはこの差を潰す。上記の積は潰さない。
90分でモデルを回す
脅威モデリングのセッションは、分析力ではなく社交的な理由で失敗する。再現可能にするための手順は次の通り。
| 分 | 活動 | 出力 |
|---|---|---|
| 0-10 | スコープと目標、明示的な対象外を宣言する | 1行ずつ、全員が見える場所に書く |
| 10-25 | 設計文書からデータフロー図を描き、境界ラベルを全部疑う | データクラスと境界に名前が付いた図 |
| 25-45 | 無言の列挙。全員が要素に対して脅威を書き、議論しない | 独立したリスト(無言は最も声の大きい人への同調を防ぐ) |
| 45-70 | 統合と重複排除、分類法を要素横断で回して穴を埋める | 分類ラベル付きの脅威レジスタ |
| 70-85 | 全行に処遇と担当者を割り当て、上位帯だけ採点する | 担当者と日付が入ったレジスタの行 |
| 85-90 | テストになるアビュースケースに名前を付け、再モデリングを予約する | テストチケットとカレンダー上のトリガー1つ |
実務で効くファシリテーション規則:
- 図法議論を禁じる。記法は全員が集まる前に決めておく。図の論争はセッションを消費し、何も生まない
- オンコール当番の人と依存先チームのエンジニアを招待する。部外者は、自分が見えなくなった境界を見つける
- 「そんなことは起きない」は全部書く。断った人の名前とともに。これが暗黙の仮定を最も速く表面化させ、行が文書に残っていれば後で間違っていたコストは安い
- 処遇は3値に固定: 名前のある制御で緩和、書面で受け入れた相手へ移転、期限付きで個人が受け入れ。「既知の問題」は処遇ではなく、リスクが社屋から出ていく方法だ
レビュアーが誰にも質問せずに4つ答えられる時点でモデルは完成だ。システムが何を守るのか、アクターは誰か、どの制御がどこで強制されるのか、誰がどのリスクを受け入れたか。それ以下は日付の入った図にすぎない。
パープルテストでモデルを証明する
検証されない制御は劣化する。2リリース以内に「検証済みトークン」は「解析したトークン」へ黙って変わる。だからこそ検証は脅威モデルの下流の品質保証ではなく、モデルの一部だ。
証拠は主張する内容で階層化する。
- 単体テストと契約テストで解析と判断ロジックを見る。間違った audience、間違ったアルゴリズム、期限切れの not before、テナントスコープの欠落、正規化の不一致を拒否すること。安く、退屈な過半を捕まえる
- アクセス制御マトリクスのテストを実行可能な表として。(プリンシパル、操作、リソース、テナント)の各組で許可か拒否を主張する。手書きせず認可モデルから生成し、識別子をファジングして「エンドポイント単位の幸運」ではなく一律の拒否を証明する。一律性が重要で、あるエンドポイントが403を返し兄弟が200を返すのは壊れた認可ゲートの標準的な形だ
- アビュースケースの結合テストは、レジスタの実経路をデプロイ済みの環境に対して実際に試み、結果と観測側の副作用(試行が起きたときにアラートが発火するはず)の両方を主張する
- パープルチームの演習で攻撃者の思考と検知が出会う。ノートパソコンから資格情報を取り、それを使って水平移動し、一括エクスポートを試み、「誰が、どこから、何件」を1時間以内に答えられるかを確認する
- アイデンティティカオス。リクエストの途中で資格情報をローテートまたは失効させ、セッションが生きている間にロールを取り消し、アイデンティティプロバイダを殺す。書き込み経路が fail closed で、読み取り経路が妥当な失敗をするか見る。fail open の指摘はコードレビューよりここで出る
結果はレジスタへ戻す。確認済みの指摘には脅威ID、閉じた制御にはテストリンク、そしてエスケープ(原因が受け入れ済みとしてレジスタに載っていた障害)は、誰がどの仮定で受け入れたかの読み直しを引き起こす。このループが文書をプログラムに変える。
失敗トレース
トレース: どこでも効いたトークン。 あるサービスが、パートナーのIDトークンを内部呼び出しの認可に受け入れる。両フローが同じ発行者と同じ署名鍵を使うためだ。手順はこう。ベンダー侵害でパートナー資格情報が漏れ、保有者が内部エンドポイントへトークンを再生する。署名チェックは全部通る。検知: なし。リクエストは整形式で認証済みだから。モデルがあれば、境界ラベルが「検証済みJWT」ではなく「このaudienceとこのクライアントに紐づけた検証済みJWT」と読まれ、パートナー用audienceのトークンを内部APIが拒否することをCIのテスト付きで主張するアビュースケースが1件あったはずだ。
トレース: 顧客レコードを読んだログ行。 サポートエンジニアがレポートIDでログを検索する。検索ページは生のログ行をHTMLとして描画し、1行に顧客ペイロード(メールアドレスと部分トークン)が含まれていた。手順はこう。未検証の文字列が誰も引かなかったレンダリング境界を越え、同じログがダッシュボードへ流れたときに2つ目の境界も越える。信頼境界図はこのフローに明示的に名前を付ける。制御は更新を忘れたリダクション正規表現ではなく、キャプチャ時のフィールド許可リストだ。
トレース: メタデータサービスを見つけたフェッチエンドポイント。 ユーザーがURLでドキュメントを取り込む機能がある。検証はスキームだけ見て localhost を塞ぐ。手順はこう。攻撃者がリンクローカルのメタデータアドレスを渡し、インスタンスロールに紐づいた一時クラウド資格情報を受け取り、そのロールが到達できるものを列挙する。脅威レジスタはこれを「混乱した代理人: 信頼されたサービスが呼び出し元指定の宛先を上位の特権へそのまま転送する」として捕まえ、処遇は2つ。送信先のクラス単位の許可リストと、広いクラウド資格情報を発行できないワークロードアイデンティティ。どちらも設計時の判断で、思いつきで後から追加できるものは1つも無い。
トレース: 割引のオラクル。 価格エンドポイントが有効なプロモコードと無効なものでレイテンシとペイロードサイズを変える。手順はこう。自動化された呼び出し元が応答を測ってコードを列挙し、有効な集合を集め、注文のごく一部に適用する。個々の注文は正当に見えるので不正検知の閾値下に留まる。検知: なし。何も失敗しなかったから。モデルはこれをサイドチャネルによる情報漏えい経路として扱い、爆発半径はプロモーション予算で区切られる。ある会社では受け入れリスク、別の会社では緊急事項で、判断は発見される代わりに記録される。
トレース: 発見に耐えられなかった監査証跡。 オペレーターが保持ポリシーを変更し、データセットをエクスポートし、前の構成へ戻す。手順はこう。監査ストアが運用データベースと同じ権限を使うので、アクターは履歴を編集できる。エクスポート経路はアラートなしの読み取りレプリカだ。モデルの否認セクションはまさに1つだけ問う。「アクターは自分の行為の記録を変更できるか」。正直な答えはエンジニア2人週で済み、法的な証拠開示の問題より安かった。
検証戦略
実践が起きたかではなく機能しているかを追跡する。
- カバレッジ: データクラスで加重した、外部へ到達可能な表面のうち現行モデルを持つ割合。読み取り専用の公開カタログと、お金を動かす書き込み経路が同じ労力を要求してはいけない
- 受け入れたリスクへのテスト密度: 緩和済みの脅威はすべて、制御を外せば落ちるテストを指すべきだ。受け入れたリスクには検知か期限が必要で、どちらもレジスタから数えられる
- エスケープ分析: セキュリティ障害ごとに、原因がレジスタに載っていたか。載っていたなら処遇が間違っていたので受け入れた者に返す。載っていなければモデルのスコープか分類法が間違っている。この1回のレビューがモデルを良くし、セッションの回数では良くならない
- 証拠までの時間: 演習中に、誰が・どこから・何件と誰かが答えられるまでどのくらいかかるか。否認の制御が機能しているかを測る、可用性に依存しない唯一の指標だ
- 年齢分布: 合意した修正期間を超えた指摘は経営へのキュー健全性の信号だ。セキュリティの負債は、誰も正しく予測できない速さで障害の負債に変わる
弱いモデルを速く見つけるレビューの問い: 特権が変わる境界を見せてくれ。アビュースケースとそれを強制するテストを1組見せてくれ。受け入れたリスクと署名した人を1つ挙げてくれ。前回のモデルから何が変わったのか。
判断の枠組み
| 状況 | 最も安い有用なモデル | 深さ |
|---|---|---|
| 新しい公開API | リクエスト経路と依存呼び出しへの1時間セッション | 設計レベル、脅威8-15件、上位3件のアビュースケース |
| 新しいテナント境界またはパートナー連携 | 連携のオーナーと同席した境界集中のセッション | データフローレベル、テスト成果物としてのアクセスマトリクス |
| サードパーティ製コンポーネントまたは買収品 | 何が到達を許されているかのサプライチェーンと信頼仮定のパス | 仮定リストと明示的なケイパビリティ付与 |
| 規制対象データが新しいストアやパイプラインへ | コピー在庫モデル: そのデータクラスが着地する全ての場所 | 漏えい中心、コピー単位の保持とアクセス |
| モデルの無いレガシーで時間が無い | 20分の露出パス: 何が到達可能で、誰から、どんなケイパビリティで | 概念レベル、レジスタのみ、図なし |
| 障害後 | 実際に使われた攻撃経路から逆コンパイルしたモデル | 1ページと、そこに現れた分類法の穴 |
判断を変えられないモデルは却下する。その成果物がリリース前に設計もテストも受け入れも何一つ変えないなら、監査人のために書かれた文書で、担当者に直接役立つチェックリストへ置き換えるべきだ。
主要な要点
- 想像力ではなく構造をモデル化する: 信頼境界とデータフロー要素を列挙し、1つの分類法を横断させると、カバレッジは部屋の誰に依存しなくなる
- 境界の線が成果物だ。越えるすべてのフローに「何を主張し、どう主張するか」のラベルが無ければ、図は装飾品
- 脅威はアクター・予算・経路・テストを持つアビュースケースになった時点で現実になる。それまでは気分にすぎない
- 経済で優先付けする: 実行コストと成功時の価値を、検知可能性と爆発半径で補正する。深刻度ラベルだけだと両方の項が消える
- 攻撃ツリーは直感の穴を晒す。冗長な経路は全分岐を閉じない限りリスクを下げてくれないし、ANDの1脚の強化は他を守らない
- 列挙オラクルと時間チャネルは成功レスポンス無しにデータを明かす。どのスキャナも教えてくれないのでモデル化する
- 権限昇格は間接経由のグラフ到達性だ。混乱した代理人、参照によるケイパビリティ漏れ、そして「誰が信頼されるか」を変更できる者
- 処遇は名前のある制御での緩和、書面での移転、期限付きの個人受け入れのいずれかでなければならない。「既知の問題」はリスクが社屋から出ていく方法だ
- 検証はモデルの一部: 認可ポリシーから生成したマトリクス、デプロイ済み環境で走らせるアビュースケース、fail closed を証明するアイデンティティカオス
- 露出でスコープし90分に区切る。判断を変えられないモデルは維持ではなく削除する
参考文献
- Shostack, A. "Threat Modeling: Designing for Security." Wiley, 2011 — 4つの問いのループ、要素単位の列挙(STRIDEの適用法の源)、価値ある資産の周囲のマイクロハーデニング
- Swiderski, F., and Snyder, W. "Threat Modeling." Microsoft Press, 2004 — 開発スケジュールへのモデリング組み込みを、チームが維持できる成果物として実践する方法
- Schneier, B. "Attack Trees: A Method for Constructing Security Models." Dr. Dobb's Journal, 1999 — AND/OR分解と目標から葉へのコスト伝播
- Howard, J., and LeBlanc, D. "Writing Secure Code," 2nd ed. Microsoft Press, 2003 — 信頼の主張が依存する8つの性質の分類としてのSTRIDE
- Anderson, R. "Security Engineering: A Guide to Building Dependable Distributed Systems," 3rd ed. Wiley, 2020 — 攻撃者の経済学、制御が攻撃より安くなければならない理由、境界設計の人間要因
- Chua, T.-L. "A Philosophy of Software Security." 2023 — セキュリティ活動をベストプラクティスの収集ではなく、具体的な悪い結果の防止として組織する理由
- MITRE ATT&CK knowledge base — フェーズの網羅性のために使う戦術表。スコアリングには使わない
- OWASP Application Security Verification Standard (ASVS) 5.0 と OWASP Web Security Testing Guide — アビュースケースの受け入れ基準へ写しやすい要求カタログ
- NIST SP 800-161r1, "Cybersecurity Supply Chain Risk Management Practices for Systems and Organizations." 2022 — サプライヤーとコンポーネントの信頼仮定を第一級のモデル項目として扱う
- NIST SP 800-189, "Resilient Computer System Design." 2020 — 敵対的障害と偶発的障害を1つの設計問題として扱う枠組み
- Katz, D., Reddy, S., Barkovich, B., Chojnacki, D., Lu, L., Srivatsan, D., et al. "BBox: Applying Security Chaos Engineering to Serverless Execution Context Creation." ACM CCS 2020 — 分離の主張を議論ではなく実行可能なテストで検証する