私は最近Rust言語ドキュメントを読み、 this を見ました:
デフォルトでは、HashMapは暗号的に安全なハッシュ関数を使用して、サービス拒否(DoS)攻撃への耐性を提供できます。これは利用可能な最速のハッシュアルゴリズムではありませんが、パフォーマンスの低下に伴うセキュリティの向上と引き換えに価値があります。
システム言語の知識がない人として、間違ったハッシュアルゴリズムに基づくメモリ内攻撃について聞いたことがありません。だから私はいくつかの質問を得ました:
安全なハッシュアルゴリズムは、DoSやその他の攻撃をどのように防止しますか?
高速なハッシュよりも安全なハッシュを選択する必要があるのはいつですか?
時々、アプリケーションは信頼できないデータをハッシュマップのキーとして使用します。単純な実装では、信頼できないデータがサービス拒否攻撃を引き起こす可能性があります。
ハッシュマップは高速です-O(1)-最良の場合)、遅い-O(n)-最悪の場合。これはキーが通常は別々のバケットにありますが、一部の値は同じハッシュ(衝突)になる可能性があり、低速リンクリストによって処理されます。ランダムデータを使用すると、衝突は珍しくなります。ただし、一部の実装には、悪意のあるデータが多くの原因となる脆弱性があります衝突、これによりハッシュマップが遅くなります数年前、このため LinuxカーネルDoS がありました。
Linuxの脆弱性の根本的な原因は、ハッシュが予測可能であることでした。これは、リモートユーザーが知らないキーをハッシュ関数に導入することで修正されました。 Rustハッシュマップがどのように機能するかは正確にはわかりませんが、同様の種類のキー付きハッシュを使用することを期待しています。
信頼できないデータをキーとして使用している場合は常に、より安全なハッシュを選択する必要があります。
ハッシュテーブルの挿入、検索、および削除操作にはO(n)最悪の場合の動作があります。攻撃者がハッシュテーブルに挿入するキーを選択でき、ハッシュ関数自体を計算できる場合、彼らはサービス拒否の機会を作り出します彼らがする必要があるのは同じバケットにマッピングするキーを選択することだけです.
この引用は、暗号化ハッシュアルゴリズム(SHA、MD5、Blake、Skeinなど)を使用して問題を解決することを示唆しています。その解釈は完全に間違っています。 RustのHashMapが使用するアルゴリズムは SipHash と呼ばれます。ハッシュアルゴリズムです。そしてそれは暗号アルゴリズムです。しかし、それは cryptographic-hash-function ではありません。暗号化の世界におけるSipHashの正しい用語は [〜#〜] prf [〜#〜] です。
主な違いは、(暗号法では)ハッシュ関数のすべての詳細が公開されている可能性があることです。一方、PRFには秘密鍵が必要です。秘密の情報がなければ、どんな入力に対しても、出力がどうなるかを予測する方法はありません。 (その他すべての詳細は公開されています。)
SHA-2のようなものはサービス拒否を防止しません。それは敵対的でない入力に対して完全に不偏です。 (暗号化ハッシュ関数は random oracles としてモデル化できるためです。)ただし、だれでもプレーンSHA-2を評価できるため、ブルートフォースによってハッシュテーブルの衝突を見つけることができます。
暗号化ハッシュ関数が衝突耐性(少なくとも256ビットの出力)であるという事実は、ハッシュテーブルの場合の衝突の欠如を意味しません。最終的に、nバケットを持つテーブルのハッシュ関数は、n可能な値の1つに削減されます。試行錯誤により、nの試行ごとに約1回、特定のバケットにマップする入力を見つけることができます。これを不可能にするのに十分なバケットを使用するハッシュテーブルはありません。
キーなしのハッシュ関数を使用すると、ハッシュ関数がどの程度優れていても、本質的にサービス拒否に対して脆弱です。攻撃者とserver-with-a-hash-mapの両方が同じクエリを実行するという事実 Oracle は、DOSerが特別に選択された入力を使用して連携することを可能にしますあなたのCPU。
SipHashのようなPRFを正しく使用すれば、この脆弱性はありません。サーバーは2つのプールから選択されたOracle /関数を使用します128 可能な機能。 PRFベースの(ハッシュテーブル)ハッシュ関数を悪用するには、攻撃者は2つのうちどちらを推測する必要があります。128 彼が使用する必要がある関数(「キーリカバリ」)、またはキーとは無関係にPRFのバイアスを見つける(ランダムなOracleからPRFを区別する方法)。
最後に、ハッシュアルゴリズムを含むより混乱するニュアンスがあります。しかし簡単に要約すると:
これは少しあいまいで、ハッシュマップの使用方法に大きく依存します。
これが私の推測です。ユーザーから入力を受け取っているとします。たとえば、[Firstname.Lastname]
とし、それをハッシュテーブルのルックアップ値として使用します。イニシャルを取る単純なハッシュ関数を使用してハッシュテーブルを構築しているとしましょう。こうすることで、[Firstname.Lastname] --> FL
を使用すると、攻撃者がすべて同じ値にハッシュする値の負荷を簡単に送信できます。これは基本的にハッシュテーブルをリストに変え、ハッシュテーブルを使用することによるパフォーマンスの向上をすべて無効にします。遅い検索=サービス拒否。
AA -> [ ]
AB -> [ ]
...
FK -> [ ]
FL -> [First.Last, F1.F2, F1.F2, Fanotheu.Lonteuh, ...]
FM -> [ ]
...
ZZ -> [ ]
暗号化ハッシュ関数は、同じハッシュ値を持つ2つの異なる入力(衝突と呼ばれる)を構築することが非常に難しいため、これを防ぐように特別に設計されています。
高速なハッシュよりも安全なハッシュを選択する必要があるのはいつですか?
答えは簡単です。ルックアップ値がユーザーによって提供され、悪意を持って作成される可能性がある場合はいつでも暗号化ハッシュを選択してください。ルックアップ値が、悪意のない、均等に分散されていると信頼できる内部ソースからのものである場合は、より高速なハッシュを使用できます。