この種の意思決定には多くの段階があります。「プラグインをスタックに押し込んで、暗号化を処理する」だけではありません。
まず、攻撃者にとっての魅力と、それを使用する必要がある検索/クエリ、結合列/インデックス候補であるかどうかなど、各列を分類する必要があります。一部のデータは、他のデータよりもはるかに強力な保護を必要とします。
誰から守ろうとしているかを考えてみましょう:
- カジュアルな攻撃者 (リモート テーブル コピーに使用される SQL インジェクション ホールなど)
- 盗まれたデータベースのバックアップ (ヒント: これらも暗号化してください)
- 盗まれた/漏洩したログ ファイル。クエリやパラメータが含まれている可能性があります
- スーパーユーザー以外の SQL レベルで直接アクセスできる攻撃者
- 直接スーパーユーザーの SQL レベル アクセスを持つ攻撃者
- 「postgres」OS ユーザーに直接アクセスして、構成の変更、ログのコピー/編集、悪意のある拡張機能のインストール、機能定義の変更などを行う攻撃者
- DBサーバーをroot化する攻撃者
もちろん、アプリ サーバー、プログラミング言語やツールキットの信頼できるソースのアップストリーム侵害などもあります。最終的には、「これに対して現実的に防御することはできません」と言わざるを得ないところまで来ます。「私は政府の関係者です。この顧客のサーバーにルートキットをインストールすることを許可しない限り、あなたに x/y/z を行います」と言って誰かが入ってくるのを防ぐことはできません。重要なのは、何を保護する必要があるかを決定し、それに基づいてセキュリティ上の決定を下す必要があるということです。
アプリで可能な限り多くの暗号化を行うことで、PostgreSQL が暗号化/復号化キーを認識しないようにすることをお勧めします。可逆暗号化を使用するのではなく、可能な限り一方向ハッシュを使用し、ハッシュするときはハッシュを適切にソルトします。
つまりpgcrypto
、プレーンテキストをサーバーに送信することはなく、キー マテリアルもサーバーに送信しないため、実際にはあまり効果がありません。
また、SecretValue 列のプレーンテキストが同じ 2 人の人物がSecretValueSalt, SecretValueHashedBytes
、データベース内でまったく異なる値を持つことも意味します。WHERE
したがって、それに参加したり、節で便利に使用したり、便利にインデックスを付けたりすることはできません。
そのため、セキュリティで妥協することがよくあります。データムの一部の無塩ハッシュを実行して、部分一致を取得し、すべての結果をアプリケーションにフェッチして、必要な完全な情報があるアプリケーション側でそれらをフィルタリングします。したがって、SecretValue のストレージは次のようになりSecretValueFirst10DigitsUnsaltedHash, SecretValueHashSalt, SecretValueHashBytes
ます。しかし、より良い列名で。
疑わしい場合は、データベースに機密性の高いものの平文を送信しないでください。つまりpgcrypto
、あまり役に立たないことを意味し、主にアプリケーション側の暗号化を行うことになります。その最大の理由は、プレーンテキスト (またはさらに悪いことに、キー マテリアル) を DB に送信すると、ログ ファイルpg_stat_activity
などで公開される可能性があることです。
bytea
ほとんどの場合、暗号化されたデータを列に格納したいと思うでしょう。本当に主張するなら、16 進数または base64 でエンコードしてtext
列に挿入できますが、後でシステムを使用する必要がある開発者や DBA は泣くでしょう。