Ideally, the time complexity of the hash table insert and find operation is O (1), and any data item can calculate a hash value (key) in a time independent of the hash table length, and then navigate to a bucket within a constant time (the term bucket, which represents a position in the hash table). Of course this is ideal, because the length of any hash table is limited, so there must be a case where different data items have the same hash value, when different data items are set to the same bucket, called collisions (collision). The implementation of the hash table needs to solve the collision problem, the collision solution has two general ideas, the first is to set the collision data to other barrels according to some principle, such as linear detection-if the data in the insertion of a collision, then the order to find the bucket behind the bucket, put it into the first unused bucket The second strategy is that each bucket is not a location that can hold a single data item, but a data structure that can hold multiple data (for example, a linked list or a red-black tree), and all the colliding data is organized in the form of a data structure.
Regardless of which collision resolution strategy is used, the time complexity of the insert and find operations is no longer O (1). To find, for example, cannot be positioned through the key to the end of the bucket, you must also compare the original key (that is, the key before the hash) is equal, if not equal, you want to use the same algorithm as insert to continue the lookup until a matching value is found or the confirmation data is not in the hash table.
Attack
Knowing the algorithm of the PHP internal hash table, you can use its principle to construct the data for the attack. One of the simplest methods is to create collisions using a mask pattern. As mentioned above, the length of the Zend Hashtable ntablesize will be rounded to 2 of the whole power, assuming we construct a 2^16 hash table, then ntablesize binary representation is: 1 0000 0000 0000 0000, and Ntablemask = Ntablesize–1:0 1111 1111 1111 1111. Next, you can use 0 as the initial value, with 2^16 as the step size, to produce enough data, you can get the following speculation:
0000 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 00001 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 00010 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 00011 0000 0000 0000 0000 & 0 1111 1111 1111 1111 = 00100 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:
<?php$size = POW (2, +); $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 ', ' \ n ';? >
PHP Hash Table Collision attack