web-dev-qa-db-ja.com

MySQLデータベースのIPアドレスの暗号化

MySQLデータベースのIPアドレスを暗号化したいのですが、次の制約があります。

  • クエリを実行できる攻撃者に耐性を持つ必要はありません。
  • ディスク上のファイルにアクセスできる攻撃者に耐性がある必要があります。
  • 一致するかどうかを確認するために、暗号化されたフォームに対してIPを検証できる必要があります。
  • /24ワイルドカード(例:10.20.30.*)に対するチェックも役に立ちます。
  • システムの起動時にキーやパスワードを入力することはできません。これは、データセンターのサーバーで実行されるため、再起動のたびにSSH経由でログインする必要がないため、手間がかかりません。

私は現在、別のデータベース接続を使用して、より良い特権制限を提供しており、パスワード用の別のテーブルがあります。また、MySQLiと半自動化されたコードレビューを使用して、SQLインジェクションホールがないことを確認しています。

非ソルト(つまり、確定的)ハッシュメカニズムを使用すると、考えられるすべてのIPハッシュを簡単に計算できます。ソルトハッシュを使用すると、その問題は軽減されますが、攻撃者が1つのIPハッシュを破壊しようとするだけの場合は、それほど良くありません。もちろん、これらすべてによりワイルドカード検索もできなくなります。

これに対する解決策はありますか?


更新:
少し考えた後、私は次のスキームを思いつきました:

  • Webappには4096ビットのRSA公開鍵がソースに埋め込まれています。私は秘密鍵を自宅のマシンのTrueCryptボリュームに保持しています。
  • エントリをログテーブルに挿入すると、IPはランダムな文字列で埋められ、公開鍵で暗号化されます。これにより解読が不可能になり、暗号化が非決定的になります。
  • Webアプリケーションは、ログをエクスポートするためのAPIを提供します。これは、認証された管理者ユーザーのみがSSL経由でアクセスできます。
  • 私は、自宅のマシンのログを閲覧するためにAPIを使用するアプリケーションを作成し、秘密鍵を使用してIPアドレスを復号化します。
  • IPアドレスが禁止されると、そのIPはbansテーブルにプレーンテキストで格納されます。

コメントや提案はありますか?

12
Polynomial

公開鍵/秘密鍵の暗号化は低速です。書くことも忘れることも理想的ですが、高速なプロセスではありません。

速度を上げるために、これを考慮してください。ランダムに生成された対称鍵を使用します。これは、デーモンの起動時に選択され、場合によっては、毎時間、毎日、毎週、または毎月(トラフィックとセキュリティのニーズに応じて)ローテーションされます。そのキーをメモリにのみ残し、その対称キーをキーペアの公開キーでデータベーステーブルに暗号化します。その後、キーを回復できますが、攻撃者はプロセスのメモリをダンプする以外にキーを取得できません。それでも、攻撃者は最新のキーのみを使用できます。おそらく、キーをデータにリンクするために何かを使用する必要があるでしょう。そうしないと、各レコードに対してキーのリストを総当たりにする必要があります。その記録は、ログにタイムスタンプが付けられている場合の開始/停止時間、シーケンス番号、またはキーIDフィールドなどで暗号化されたエントリの開始など、単純なものである可能性があります。

使用する方法に関係なく、暗号化する前にIPをパディングします。あなたの回答を更新したので、これは言及されているようですが、これを参照している人にとっては間違いなく重要です。これはインデックス作成を防ぎますが、「pigeonhole」の問題を防ぎ、同じIPが常に同じ暗号化出力を持ちます。

6
Jeff Ferland

あなたのスキームは良い解決策です。よくできました!

可能なパフォーマンス最適化。より効率的にする方法が必要な場合、効率を改善する方法があります。たとえば、ここに1つあります。アプリケーションはランダムな対称キーを選択できます[〜#〜] k [〜#〜]、暗号化[〜 #〜] k [〜#〜]を公開鍵で、次にIPアドレスをで暗号化します[〜#〜] k [〜#〜]、暗号化されたIPアドレスと[〜#〜] k [〜#〜]の暗号化された値をデータベース。

後でログをエクスポートするときに、IPアドレスを禁止したい場合は、秘密鍵を持っているため、[〜#〜] k [〜#〜]の対応する値を回復できます、次に[〜#〜] k [〜#〜]を使用して復号化し、IPアドレスを回復して、クリアリストのIPアドレスを禁止リストに追加します。

これにより、どのようにパフォーマンスが向上しますか?重要なトリックは、[〜#〜] k [〜#〜]の同じ値を多くの異なるIPアドレスに再利用できることです。起動時に、[〜#〜] k [〜#〜]を選択し、公開鍵で暗号化して、[〜#〜] k [〜#〜]および[〜#〜] k [〜#の暗号化〜]。今では、それを多くのログエントリで再利用できます。必要に応じて、定期的にキャッシュをクリアし、新しい[〜#〜] k [〜#〜]を作成できます。 ([〜#〜] k [〜#〜]のキャッシュされた値を、データベースではなくメモリにのみ格納するようにしてください。)これは方法は、単一の公開鍵暗号化を時々行うだけです。新しいIPアドレスを記録するたびに、[〜#〜] k [〜#〜]、非常に効率的なはずです。

最適化が不要な理由があります。つまり、公開鍵暗号化アルゴリズムを適切に選択すれば、基本的なスキームでさえ非常に効率的である可能性があります。たとえば、公開指数e = 3を使用してRSA暗号化を使用する場合、暗号化は非常に高速であり、提案するスキームは十分高速である可能性があります。

3
D.W.

「暗号化された形式に対してIPアドレスを検証する」のは誰/何なのかわからないため、説明は完全ではありません。あなたのアップデートから、私はあなたが望むと思います:

  • 攻撃者がサーバーファイルへの完全な読み取りアクセス権を取得して、ログに記録されたIPアドレスを再構築できないような方法で、着信IPアドレスをlogできるようにする許可された管理者(あなた)がそれを行うことができます。
  • 一連の「禁止された」IPアドレス(範囲を含む場合もある)を維持するには、サーバーがIPアドレスをそのセットと照合できる必要があります。

サーバーが再起動するたびにパスフレーズを入力したり、キーを挿入したりすることは(当然のことながら)したくないので、完全なサーバーファイルに対する完全な読み取りアクセス権を取得した攻撃者は、サーバーが新たに起動した直後に知っているすべてを知っていると想定する必要があります。特に、攻撃者は自分のマシンでサーバーをシミュレートできます。このようなサーバーは特定のIPアドレスを禁止するかどうかを決定できるため、攻撃者はシミュレーションで同じ情報を簡単に取得できます(結局、IPv4アドレスは40億個しかない)。当然のことですが、禁止された(範囲の)アドレスをクリアテキストで保持するとすることもできます。

logging useの場合、非対称暗号化は適切なツールのように見えます。適切な非対称暗号化にはすでにランダムパディングが含まれています(データ自体の徹底的な検索を回避するために、実際にはIPv4アドレスは40億ほどしかありません)。ただし、RSA-4096は完全に過剰です。 IPアドレスなどの価値の低い情報には1024ビットで十分です(詳細は この回答 を参照)。さらに、RSA-1024は、暗号化された各IPアドレスが128バイトを使用することを意味します。スペースを節約するために、少し最適化することをお勧めします。

たとえば、 Elliptic Curve Diffie-Hellman を使用してハイブリッド暗号化を行うことができます。IPv4アドレスを暗号化するには、公開鍵に関してECDHを実行します(RSA鍵と同じ原則:管理者だけが保持します)秘密鍵)、そして結果の共有秘密を使用してIPv4アドレスを暗号化します。 Format Preserving Encryption を使用して、IPv4アドレスを4バイトに暗号化します(たとえば、Thorpシャッフルを使用するか、より簡単に、DHキーで初期化されたストリーム暗号を使用します)。 「128ビットセキュリティ」の場合は、256ビットの楕円曲線が必要です。ECDH公開鍵は、32バイトを超えてエンコードできます。暗号化されたIPアドレスを合わせると、アドレスあたり36バイトになります。

さらに削減するには、@ D.W。のアドバイスを適用します。サーバーの起動時にECDHを1回実行し、共有キーの使用を相互に使用します。 ECDH公開キーのテーブルがあり、ゆっくりと拡大し(リブートごとに1つの新しいエントリ)、暗号化された各IPアドレスは使用するキーを参照するだけです(32ビットフィールドで十分です)。ただし、この場合、IPアドレスの対称暗号化をランダム化するように注意する必要があります。たとえば、IPアドレス(4バイト)に12バイトのランダムを埋め込み、16バイトを1ブロックとして [〜#〜] aes [〜#〜] で暗号化します。公開鍵参照と合わせて、この低コストはIPあたり約20バイトに削減されます。ランダム化を行わない場合、攻撃者はログを通じて繰り返されるIPアドレスを推測できます。このスキームは対称鍵を再利用するため、暗号化も慎重に行う必要があります(たとえば、RC4のようなストリーム暗号は非常に悪い考えになります)。

CPUパフォーマンスについて: @ D.Wとして。指摘、これは問題ではありません。 ECDHでは、IPアドレスあたり0.1ミリ秒未満です。 RSAencryptionは、このようなコストよりもさらに低くなります。これが、CPUではなく上記のspaceパフォーマンスに集中する理由です。

2
Thomas Pornin

いい質問だ!

256 ^ 4の可能なIPv4アドレスがあります。衝突しないアルゴリズム(1つのIPが一意のハッシュを生成する)を使用する場合、これを Pigeonholeの原則 に関連付けることができます。鳩と同じ量以上の鳩の穴(ハッシュ)があります。 (IP)。通常、衝突が発生しないハッシュアルゴリズムを使用して、暗号化されたIPアドレスを格納するための256 ^ 4を超えるピジョンホールがあります。

256 ^ 4の可能なIPアドレスの低いエントロピーで1対1のハッシュを簡単に見つけることができるため、攻撃者はデータベースに対してブルートフォース検索を簡単に実行して、各IPアドレスに対応するハッシュを確認できます。 (アルゴリズムを複数回繰り返しても)。 100%の精度でデータベースに対して1つのIPを照合できる必要がない場合は、ハト穴の数を減らす方法があります。これにより、選択したアルゴリズムにハッシュの衝突が発生します。

したがって、ハッシュサイズを256 ^ 3(3バイト)にすると、各IPアドレスで256の衝突が発生する可能性があります。

制約のリストで誤った衝突の可能性について言及しなかったので、これが役立つかどうかはわかりません。

考慮すべきもう1つのアプローチは、リモート認証サーバーを使用したフルディスク暗号化の使用です。 Windowsサーバーを使用している場合、 PBConnex などのプリブートディスク暗号化を使用したソリューションが見つかると思います。現在、Linuxソリューションの名前は覚えていませんが、少なくとも1つはあることはわかっています。

1

いい質問じゃない!!!!!!!

システムを安全にしたいという要望は、機能、パフォーマンス、容量、セキュリティのバランスをとるのではなく、ここで設計を推進しているようです。

データベース内のデータの暗号化はワームの缶詰です。暗号化の方法は、データへのアクセス方法によって異なります。明示的な一致のみを検索したい場合は、データベースの外部で暗号化し、暗号化されたデータをデータベースに書き込むことができます。暗号化された述語に基づいてクエリを作成することもできます。しかし、範囲内の値(クエリ内の範囲またはデータベースレコード内の範囲のいずれか)を見つけようとすると、事態は複雑になります。

/ 24ワイルドカード(例:10.20.30。*)をチェックすることも有用です

これは、データベースで範囲を使用することを意味します。 CIDR表記でデータを記述すると、インデックスを使用してデータを見つけることができなくなります(固定ネットマスクを使用する場合を除く)。問題を解決する正しい方法は、データベースでINET_ATON(from_address)とINETATON(to_address)を使用することです。データベースのレコードごとに1つの特定のアドレスのみを格納する場合でも、これを行うにはいくつかの理由があります。ただし、レコードを効率的に検索するには、これら(1次元の値)を2次元空間にマッピングし、 geospatial indexing を使用してレコードを検索する必要があります。

それでは、暗号化要件はどこに残っていますか?

クエリを実行できる攻撃者に耐性がある必要はありません

ディスク上のファイルにアクセスできる攻撃者に耐性がある必要があります

...簡単に、データベースが置かれているファイルシステムを暗号化します。

システムの起動時に、いかなる形式のキーまたはパスワードも入力できません

それはずっと難しい

ここで受け入れられた答えは詳細が非常にまばらです-そして、PHPのshmopにキーを保持できるかもしれません-しかし、データを入力する必要がありますそこにアプリケーションサーバーが起動します。

ストレージ暗号化キーを維持する問題について ここでの潜在的な解決策 についていくつかの議論があります。

0
symcbean