検索
ホームページバックエンド開発PHPチュートリアルPHP カーネルの探索: ハッシュ テーブル衝突攻撃の原理、kernel_PHP チュートリアル

PHP カーネルの探索: ハッシュ テーブル衝突攻撃の原理、カーネル

以下では、PHP カーネルの探索: ハッシュ テーブル衝突攻撃の原理を写真とテキストで説明します。

最近DOS攻撃としてのHashtable衝突の話題が絶えず取り上げられており、様々な言語が影響を受けています。この記事では、PHP カーネルのソース コードを組み合わせて、この攻撃の原理と実装について説明します。

ハッシュテーブル衝突攻撃の基本原理

ハッシュテーブルは非常に検索効率の高いデータ構造であり、多くの言語が内部的にハッシュテーブルを実装しています。 PHP のハッシュ テーブルは非常に重要なデータ構造です。配列データ型を表すために使用されるだけでなく、Zend 仮想マシン内にコンテキスト情報を保存するためにも使用されます (実行コンテキストの変数と関数はすべて、ハッシュテーブル構造)。

理想的には、ハッシュ テーブルの挿入と検索操作の時間計算量は O(1) です。どのデータ項目も、ハッシュ テーブルの長さに関係なく、時間内にハッシュ値 (キー) を計算し、バケット (用語) を見つけることができます。バケットは、一定時間内のハッシュ テーブル内の位置を指します。もちろん、これは理想的な状況です。ハッシュ テーブルの長さには制限があるため、異なるデータ項目が同じハッシュ値を持つ状況が存在する必要があります。このとき、異なるデータ項目が同じバケットに割り当てられます。衝突(衝突)といいます。ハッシュ テーブルの実装では、衝突の問題を解決する必要があります。衝突を解決するには、一般に 2 つのアイデアがあります。1 つは、データが衝突した場合に、線形検出などの特定の原則に従って衝突したデータを他のバケットに割り当てることです。次に、このバケットの後のバケットを順番に検索し、最初の未使用のバケットに入れます。2 番目の戦略は、各バケットが 1 つのデータ項目のみを保持できる場所ではなく、複数のデータを保持できる場所であるということです。構造 (リンク リストや赤黒ツリーなど) を使用すると、すべての衝突データは何らかのデータ構造の形式で編成されます。

どの衝突解決戦略が使用されるかに関係なく、挿入および検索操作の時間計算量はもはや O(1) ではありません。例として検索を考えます。キーでバケットを検索して終了することはできません。元のキー (つまり、ハッシュ前のキー) が等しいかどうかも比較する必要があります。そうでない場合は、挿入と同じアルゴリズムを使用する必要があります。一致する値または確認データがハッシュ テーブルに存在しないまで検索します。

PHP は衝突データを保存するために単一リンク リストを使用するため、実際には、PHP ハッシュ テーブルの平均検索複雑さは O(L) です。ここで、L はバケット リンク リストの平均長で、最悪の複雑さは O(N; )、この すべてのデータが衝突すると、ハッシュ テーブルは単一リンク リストに縮退します。次の図は、PHP の通常のハッシュ テーブルと縮退ハッシュ テーブルの概念図です。

ハッシュテーブル衝突攻撃は、すべてのデータが衝突するようにデータを注意深く構築し、ハッシュテーブルを人為的に縮退した単一リンクリストに変えることです。このとき、ハッシュテーブルに対するさまざまな操作の時間が1桁増加します。大量の CPU リソースが使用されると、システムがリクエストに迅速に応答できなくなり、サービス拒否攻撃 (DoS) の目的が達成されます。

ご覧のとおり、ハッシュ衝突攻撃を実行する前提は、ハッシュ アルゴリズムが特に衝突を見つけやすいということです。幸いにも (または残念ながら)、ほとんどのプログラミング言語では問題になりません。ハッシュ アルゴリズムは非常にシンプルなので (これは効率性を考慮したものです)、攻撃データを簡単に構築できます。次のセクションでは、Zend 関連のカーネル コードを分析して、ハッシュ テーブルの衝突を攻撃し、PHP を攻撃する方法を見つけます。
Zend ハッシュ テーブルの内部実装データ構造
PHP はバケットを表すために Backet と呼ばれる構造を使用し、同じハッシュ値を持つすべてのバケットは単一リンク リストに編成されます。ハッシュ テーブルは HashTable 構造によって表されます。関連するソース コードは zend/Zend_hash.h にあります:

リーリー

フィールド名はその目的を明確に示しているため、これ以上の説明は不要です。次のフィールドに注目してください: Bucket の "h" は元のキーを格納するために使用されます。HashTable の nTableMask はマスクであり、通常は nTableSize - 1 に設定されます。これはハッシュ アルゴリズムについては後で説明するときに詳しく説明します。 ; arBuckets はポインターの配列を指します。各要素はバケット リストの先頭へのポインターです。
ハッシュアルゴリズム
PHP ハッシュ テーブルの最小容量は 8 (2^3)、最大容量は 0×80000000 (2^31) で、2 の整数乗に丸められます (つまり、長さは自動的に整数に拡張されます)。 2 の累乗 (13 など)。要素のハッシュ テーブルの長さは 16、要素 100 個のハッシュ テーブルの長さは 128)。 nTableMask は、ハッシュ テーブルの長さ (丸め後) から 1 を引いた値に初期化されます。具体的なコードは zend/Zend_hash.c の _zend_hash_init 関数にあります。ここでは、この記事に関連する部分を抜粋し、いくつかのコメントを追加します。

リーリー

2 の整数乗に丸める PHP の方法は非常に賢く、覚えて必要なときに使用できることは言及する価値があります。

Zend HashTable のハッシュ アルゴリズムは非常にシンプルです:

コードをコピーします コードは次のとおりです:
ハッシュ(キー)=キー&nテーブルマスク

つまり、データの元のキーと HashTable の nTableMask の間でビットごとの AND を実行するだけです。

元のキーが文字列の場合は、まず Times33 アルゴリズムを使用して文字列を整数に変換し、次に nTableMask とビット単位の AND を実行します。

复制代码 代码如下:
hash(strkey)=time33(strkey)&nTableMask

下面是Zend源码中查找哈希表的代码:

ZEND_API int zend_hash_index_find(constHashTable *ht, ulong h, void **pData)
{
 uint nIndex;
 Bucket *p;
 IS_CONSISTENT(ht);
 nIndex = h & ht->nTableMask;
 p = ht->arBuckets[nIndex];
 while(p != NULL) {
 if((p->h == h) && (p->nKeyLength == 0)) {
  *pData = p->pData;
  returnSUCCESS;
 }
 p = p->pNext;
 }
 returnFAILURE;
}
ZEND_API int zend_hash_find(constHashTable *ht, constchar *arKey, uint nKeyLength, void **pData)
{
 ulong h;
 uint nIndex;
 Bucket *p;
 IS_CONSISTENT(ht);
 h = zend_inline_hash_func(arKey, nKeyLength);
 nIndex = h & ht->nTableMask;
 p = ht->arBuckets[nIndex];
 while(p != NULL) {
 if((p->h == h) && (p->nKeyLength == nKeyLength)) {
  if(!memcmp(p->arKey, arKey, nKeyLength)) {
  *pData = p->pData;
  returnSUCCESS;
  }
 }
 p = p->pNext;
 }
 returnFAILURE;
}

其中zend_hash_index_find用于查找整数key的情况,zend_hash_find用于查找字符串key。逻辑基本一致,只是字符串key会通过zend_inline_hash_func转为整数key,zend_inline_hash_func封装了times33算法,具体代码就不贴出了。
 攻击 基本攻击
知道了PHP内部哈希表的算法,就可以利用其原理构造用于攻击的数据。一种最简单的方法是利用掩码规律制造碰撞。上文提到Zend HashTable的长度nTableSize会被圆整为2的整数次幂,假设我们构造一个2^16的哈希表,则nTableSize的二进制表示为:1 0000 0000 0000 0000,而nTableMask = nTableSize - 1为:0 1111 1111 1111 1111。接下来,可以以0为初始值,以2^16为步长,制造足够多的数据,可以得到如下推测:

0000 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0

0001 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0

0010 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0

0011 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0

0100 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 0

……

概况来说只要保证后16位均为0,则与掩码位于后得到的哈希值全部碰撞在位置0。

下面是利用这个原理写的一段攻击代码:

<&#63;php
$size= pow(2, 16);
$startTime= microtime(true);
$array= array();
for($key= 0, $maxKey= ($size- 1) * $size; $key<= $maxKey; $key+= $size) {
 $array[$key] = 0;
}
$endTime= microtime(true);
echo $endTime- $startTime, " seconds";

这段代码在我的VPS上(单CPU,512M内存)上用了近88秒才完成,并且在此期间CPU资源几乎被用尽:

而普通的同样大小的哈希表插入仅用时0.036秒:

<&#63;php
$size= pow(2, 16);
$startTime= microtime(true);
$array= array();
for($key= 0, $maxKey= ($size- 1) * $size; $key<= $size; $key+= 1) {
 $array[$key] = 0;
}
$endTime= microtime(true);
echo $endTime- $startTime, " seconds";

可以证明第二段代码插入N个元素的时间在O(N)水平,而第一段攻击代码则需O(N^2)的时间去插入N个元素。

POST攻击

当然,一般情况下很难遇到攻击者可以直接修改PHP代码的情况,但是攻击者仍可以通过一些方法间接构造哈希表来进行攻击。例如PHP会将接收到的HTTP POST请求中的数据构造为$_POST,而这是一个Array,内部就是通过Zend HashTable表示,因此攻击者只要构造一个含有大量碰撞key的post请求,就可以达到攻击的目的。具体做法不再演示。

防护 POST攻击的防护

针对POST方式的哈希碰撞攻击,目前PHP的防护措施是控制POST数据的数量。在>=PHP5.3.9的版本中增加了一个配置项max_input_vars,用于标识一次http请求最大接收的参数个数,默认为1000。因此PHP5.3.x的用户可以通过升级至5.3.9来避免哈希碰撞攻击。5.2.x的用户可以使用这个patch: http://www.laruence.com/2011/12/30/2440.html 。

另外的防护方法是在Web服务器层面进行处理,例如限制http请求body的大小和参数的数量等,这个是现在用的最多的临时处理方案。具体做法与不同Web服务器相关,不再详述。

其它防护

上面的防护方法只是限制POST数据的数量,而不能彻底解决这个问题。例如,如果某个POST字段是一个json数据类型,会被PHP json_decode ,那么只要构造一个超大的json攻击数据照样可以达到攻击目的。理论上,只要PHP代码中某处构造Array的数据依赖于外部输入,则都可能造成这个问题,因此彻底的解决方案要从Zend底层HashTable的实现动手。一般来说有两种方式,一是限制每个桶链表的最长长度;二是使用其它数据结构如 红黑树 取代链表组织碰撞哈希(并不解决哈希碰撞,只是减轻攻击影响,将N个数据的操作时间从O(N^2)降至O(NlogN),代价是普通情况下接近O(1)的操作均变为O(logN))。

目前使用最多的仍然是POST数据攻击,因此建议生产环境的PHP均进行升级或打补丁。至于从数据结构层面修复这个问题,目前还没有任何方面的消息。

以上所述就是本文的全部内容,希望大家喜欢。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/1041337.html技術記事 PHP カーネルの探索: ハッシュ テーブル衝突攻撃の原理 以下のカーネルでは、PHP カーネルの探索: ハッシュ テーブル衝突攻撃の原理を画像とテキストで示します。 最近のハッシュ テーブル衝突攻撃 (...
)
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
PHPの現在のステータス:Web開発動向を見てくださいPHPの現在のステータス:Web開発動向を見てくださいApr 13, 2025 am 12:20 AM

PHPは、現代のWeb開発、特にコンテンツ管理とeコマースプラットフォームで依然として重要です。 1)PHPには、LaravelやSymfonyなどの豊富なエコシステムと強力なフレームワークサポートがあります。 2)パフォーマンスの最適化は、Opcacheとnginxを通じて達成できます。 3)PHP8.0は、パフォーマンスを改善するためにJITコンパイラを導入します。 4)クラウドネイティブアプリケーションは、DockerおよびKubernetesを介して展開され、柔軟性とスケーラビリティを向上させます。

PHP対その他の言語:比較PHP対その他の言語:比較Apr 13, 2025 am 12:19 AM

PHPは、特に迅速な開発や動的なコンテンツの処理に適していますが、データサイエンスとエンタープライズレベルのアプリケーションには良くありません。 Pythonと比較して、PHPはWeb開発においてより多くの利点がありますが、データサイエンスの分野ではPythonほど良くありません。 Javaと比較して、PHPはエンタープライズレベルのアプリケーションでより悪化しますが、Web開発により柔軟性があります。 JavaScriptと比較して、PHPはバックエンド開発により簡潔ですが、フロントエンド開発のJavaScriptほど良くありません。

PHP対Python:コア機能と機能PHP対Python:コア機能と機能Apr 13, 2025 am 12:16 AM

PHPとPythonにはそれぞれ独自の利点があり、さまざまなシナリオに適しています。 1.PHPはWeb開発に適しており、組み込みのWebサーバーとRich Functionライブラリを提供します。 2。Pythonは、簡潔な構文と強力な標準ライブラリを備えたデータサイエンスと機械学習に適しています。選択するときは、プロジェクトの要件に基づいて決定する必要があります。

PHP:Web開発の重要な言語PHP:Web開発の重要な言語Apr 13, 2025 am 12:08 AM

PHPは、サーバー側で広く使用されているスクリプト言語で、特にWeb開発に適しています。 1.PHPは、HTMLを埋め込み、HTTP要求と応答を処理し、さまざまなデータベースをサポートできます。 2.PHPは、ダイナミックWebコンテンツ、プロセスフォームデータ、アクセスデータベースなどを生成するために使用され、強力なコミュニティサポートとオープンソースリソースを備えています。 3。PHPは解釈された言語であり、実行プロセスには語彙分析、文法分析、編集、実行が含まれます。 4.PHPは、ユーザー登録システムなどの高度なアプリケーションについてMySQLと組み合わせることができます。 5。PHPをデバッグするときは、error_reporting()やvar_dump()などの関数を使用できます。 6. PHPコードを最適化して、キャッシュメカニズムを使用し、データベースクエリを最適化し、組み込み関数を使用します。 7

PHP:多くのウェブサイトの基礎PHP:多くのウェブサイトの基礎Apr 13, 2025 am 12:07 AM

PHPが多くのWebサイトよりも優先テクノロジースタックである理由には、その使いやすさ、強力なコミュニティサポート、広範な使用が含まれます。 1)初心者に適した学習と使用が簡単です。 2)巨大な開発者コミュニティと豊富なリソースを持っています。 3)WordPress、Drupal、その他のプラットフォームで広く使用されています。 4)Webサーバーとしっかりと統合して、開発の展開を簡素化します。

誇大広告を超えて:今日のPHPの役割の評価誇大広告を超えて:今日のPHPの役割の評価Apr 12, 2025 am 12:17 AM

PHPは、特にWeb開発の分野で、最新のプログラミングで強力で広く使用されているツールのままです。 1)PHPは使いやすく、データベースとシームレスに統合されており、多くの開発者にとって最初の選択肢です。 2)動的コンテンツ生成とオブジェクト指向プログラミングをサポートし、Webサイトを迅速に作成および保守するのに適しています。 3)PHPのパフォーマンスは、データベースクエリをキャッシュおよび最適化することで改善でき、その広範なコミュニティと豊富なエコシステムにより、今日のテクノロジースタックでは依然として重要になります。

PHPの弱い参照は何ですか、そしていつ有用ですか?PHPの弱い参照は何ですか、そしていつ有用ですか?Apr 12, 2025 am 12:13 AM

PHPでは、弱い参照クラスを通じて弱い参照が実装され、ガベージコレクターがオブジェクトの回収を妨げません。弱い参照は、キャッシュシステムやイベントリスナーなどのシナリオに適しています。オブジェクトの生存を保証することはできず、ごみ収集が遅れる可能性があることに注意する必要があります。

PHPで__invoke Magicメソッドを説明してください。PHPで__invoke Magicメソッドを説明してください。Apr 12, 2025 am 12:07 AM

\ _ \ _ Invokeメソッドを使用すると、オブジェクトを関数のように呼び出すことができます。 1。オブジェクトを呼び出すことができるように\ _ \ _呼び出しメソッドを定義します。 2。$ obj(...)構文を使用すると、PHPは\ _ \ _ Invokeメソッドを実行します。 3。ロギングや計算機、コードの柔軟性の向上、読みやすさなどのシナリオに適しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール