はじめに
今回は、セキュリティアタックへの対策のため、データベースの保存データを暗号化する方法を調査したので、ざっと紹介したいと思います。
主にクラウドインフラ上に構築する、商用WEBアプリケーションへの導入という観点でまとめています。
データ暗号化の方針
1.ストレージの暗号化
2.アプリケーション層で暗号化し、暗号化データを保存
3.データベースの機能で透過的な暗号化
1.ストレージの暗号化
概要
データベースの保存データだけでなく、ストレージやシステムそのものを暗号化する手法。
プロダクト例
・cryptsetup / LUKS(Linux Unified Key Setup)など
・Amazon S3のストレージ暗号化など
・その他
動作概要
暗号化
暗号化前のデータがアプリケーションからOSに渡される
↓
事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがストレージに書き込まれる
復号
暗号化されたストレージ上のデータがOSに読み込まれる
↓
事前に決められたキーによりデータが復号される
↓
復号されたデータがOSからアプリケーションに渡される
OS側の権限奪取への耐性
ストレージへのアクセス権と同時に、暗号化キーや暗号化パスワードが盗まれた場合、データ盗難が可能と考えられる。
稼働中のシステムの場合、常時データを参照する必要があるため、アプリケーションサーバの権限を奪取されれば、データ盗難が可能と考えられる。
データベース側の権限奪取への耐性
OS側で透過的に復号されるため、データ盗難が可能と考えられる。
SQLインジェクションへの耐性
OS側で透過的に復号されるため、データ盗難が可能と考えられる。
物理的なストレージ盗難への耐性
生の状態の暗号化キーや暗号化パスワードが含まれていなければ、データ盗難の対策になると考えられる。
寸評
「クラウドインフラ上に構築する商用サービス」という観点の場合、ストレージの暗号化に対応しているインフラ自体が少ない。
分かりやすい選択肢としては、AWS(S3のストレージ暗号化)になりそう。
2.アプリケーション層で暗号化し、暗号化データを保存
概要
アプリケーション層(Javaなどのサーバサイドプログラム)で暗号化をし、データベースに渡す手法。
復号キーは、データベースサーバとは切り離されたWebサーバに持つものと想定。
データベース側のSQL関数で暗号化することもできるが、実質的にはこの手法と同じものと考える。
動作概要
暗号化
アプリケーション上で、事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがデータベースエンジンに渡される
↓
暗号化されたデータがストレージに書き込まれる
復号
暗号化されたストレージ上のデータがデータベースエンジンに読み込まれる
↓
暗号化されたデータがアプリケーションに渡される
↓
事前に決められたキーによりデータが復号される
プロダクト例
・プログラミング言語側のencrypt関数など
・opensslライブラリなど
OS側の権限奪取への耐性
Webサーバへの直接的な侵入で考えると、暗号化キーが漏洩する可能性が高いため、データ盗難が可能な確率が高いと考えられる。
※暗号化キーの管理自体にセキュリティ対策がされていれば、データ盗難の対策となる可能性がある。(データベースのレコード毎に暗号化キーを変える。キーの生成ロジック自体を隠蔽するなど)
データベースサーバへの直接的な侵入で考えると、暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。
データベース側の権限奪取への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。
しかしながら、データベースの権限が奪取され、データベースエンジンにアクセス可能な時点で、Webサーバ側の権限が奪取されている可能性が高いはず。
SQLインジェクションへの耐性
WebアプリケーションにSQLインジェクションの脆弱性があった場合、暗号化キーが漏洩しておらず、また、復号化を経由しないアタックだった場合は、データ盗難の対策になると考えられる。
※テーブルやレコード毎に暗号化キーを変えておくと、部分的な暗号化キー漏洩のリスクヘッジになると考えられる。
物理的なストレージ盗難への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。
寸評
Webアプリケーションレベルでは、有効な対策と考えられる。(SELECT文での検索などをするためには実装上の工夫が必要だが)
暗号化キーをどのような単位で、どのように管理するかが重要になってくる。
3.データベースの機能で透過的な暗号化
概要
データベースエンジン側の機能により、透過的にデータの暗号化を行う手法。
※データベース側のログデータに生のデータが保存されてしまうことがあるので、利用する場合は、レプリケーション機構やエラー機構などのログに生データが残っていないか要注意。
動作概要
暗号化
生データがアプリケーションからデータベースエンジンに渡される
↓
事前に決められたキーによりデータが暗号化される
↓
暗号化されたデータがストレージに書き込まれる(一部のログなどは生のまま)
復号
暗号化されたストレージ上のデータがデータベースエンジンに読み込まれる
↓
事前に決められたキーによりデータが復号される
↓
生データがアプリケーションに渡される
プロダクト例
・各データベースエンジンの透過的データ暗号化機能(TDE)
OS側の権限奪取への耐性
Webサーバ、データベースサーバのどちらに侵入されても、データ盗難が可能と考えられる。
データベース側の権限奪取への耐性
データ盗難が可能と考えられる。
SQLインジェクションへの耐性
データ盗難が可能と考えられる。
物理的なストレージ盗難への耐性
暗号化キーが漏洩していなければ、データ盗難の対策になると考えられる。
寸評
SELECT文での検索が透過的に行われるため便利だが、セキュリティ対策できる余地が限られてしまう。
また、各種ログにデータが残りやすいため、その点も不安がある。
まとめ
こんな感じで、データベースに保存するデータを暗号化する方法をまとめてみました。
少し軸が替わりますが、データ漏洩対策の観点としては、データベースの暗号化以外に、
「中間のデータ(メモリ上のデータやキャッシュデータ)」
「各種ログデータ」
への注意も重要になります。
個人的には、
「3.データベースの機能で透過的な暗号化」のデータベース全体への対策をベースにしつつ、
秘匿性の高い個人情報などは、アプリケーションでの実装の工夫も含めた、「2.アプリケーション層で暗号化し、暗号化データを保存」
を組み合わせる形でいいのではないかと思いました。
このテーマについては、まだまだ検証・検討すべきことが多いと思います。
お気づきの点がありましたらアドバイス頂ければと思います。