40
HashTable HashDoS @yuya_takeyama

HashTable と HashDos

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: HashTable と HashDos

HashTableと

HashDoS@yuya_takeyama

Page 2: HashTable と HashDos

Forthe

Beginners

Page 3: HashTable と HashDos

Bya

Beginner

Page 4: HashTable と HashDos

アジェンダ

•ハッシュテーブルとは•PHP におけるハッシュテーブル•PHP における HashDoS

Page 5: HashTable と HashDos

ハッシュテーブルとは•Key から Value を検索•連想配列に使われる•基本的には効率的で高速•最悪の場合はとても非効率に

Page 7: HashTable と HashDos

PHP における ハッシュテーブル

•HashTable 構造体•複数の Bucket 構造体から成る•順番を保持

Page 8: HashTable と HashDos

typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;} HashTable;

Page 9: HashTable と HashDos

typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;} HashTable;

テーブルのスロット数

Page 10: HashTable と HashDos

typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;} HashTable; 要素数

Page 11: HashTable と HashDos

typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;} HashTable;

先頭または

末尾の要素

Page 12: HashTable と HashDos

typedef struct _hashtable { uint nTableSize; uint nTableMask; uint nNumOfElements; ulong nNextFreeElement; Bucket *pInternalPointer; Bucket *pListHead; Bucket *pListTail; Bucket **arBuckets; dtor_func_t pDestructor; zend_bool persistent; unsigned char nApplyCount; zend_bool bApplyProtection;} HashTable;

要素の集まり

Page 13: HashTable と HashDos

ドユコト?

Page 14: HashTable と HashDos

可視化しましょう 

Page 15: HashTable と HashDos
Page 16: HashTable と HashDos
Page 17: HashTable と HashDos

<?phphashtable_dump(array(1, 2, 3, 4, 5, 6, 7, 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 8pListHead: 0pListTail: 7**arBuckets: 0 => [0, NULL] 1 => [1, NULL] 2 => [2, NULL] 3 => [3, NULL] 4 => [4, NULL] 5 => [5, NULL] 6 => [6, NULL] 7 => [7, NULL]*/

テーブルのスロット数

Page 18: HashTable と HashDos

<?phphashtable_dump(array(1, 2, 3, 4, 5, 6, 7, 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 8pListHead: 0pListTail: 7**arBuckets: 0 => [0, NULL] 1 => [1, NULL] 2 => [2, NULL] 3 => [3, NULL] 4 => [4, NULL] 5 => [5, NULL] 6 => [6, NULL] 7 => [7, NULL]*/ 要素数

Page 19: HashTable と HashDos

<?phphashtable_dump(array(1, 2, 3, 4, 5, 6, 7, 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 8pListHead: 0pListTail: 7**arBuckets: 0 => [0, NULL] 1 => [1, NULL] 2 => [2, NULL] 3 => [3, NULL] 4 => [4, NULL] 5 => [5, NULL] 6 => [6, NULL] 7 => [7, NULL]*/

先頭または

末尾の要素

Page 20: HashTable と HashDos

<?phphashtable_dump(array(1, 2, 3, 4, 5, 6, 7, 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 8pListHead: 0pListTail: 7**arBuckets: 0 => [0, NULL] 1 => [1, NULL] 2 => [2, NULL] 3 => [3, NULL] 4 => [4, NULL] 5 => [5, NULL] 6 => [6, NULL] 7 => [7, NULL]*/

要素の集まり

Page 21: HashTable と HashDos

Bucket 構造体

•値の入れ物•配列内の一要素を表現•二重の双方向リスト

Page 22: HashTable と HashDos

typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket;

キーの数値または

キー文字列のハッシュ値ここあんまり自信無いです...

Page 23: HashTable と HashDos

typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket; キー文字列

Page 24: HashTable と HashDos

typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket; 値まだよく読めてないです...

Page 25: HashTable と HashDos

typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket;

ハッシュテーブル内の前後の要素

Page 26: HashTable と HashDos

typedef struct bucket { ulong h; uint nKeyLength; void *pData; void *pDataPtr; struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; const char *arKey;} Bucket;

スロット内の前後の要素

Page 27: HashTable と HashDos

二重の双方向リスト

•ハッシュテーブル内のリスト-> 配列の走査に使う

•スロット内のリスト-> ハッシュ値の衝突時に連結

Page 29: HashTable と HashDos

p = ht->pListHead;while (p != NULL) { // p にごにょごにょする p = p->pListNext;}

リスト全体の走査

Page 30: HashTable と HashDos

h = ハッシュ値の計算(arKey, nLength);

// スロット番号の算出nIndex = h & ht->nTableMask;

p = ht->arBuckets[nIndex];while (p != NULL) { if (キーが等しければ) {

*pData = p->pData; return SUCCESS; } p = p->pNext;}return FAILURE;

キーによる探索

Page 31: HashTable と HashDos

PHPにおけるHashDoS

Page 32: HashTable と HashDos

テキスト

http://blog.tokumaru.org/2011/12/webdoshashdos.html

Page 33: HashTable と HashDos

HashDoS とは

•ハッシュ値の衝突する連想配列を作る•Web アプリに入力として与える

•非効率な挿入・検索が起こる•効率よく DoS アタックができる

Page 34: HashTable と HashDos

<?phphashtable_dump(array(0 => 1, 8 => 2, 16 => 3, 24 => 4, 32 => 5, 40 => 6, 48 => 7, 56 => 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 57pListHead: 0pListTail: 56**arBuckets: 0 => [56, 48, 40, 32, 24, 16, 8, 0, NULL] 1 => [NULL] 2 => [NULL] 3 => [NULL] 4 => [NULL] 5 => [NULL] 6 => [NULL] 7 => [NULL]*/

全ての要素が同じスロットに

Page 35: HashTable と HashDos

<?phphashtable_dump(array(0 => 1, 8 => 2, 16 => 3, 24 => 4, 32 => 5, 40 => 6, 48 => 7, 56 => 8));/*nTableSize: 8nTableMask: 7nNumOfElements: 8nNextFreeElement: 57pListHead: 0pListTail: 56**arBuckets: 0 => [56, 48, 40, 32, 24, 16, 8, 0, NULL] 1 => [NULL] 2 => [NULL] 3 => [NULL] 4 => [NULL] 5 => [NULL] 6 => [NULL] 7 => [NULL]*/

全ての要素が同じスロットに

非効率な探索

Page 36: HashTable と HashDos

HashDoS への対策•入力による HashTable の生成を制限する (max_input_vars とか)

•根本的解決では無いが, 現実的なリスクを軽減できる

•続きは徳丸さんのブログで

Page 37: HashTable と HashDos

根本的な解決の事例

•Perl (5.8.1 以降)•Ruby (1.8.7-p356 より後)•ハッシュ値の予測を困難にする? まだよく調べてません...

Page 38: HashTable と HashDos

まとめ•PHP の HashTable は HashDoS に対して脆弱である

•運用でカバーしましょう•詳しくは徳丸さんのブログで

Page 39: HashTable と HashDos

ご清聴ありがとうございました

Page 40: HashTable と HashDos

参考資料• アルゴリズムとデータ構造編 第14章 ハッシュ探索①(チェイン法)

http://www.geocities.jp/ky_webid/algorithm/014.html

• PHPソースコードリーディング入門(とっかかり編)http://d.hatena.ne.jp/anatoo/20111031/1319991834

• Webアプリケーションに対する広範なDoS攻撃手法(hashdos)の影響と対策http://blog.tokumaru.org/2011/12/webdoshashdos.html

• Zend_Hash_Del_Key_Or_Index Vulnerabilityhttp://www.hardened-php.net/hphp/zend_hash_del_key_or_index_vulnerability.html

• ハッシュテーブルの実装https://www.codeblog.org/blog/moriyoshi/20060824.html

• PHP のコア: Zend Engine ハッカーの手引きhttp://www.php.net/manual/ja/internals2.php

• PHP Extensions: Understanding and working with hash API Part 1http://zendguru.wordpress.com/2009/05/10/php-extensions-understanding-and-working-with-hash-api-part-1/