Googleは暗号を積極的に使っていることが知られています。暗号を積極的に使う理由を紹介します。
「信頼境界線の中で暗号を使っても、内部に侵入を許した時点で終わり」なので、「暗号を使っても意味がない」と考えているかも知れません。「リスクの廃除」だけが、セキュリティ対策ではありません。「リスクの緩和」もセキュリティ対策です。暗号は侵入を許してしまった場合のリスク緩和に効果的です。
境界防御の限界
境界防御はセキュリティ対策で最も重要な要素の1つです。境界防御が有効に機能していれば、安全性は維持できます。しかし、境界防御に失敗した場合にデータの安全性が全く維持できない、というケースがあります。
などです。
そもそも、データは「最小権限の原則」に則り、必要最小限の権限で利用するのが理想的です。例えば、
- WebユーザーがSQLデータベースにアクセスする場合、データベース固有のユーザーとしてアクセスし、データのアクセス権限を最小にする
ことが理想的です。
しかし、現実的にはWebアプリがDBサーバーにアクセスする場合、全てのユーザーのデータに完全にアクセスできる、スーパーユーザーのようなアカウントだけ1で、データベースにアクセスするアプリケーションがほとんどです。
クリティカルなユーザーデータだけでも、暗号化していれば盗まれる/改竄されるリスクを低減できます。
暗号化のメリット
暗号化のメリットは、境界防御が失敗した場合の安全性維持、が可能なことにあります。先程の例もですが、TLSプロトコルの有り/無しの違いを見れば、暗号化のメリットは明らかです。
内部ネットワークの場合、暗号化していない通信であっても、基本的には安全であるべきです。内部ネットワークは境界防御により守られているはずです。このため、Webサーバーとデータベースの通信は暗号化されていないことも多いです。
しかし、万が一Webサーバーとデータベースサーバーの通信の途中にあるルーターに侵入された場合2、つまり境界防御が破られた場合、攻撃者は通信の内容を簡単に盗めます。
TLSはそもそも通信経路と信用できないインターネットでは必須のセキュリティ機能ですが、信頼できる内部ネットワークの場合、「転んだ時の杖」の役割があります。
信頼境界線内での暗号化の目的は
- 境界防御に失敗した場合の、多層防御として機能
する点にあります。
暗号化を有効に機能させるための必要条件
信頼境界線内での暗号化の目的は
- 境界防御に失敗した場合の多層防御
です。多層防御として機能させるには、
- キャッシュカードと暗証番号を一緒に保管する
ようなことしてはいけません。
- Webサーバーの設定ファイルに暗号鍵が記載されている状態
- データベース内データの暗号化鍵がデータベース内にある状態
これらは「キャッシュカードと暗号番号を一緒に保管している」状態です。暗号化のメリットを活かすには、鍵を安全に管理することが重要です。
境界防御に失敗していることが前提なので「信頼境界線の中だから安全」は通用しません。既に破られた境界とは別の信頼境界を引き、防御する必要があります。
参考:
まとめ
「え、ここでまとめ?」と思ったかも知れません。
「安全な鍵管理」は本当に大変なことなのです。”鶏と卵問題”のような問題です。ブログにさらっと書いてしまえるような内容ではないです。
鍵管理については、簡単なまとめなら
https://www.owasp.org/index.php/Key_Management_Cheat_Sheet
より本格的な物なら
https://www.ipa.go.jp/security/fy22/reports/tech1-tg/b_04.html
などを参考にしてください。
境界防御についてはこのエントリを参考にしてください。
鍵情報を環境変数として渡している場合、これで完璧という方法ではないですが、
- 鍵を環境変数として渡し、鍵をメモリに保存した後、鍵を保存した環境変数を消去
すれば、多少リスクを減らせます。
データベース内のデータを暗号化する場合、(最小権限の原則に則り、ユーザー毎に別々の暗号鍵を使うことを想定)
- 暗号化鍵は別の鍵管理用のデータベースに保存する
- データベース内には暗号化鍵のSaltとなる情報のみを保存し、暗号化鍵はHMACなどで導出する
これらでリスクを減らせます。厳重にセキュリティ対策を施した専用の鍵管理サーバーを置けない場合、後者を選択することになります。以下のような形で鍵を導出します。
$encryption_key = hash_hmac($MASTER_KEY, $user_salt);
のようにします。当然ですが、$MASTER_KEYはデータベースとは別の安全な場所に保存します。