前置き
マイクロサービスやシステムオブシステムズのような、分散アーキテクチャにおいて、
脅威モデリングを事前に机上で行わないのは、正直あり得ないといっても過言ではない。
それを行わないことで、後工程になってから脆弱さが露呈し、大幅な手戻りになりかねません。
そこで、以下では、脅威モデリングを分散アーキテクチャにおいて適用した場合の各ステップをフレームワーク化したプロセスとして提示していきます。
このプロセスは、マイクロサービスアーキテクチャのセキュリティを、
設計の初期段階から体系的に組み込む
ための、非常に効果的なアプローチです。
DFDと脅威モデリングを用いて、セキュリティ要件を導き出すプロセスは、以下の4つのステップで構成されます。
ステップ1:DFDによるアーキテクチャの可視化
目的
まず、これから設計する、あるいはすでに存在するマイクロサービス群のアーキテクチャを、関係者全員が共通認識を持てる形で可視化します。
詳細なアクションは、以下の通りです。
①. コンテキスト図(レベル0 DFD)の作成
まずシステム全体を一つのプロセスと見なし、どのような外部エンティティ(例:ユーザー、決済ゲートウェイ)と、どのようなデータをやり取りするのか、最も抽象度の高いレベルで定義します。
②. レベル1 DFDへの分解
コンテキスト図の内部を、主要なマイクロサービス(プロセス)、サービスが所有するデータストア(コマンドモデル)、そしてそれらの間のデータフローに分解していきます。
③. 信頼境界の明示
これが脅威モデリングにおいて最も重要な作業です。
DFD上に、信頼レベルが異なる領域の境界線を明確に引きます。例えば、
・インターネットとDMZの境界
外部からの攻撃を最初に受ける場所。
これは、信頼できないインターネット(外部)と、自社がある程度管理できる最初の防御線(DMZ: DeMilitarized Zone)との境界です。(図の緑線枠)
ここを横切る通信は、最も警戒レベルの高いものとして扱われます。
・内部ネットワークと決済ネットワークの境界
PCI-DSS準拠など、特に厳格なセキュリティが求められる領域。
たとえ自社の内部ネットワークであっても、全ての領域が同じ信頼レベルではありません。
特に、クレジットカード情報などを扱う決済ネットワークは、PCI-DSSのような厳格なコンプライアンス要件を満たすために、他の社内システムから厳格に隔離される必要があります。
この境界を越える通信は、厳しく制御・監査されます。
・ユーザーデータを持つサービスと、持たないサービスの境界
個人情報(PII)を扱うサービスは、プライバシー保護の観点から、より高いセキュリティレベルとアクセス制御が求められます。
したがって、
PIIを扱うサービス群と、そうでないサービス群との間に明確な信頼境界を設け、
「知る必要のないサービス」が個人情報にアクセスできないように設計する
ことは、セキュリティの基本原則です。
ステップ2:STRIDE/LINDDUNによる脅威の洗い出し
目的
可視化したDFDの各要素に対して、どのような脅威が存在しうるかを、網羅的かつ体系的に洗い出します。
詳細なアクション
DFD上の全ての要素(プロセス、データストア、データフロー)と、信頼境界を横切るフローに対して、STRIDE(またはプライバシーに焦点を当てるならLINDDUN)の各カテゴリを適用し、具体的な脅威シナリオをブレインストーミングします。
S (なりすまし)
・「注文サービスは、本当に決済サービスからの通知だと検証できるか?」
・「偽造されたJWTトークンで、サービスになりすましてアクセスできないか?」
・「サービスメッシュが導入されていない場合、内部の別サービスになりすましてAPIを呼び出せないか?」
T (改ざん)
・「ユーザーサービスと注文サービスの間を流れる顧客データは、途中で改ざんされないか?」
・「APIリクエストのパラメータ(例:商品の価格、送金先口座)を不正に書き換えられないか?」
・「サービス間の暗号化されていない通信(データフロー)を、中間者攻撃で改ざんできないか?」
R (否認)
・「決済サービスは、後から『そんな決済依頼は受け取っていない』と主張できないか?」
・「監査ログが無効化されたり、削除されたりする可能性はないか?」
・「共有アカウントが使われており、特定の個人の操作を後から証明できない状態になっていないか?」
I (情報漏洩)
・「顧客データベースに保存されている個人情報が、権限のないサービスから読み取られる可能性はないか?」
・「エラーメッセージのスタックトレースに、内部のシステム情報や機密データが含まれていないか?」
・「サービス間の通信(データフロー)で、暗号化されずに個人情報が流れていないか?」
D (サービス妨害)
・「在庫サービスに大量のリクエストを送りつけ、システム全体を停止させることは可能か?」
・「特定のサービスに大量のリクエストを送りつけ、リソースを枯渇させられないか?」
・「サーキットブレーカーがない状態で、依存先サービスの障害が呼び出し元に連鎖し、
システム全体が停止しないか?」
E (権限昇格)
・「一般ユーザーが、何らかの方法で管理者権限を持つ運用サービスを呼び出せてしまわないか?」
・「サービスに割り当てられたIAMロールが過剰で、必要以上の権限を持っていないか?」
LINDDUN(プライバシー)
・「個人を特定できないはずの分析データが、他のデータと結合(Linkability) することで、個人を再特定できてしまわないか?」
ステップ3:リスク評価と優先順位付け
目的
洗い出した全ての脅威に一度に対処するのは非現実的です。
ビジネスインパクトと発生可能性を元に、対処すべき脅威の優先順位を決定します。
アクション
特定した各脅威シナリオに対して、CVSSやDREADのようなフレームワーク、
あるいは単純な「影響度(ビジネスへの損害)」と「発生可能性(攻撃の容易さ)」のマトリクスで評価し、リスクレベルを算出します。
ステップ4:セキュリティ要件の定義(対策の決定)
目的
優先度の高いリスクを軽減するための、具体的で実行可能なセキュリティ要件を、アーキテクチャの設計に落とし込みます。
詳細なアクション
脅威シナリオとリスク評価に基づき、個々のマイクロサービスが満たすべきミクロな要件と、プラットフォーム全体で満たすべきマクロな要件を定義します。
個々のマイクロサービスへの要件
入力バリデーション
「ユーザーサービスは、入力された全ての外部入力(APIリクエスト、メッセージ)に
対して、厳格な型、長さ、フォーマット、範囲の検証を実装しなければならない」
(改ざん対策)
「注文サービスは、受け取ったJWTトークンの署名と有効期限を必ず検証しなければならない」(なりすまし対策)
認可制御
全てのAPIエンドポイントで、リクエスト元の権限(ロール、スコープ)を検証し、操作が許可されているかをチェックする。(権限昇格対策)
エラーハンドリング
機密情報を含まない、汎用的なエラーメッセージを返すようにする。(情報漏洩対策)
全体としての要件
サービス間認証・暗号化
サービスメッシュを導入し、全てのサービス間通信をmTLSで暗号化・認証しなければならない。(なりすまし、改ざん、情報漏洩対策)
中央集権的な監査ログ
全てのサービスは、自身が発行したイベントの否認防止のため、監査証跡を改ざん不可能な状態で、中央ログ基盤に集約・永続化しなければならない。(否認対策)
APIゲートウェイ
レートリミット、認証トークンの一括検証、WAF機能などを提供する。
(サービス妨害、なりすまし対策)
まとめ
このプロセスを経ることで、
セキュリティ要件は「なんとなく必要だから」という曖昧なものではなく、
「特定の脅威から、特定のビジネス価値を守るため」
という、明確な根拠を持ったものになります。
是非ともイベントストーミングなどのモデリング手法と組み合わせて、
マイクロサービス群全体の系への脅威分析にも応用してみてください。