セキュリティを維持する為にはゼロトラスト、何も信頼しない所から始めて信頼できることを検証する、作業が必要です。ゼロトラストは信頼できるモノと信頼できないモノに分ける作業ですが、より細かく考える必要があります。
※ より細かく考える、とはいっても「細かい事だけ」では合成の誤謬にハマります。全体と詳細、両方をバランスよく「ゼロトラスト」することが大切です。
信頼できるモノ、信頼できないモノ
信頼できるモノと信頼できないモノ、と単純に分類できれば良いのですが現実にはそうなりません。「モノ」の粒度が大きいと単純に「モノ」全体を信頼することができないからです。
セキュリティ設計を行う場合
- 物理的
- ネットワーク的
- ソフトウェア
- システム
の各レベルで信頼境界を引き、可能な限り信頼できるように設計します。しかし、普通は信頼境界の中の「モノ」全体を完全には信頼できません。
例えば、”ソフトウェア全体を信頼できるモノ”1とする場合でも必ずリスクが残ります。
- ライブラリを安全に利用するには条件がある(無条件に信頼できない。例:バッファオーバーフロー)
- ライブラリが更新/追加された場合に脆弱性が追加される。最悪の場合、悪意があるコードが含まれたモノに更新される
- ソフトウェアのコードが更新された場合に脆弱性が追加される
ネットーワークの場合なら
- 信頼できないデバイスを追加/接続される
- 信頼できない接続経路を追加される
- 信頼できるデバイスのみで構成したつもりでも、デバイスに脆弱性がある
- そもそも解った上で脆弱なデバイスやプロトコルを使用している
- デバイスのファームウェア更新などで脆弱性が追加される
といったリスクが残ります。
信頼するには検証が必要です。しかし、そもそも完全に信頼できるモノにはできない場合があります。段階的な検証が必要であったり、処理が複雑であるため確実に信頼可能か不明確であったり、変更による不確実性が残る場合があります。
ソフトウェアのデータ検証の場合なら
- アプリケーションレベルの入力データ検証(アプリケーションソフトウェアの信頼境界の検証)なら、通常はデータ形式の検証どまり。論理的な妥当性検証はロジックで行う。
→ データは検証内容の範囲内でしか信頼できない
→ 全面信頼できるとは限らない - 出力時に利用するデータが複雑な処理を経ている場合、それ以前のデータ検証が確実に必要な信頼性を担保する検証であったか保証できない。
→ コードは変わることが多く、複雑である場合が多い
→ 全面信頼できるとは限らない
→ 出力時にフェイルセーフ対策/検証を行う
参考:バリデーションには3種類のバリデーションがある 〜 セキュアなアプリケーションの構造 〜
ゼロトラストとセキュリティ設計
セキュリティ設計を行う場合、全ての「モノ」を信頼できない「モノ」としゼロトラストで1つ1つの「モノ」を”信頼可能な状態”になるよう管理できるようにします。しかし、”信頼可能な状態”とは”無条件で信頼可能な状態”にすることではありません。”無条件に信頼可能な状態”とは”完璧なセキュリティが維持されている状態”と言えます。セキュリティに完璧はありません。必ず何らかのリスクが残っている、と考えることが大切です。
”信頼可能であるとしたモノは無条件で信頼できる”、つまり”信頼できるモノにはリスクが無い”と誤った仮定をしてしまう間違いはよくあります。例えば、風力発電システムが簡単に攻撃できてしまう状態、風力発電機のどれかに侵入できるとシステム全体を容易に破壊できてしまう原因は「簡易な鍵のみで、物理的なセキュリティが維持でき信頼できる」と誤った仮定(=誤った信頼)をしてしまった事にあります。
ゼロトラストで安全、検証済みである、信頼できる、としたモノにも必ずと言って良いほど残存リスクがあります。つまり検証済み/信頼できるモノであっても、前提条件付きで信頼できるモノに過ぎません。
前提条件付きの信頼である、という点がポイントです。前提条件が維持されない場合、安全性は維持できません。風力発電システムの場合、「鍵によって物理的セキュリティは維持される」とする前提条件が簡単に突破されるため、それに頼ったセキュリティはあまり役立たないものになっていました。
個々のリスク廃除/削減策を強固な対策にすることも重要です。しかし、同時に全てのリスク廃除/削減策は突破されるリスクがあることを前提にセキュリティを考える必要があります。
ITシステムの最外周信頼境界(最も外側の信頼境界)で出来る限りのリスク廃除/削減策を行うべきですが、それだけに頼ると要求される安全性を維持できません。そこで、セキュリティ設計には必ず多層防御が必要になります。
セキュリティ対策に幾らでもリソース(人、モノ、お金)を使えるのであれば良いのですが、普通は最小限のコストで必要なレベルの安全性を維持することが求められます。どこに、どれだけのリソースをつぎ込んで「セキュリティ対策が必要な3要素」
- 物理的なモノ(物と人)
- ネットワーク
- ソフトウェア
に必要なセキュリティ(≒信頼性)を維持するのか?これがセキュリティ設計を行う設計者の腕の見せ所になります。
※ モノ/ネットワーク/ソフトウェアは別々に信頼境界を設定し、保護(=検証)する必要があります。モノ/ネットワーク/ソフトウェアを組み合わせたシステムレベルの信頼境界も設定します。しかし、信頼境界内にある物が無条件に信頼できるといったケースはほぼ無い、と考えるべきです。
セキュリティ設計と管理(マネジメント)
どんなに注意深くゼロトラストで「セキュリティ対策が必要な3要素」を全て検証し必要な安全性を確保したとしても、システムがアップグレードや交換などにより変化したり、利用しているモノに新たな脆弱性が見つかったり、危殆化2により安全でなくなったりします。そもそもリソースの関係で、最初から考えうる万全な対策になっていない場合がほとんどです。
何をやっても万全ではない(万全にはできない)ので、利用可能なリソースに応じた設計とマネジメントが重要になります。脆弱性を場当たり的、総当たり的に対応していたのでは、不要な対策にリソースを割いたり、必要な対策にリソースを割当ない、といった問題が発生します。
ゼロトラストとデータ
ITシステム、特にソフトウェア、で問題となるのはデータです。信頼境界内にも”信頼できないデータ”は多く存在します。ネットワークの脆弱性を利用して”信頼できないデータ”を送信できるようになっているシステムも多数あります。(例:暗号なしのHTTP通信では盗聴/改ざんは自由自在と考えなければならない)
プログラムの入力検証/ロジック検証により信頼できるデータであっても、出力用には安全でない場合も少くありません。現在のシステムではほとんどのデータがテキストでやり取りされます。思わぬ所に攻撃用の文字列で攻撃可能になってしまったケースは数えきれません。HTTP/HTML/XML/JSON/etc に出力する場合、検証済みの入力であっても、出力先のコンテクストに応じたセキュリティ処理(検証/エスケープなど)が欠かせません。
※ 自分のプログラムのコードさえ信用せず、ゼロトラストで出力時にも最大限の安全性を保証する。
「データを全面的に信頼できる」はかなり危険な考え方です。大多数のセキュリティ問題は「データを全面的に信頼できる」という脆弱な前提条件の元で発生しています。データを信頼できるかどうか?は多層防御で何重にもチェック/対応する必要があります。
検証により「信頼できるデータ」になっても、信頼できるのは部分的です。信頼できるのは検証した内容の範囲まで、でしかありません。検証済み = 全面的に信頼できる、ではありません。これはデータに限ったことではありません。
まとめ
セキュリティ対策はゼロトラスト(全て信頼しない)から始めて、ホワイトリスト型で信頼可能な「セキュリティ対策が必要な3要素 – 人・物/ネットワーク/ソフトウェア」を増やしていきます。しかし、”完璧に信頼可能なモノ”はほとんどありません。常に何らかのリスクが残存したり、時間と共にリスクが増加したりします。
セキュリティ対策というとリスク廃除/削減にばかり目が行きがちですが、残存/増加したリスクに対応/管理する、視点が欠かせません。ゼロトラストからセキュリティを構築したから大丈夫!ではなく、更に細かく細分化したリスク管理が必要です。
- とにかく何も信頼しない、検証したモノも信頼しない、ゼロトラストで考える
- ゼロトラストで、信頼できるモノ、信頼できないモノ、を区別する
- 信頼できるモノ、としたモノにもリスクが残存する
- 残存リスクがある為、信頼できるモノ、には信頼できる状態の前提条件がある
- 残存リスクは定期的にレビューし、必要であれば廃除/軽減策を講じる
現在のセキュリティは工学的に構築されているのではなく、職人的に(経験則で)構築されているように感じています。これが原因で、風力発電機のどれかに侵入できるとシステム全体を容易に破壊できる、といった問題があらゆる所で再現されているのではないでしょうか?
参考1:
参考2:ゼロトラストで考えないと「大穴を開ける」考え方になる例
- ソフトウェアの信頼境界は基本的に同一プロセス/スレッドを超えることはできません。 ↩
- 危殆化とは、「危険な状態になること」「危うくなること」を意味する語である。コンピュータの性能向上によって暗号化技術をはじめとするセキュリティ技術の安全性が、相対的に低下していくこと指すことが多い。 ↩