Описание
Heap buffer overflow in array_merge()
The following PHP code triggers a reliable heap buffer overflow:
Or the general case:
This is because packed arrays in array_merge() have an optimization that requires precomputing the count of the elements, done using count += zend_hash_num_elements(Z_ARRVAL_P(arg));. However, this may overflow. Note that even if it didn't, it would cause a DoS because array_init() will trigger a bailout with too large counts.
The code provided is artificial, but I believe this can happen in the real world with for example large sets of JSON data that are then passed to array_merge(). The total count just has to exceed HT_MAX_SIZE to trigger the DoS or the 32-bit limit to trigger the buffer overflow.
Impact
If we were using a memory safe language we would "just" be limited to the DoS, but now we have heap corruption and all the joys of it. This bug has been in PHP since PHP 7.1.
Workarounds
Prevent a large number of inputs of long arrays to array_merge().
Security impact
As noted the example code is just a PoC exploit trigger.
The JSON file could be crafted and loaded via json_decode that results in a structure like: [array1, array2, array3, ...]. Then the code could use array_merge(array1, array2, array3, ...) from the JSON data. The arrays itself may be relatively small but if the sum of elements exceed the HT_MAX_SIZE bound, the buffer overflow is triggered.
Something like this:
Пакеты
< 8.1.34
8.1.34
< 8.2.30
8.2.30
< 8.3.29
8.3.29
< 8.4.16
8.4.16
< 8.5.1
8.5.1
Связанные уязвимости
In PHP versions:8.1.* before 8.1.34, 8.2.* before 8.2.30, 8.3.* before 8.3.29, 8.4.* before 8.4.16, 8.5.* before 8.5.1, a heap buffer overflow occurs in array_merge() when the total element count of packed arrays exceeds 32-bit limits or HT_MAX_SIZE, due to an integer overflow in the precomputation of element counts using zend_hash_num_elements(). This may lead to memory corruption or crashes and affect the integrity and availability of the target server.
In PHP versions:8.1.* before 8.1.34, 8.2.* before 8.2.30, 8.3.* before 8.3.29, 8.4.* before 8.4.16, 8.5.* before 8.5.1, a heap buffer overflow occurs in array_merge() when the total element count of packed arrays exceeds 32-bit limits or HT_MAX_SIZE, due to an integer overflow in the precomputation of element counts using zend_hash_num_elements(). This may lead to memory corruption or crashes and affect the integrity and availability of the target server.
In PHP versions:8.1.* before 8.1.34, 8.2.* before 8.2.30, 8.3.* before ...