こんにちは、Product Securityチームの@gloriaです。前回は、昨年のAdvent Calendarイベントでセキュリティテストについて記事を書きました。
今回は、メルカリSecurity TeamのSecurity Tech Blogシリーズの一本目として脅威モデリングについて紹介したいと思います。脅威モデリングの基礎、なぜ脅威モデリングがセキュア開発ライフサイクル(SDLC)に必要なのか、メルカリの脅威モデリングプロセスについて説明したいと思います。
脅威モデリングとは?
脅威モデリングは、システムを分析してセキュリティの脆弱性を洗い出す活動です。つまり、システムやアプリケーションの設計を深く分析し、実装前に先手を打って、起こり得る脆弱性を見つけることです。攻撃者をシステムに一歩も踏ませないので、プロアクティブ・セキュリティの一つの手段だと言われます。
プロアクティブ・セキュリティというのは、単純にインシデントが起こった後に対応することではなく、最初からインシデントを起こさないように積極的に予防することです。プロアクティブ・セキュリティで本来防げるはずのインシデントの対応に掛かるコストを減少できるので、リアクティブ・セキュリティより効果的ではないでしょうか。2021年にIBM社の行った調査によると、一般のサイバーセキュリティインシデントは5.46億米ドルほど掛かってしまうので、積極的にインシデントを防ぐ方が望ましいです。
脆弱性を防ぐ上に、脅威モデリングで既にシステムに隠れた脆弱性も洗い出せます。洗い出した懸念を分析し、対応する方法や必要な場合に直すプライオリティなどを決めて、全体的なセキュリティリスクを管理することができます。
なぜ脅威モデリングをすべきか?
脅威モデリングは、システムとアプリケーションにメリットがあるだけではなく、脅威モデリングを行うチーム自体も改善します。
脅威モデリングされたシステムとアプリケーションは、脅威モデリングされていない場合に比べると、サイバー攻撃への耐性が高い傾向があります。なぜかというと、設計にセキュリティの不充分な所を洗い出して、システムの複雑さを減少することで、攻撃対象領域を削減できるからです。その上で、単一障害点を明確にでき、追加的なセキュリティ対策が必要な部分も把握できます。
脅威モデリングは非常にコラボレーション性の高いチーム活動なので、システム設計やフィーチャーについて深く議論する場にもなります。議論し合うことで、隠れた技術的負債や未知の機能が出てくる場合があります。その他、脅威モデリングをする際、自分の作った機能を攻撃者の視点から考え直すので、参加するエンジニア全員にセキュリティのマインドセットが育つという非常に大きいメリットもあります。
まとめると、脅威モデリングはサイバー攻撃に耐性のあるプロダクトに導いて、アプリケーションとシステムの中にセキュリティ不充分な所を洗い出し、開発チームのセキュリティ教育にもなるので、セキュア開発ライフサイクルの不可欠な要素だと言っても良いでしょうか。
私たちの脅威モデリングプロセス
メルカリでは、一年以上前に脅威モデリングを開発プロセスに導入し始めました。私たちのプロセスには5つのステップがあります。
ステップ1:モデルの作成
脅威モデリングを始める前に、システムを理解する必要があります。そのために、まずは以下のコンポーネントを特定します:
- アセット:システムにある各コンポーネント(マイクロサービス、アプリケーション、クリティカル・コンポーネント、データベースなど)
- データフロー:システム内データの流れ
- 信頼境界:信頼性に変化がある所
- エントリーポイント:システムの外から入ってくる入力(ユーザーインプット、他のインターナルシステムからのインプットなど)
- 特権フロー:admin user flowなど
このような情報を様々な所から集めます。APIエンドポイントのドキュメンテーション(サンプルリクエスト・レスポンス)、設計ドキュメント、フィーチャースペックなどを参考にします。
メルカリでよく使用する2種類のモデル図も参考に使います。
- データフロー図:システムの各コンポーネント、データの流れや信頼境界を視覚化する図
- シーケンス図:システム使用時のアクション順序を表す図
データフロー図(左)とシーケンス図(右)のサンプル。(Information Security University of Florida と Stackoverflowより)
システムについて情報をまとめたら、以下のようなモデルを作成します。
サンプルの脅威モデリング図
ステップ2:ブレーンストーミング
モデルの作成後、攻撃者の視点からあらゆる問題をブレーンストーミングします!このステップはある程度セキュリティの専門知識が必要なので、開発チームのメンバーにとって最も難しいステップかもしれません。難易度を下げるために、私たちは2つのフレームワークを利用しています。
1つ目はマイクロソフトのSTRIDEフレームワークです。脅威モデリングの人気なフレームワークの1つで、シンプルかつ使いやすいという理由で選びました。あり得る攻撃が6つのカテゴリーに分けられます:
- Spoofing (スプーフィング):攻撃者は他のユーザーのなりすましをして、不正アクセスができるか?
- Tampering (改ざん):攻撃者は不正にデータの変更ができるか?
- Repudiation (否認):攻撃者が行った行動を否認できるか?
- Information disclosure (情報漏えい):攻撃者が機密データなどにアクセスできるか?
- Denial of service (サービス拒否):攻撃者がアプリケーションをクラッシュや停止させられるか?
- Escalation of privilege (特権の昇格):攻撃者が特権を手に入れることができるか?
2つ目のフレームワークは「5W1H」です。正式の脅威モデリングフレームワークではありませんが、エンジニアを違う視点から普段聞かない質問を考えさせる効果があるので非常に役に立つフレームワークだと思います。システムについて6種類の質問をします:
- WHO: 誰がデータを送信するか?誰がアクセスできるか?(外部や第三者の関わりと信頼性を問う)
- WHAT: 何のデータを送信・保存するか?(機密情報があるかどうかを問う)
- WHERE: どこに保存するか?どこで使うか?(保存・使用する所のセキュリティを問う)
- WHEN: いつデータを送信・保存するか?いつ使うか?(認証・認可が必要なのかを問う)
- WHY: なぜデータを送信・保存するか?(必要以上のデータを送信・保存していないかを問う)
- HOW: どのようにデータを送信・保存するか?(暗号化の使用などの確認)
以下の画像のようにホワイトボードを使ってブレーンストーミングすることはよくあるパターンです。しかし、コロナが始まってからメルカリは原則リモートワークなので私たちはGoogle Jamboardを使っています。
ホワイトボード式のブレーンストーミング。(MartinFowler.comより)
私たちのGoogle Jamboardはこんな感じです!
ステップ3:課題をリストアップする
あり得る課題をブレーンストーミングしたらグループで議論して、対策されてなく懸念になる課題をリストアップします。この段階で、コードを調べたり、シニア・エンジニアに質問して確かな課題なのかを確認します。
ステップ4:リスク分析を行う
確かな課題を見分けたら、各課題を直すプライオリティと、対策を決めるためにリスク分析を行います。リスク分析に使うフレームワークは様々ありますが、私たちはマイクロソフトのDREADフレームワークがわかりやすいと思って選びました。
- Damage(潜在的な損害): 攻撃からの損害はどれほどあるか
- Reproducibility(再現可能性): 攻撃の再現の難易度
- Exploitability(攻撃利用可能性): 攻撃の手段の難易度
- Affected Users(影響を受けるユーザー): どれほどユーザーが影響されるか
- Discoverability(発見可能性): 脆弱性を発見する難易度
グループディスカッションで各カテゴリーを議論してランクを付けます:High(3)、 Medium(2)、 Low(1)。ランクと以下の公式を使い、課題ごとにリスクスコアを計算します。
Risk Score = Probability(攻撃が起こる確率)x Impact(ビジネスへの影響)
- Probability = Reproducibility + Exploitability + Discoverability
- Impact = Damage + Affected Users
最後に、計算したリスクスコアでプライオリティを特定します:Low(リスクスコア0−20)、Medium(21−40)、High(41−60)。プライオリティがわかったら課題の対策方法などを決めることができます。
具体的な例として、利用手段の難易度が低くて、一人のユーザーしか影響しないような攻撃(フィッシングとか)のリスク分析は、以下のようになります:
- Damage: 2 / Medium(一回の攻撃で一人のユーザーしか影響しないので損害はある程度限られています)
- Reproducibility: 3 / Easy(攻撃の手段が分かると簡単に再現できます)
- Exploitability: 3 / Easy(攻撃の手段自体は簡単です)
- Affected Users: 1 / Low(一人のユーザーしか影響されません)
- Discoverability: 3 / Easy(脆弱性が見つかりやすい)
リスクスコアの計算:
- Probability = 3 + 3 + 3 = 9
- Impact = 2 + 1 = 3
- Risk Score = 12 (Low)
ステップ5:課題への対応
洗い出した課題を必ずしも全部直すというわけではありません。課題への対応は4つあります。
- リスク軽減:課題を直したり、システムやフィーチャーの設計を変えたりしてリスクを減少・除去する
- リスク移転:保険に入ったりしてリスクを第三者に移転する
- リスク回避:リスクを完全に回避するために影響あるコンポーネントを使わないようにする
- リスク受容:上の方法は全て損害よりコストの方が高い場合に、対応しないでリスクを受容することは一番合理的になる
課題にアサインされたプライオリティと対応する際に必要な時間や労力、アセットの価値などにより、4つの方法から対策を選びます。
そして、繰り返す!
脅威モデリングは決して一回のみ行う活動ではありません。新しいフィーチャーが出来上がるごとにプロダクトが徐々に進化していくので、新しく出てくるセキュリティの懸念や攻撃の可能性が現れることは事実です。脅威モデリングは定期的かつ継続的に、SDLCの設計フェーズで行うべきです。
最後に
脅威モデリングでは、インシデントが起こった後に対応することではなく、積極的に予防する仕組みを取り上げています。プロダクトの安全性を上げる他に、システムやアプリケーションを深く議論する場を提供する効果もあります。時には、以前知らなかった技術的な負債が出てくることもあります。最後に、私たちのプロダクトを作ったり、コードを書いたり、システムを維持したりしているエンジニアへセキュリティのマインドセットを与えるのが非常に大きなメリットだと思います。脅威モデリングをマスターするまで時間が掛かるかもしれませんが、コストよりメリットの方が圧倒的に多いので、セキュア開発ライフサイクルの不可欠な要素とは言えるでしょうか。
Product Securityチームはこの分野が得意なエンジニアを募集しています!一緒に働きたい方、是非採用情報ページをご参照ください。