Одним из новшеств релиза PHP 5.3.9 стало введение нового параметра конфигурации max_input_vars, который устанавливает максимальное возможное количество входящих параметров в запросе. Новая директива является мерой против атак Hash Collision DoS, которые могут привести к отказу в обслуживании при отправке большого количества входящих параметров. Однако в коде, отвечающим за ограничение количества параметров в запросе, была допущена ошибка, которая приводит к удаленному выполнению кода. Уязвимость была обнаружена специалистом в области информационной безопасности Стефаном Эссером, известным за публикацию ряда серьезных уязвимостей в PHP, а также за разработку джейлбрейка для Apple iOS.
Уязвимость возникает в случае, когда количество входящих параметров превышает значение max_input_vars (по умолчанию 1000).
Уязвимая функция php_register_variable_ex (php_variables.c@194):
Ограничение количества параметров реализовано циклом с условием if, причем отсутствует блок else, который должен был бы останавливать проход цикла. В следствие этого, на выходе из цикла в макрос Z_ARRVAL_PP (строка 18), который возвращает ссылку на обновленную hash-таблицу, попадет gpc_element_p со значением последней обработанной в цикле переменной, что ведет к выполнению кода.
Уязвимости не подвержены сервера с установленным расширением Suhosin patch, автором которого является Стефан Эссер. Примечательно, что накануне linux-дистрибутив Debian отказался от Suhosin patch, тем самым подвергая своих пользователей новой угрозе. А самое интересное это то, что уязвимость найдена в фиксе другой уязвимости.
Уязвимость возникает в случае, когда количество входящих параметров превышает значение max_input_vars (по умолчанию 1000).
Уязвимая функция php_register_variable_ex (php_variables.c@194):
- PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array TSRMLS_DC)
- {
- /* ... */
- if (is_array) {
- /* ... */
- while (1) {
- /* ... */
- if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
- if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
- }
- MAKE_STD_ZVAL(gpc_element);
- array_init(gpc_element);
- zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
- }
- }
- /* ... */
- symtable1 = Z_ARRVAL_PP(gpc_element_p);
- /* ... */
Ограничение количества параметров реализовано циклом с условием if, причем отсутствует блок else, который должен был бы останавливать проход цикла. В следствие этого, на выходе из цикла в макрос Z_ARRVAL_PP (строка 18), который возвращает ссылку на обновленную hash-таблицу, попадет gpc_element_p со значением последней обработанной в цикле переменной, что ведет к выполнению кода.
Уязвимости не подвержены сервера с установленным расширением Suhosin patch, автором которого является Стефан Эссер. Примечательно, что накануне linux-дистрибутив Debian отказался от Suhosin patch, тем самым подвергая своих пользователей новой угрозе. А самое интересное это то, что уязвимость найдена в фиксе другой уязвимости.