PHP 5.2.x Remote Code Execution Vulnerability http://securityvulns.ru/docs27701.html http://www.securityfocus.com/archive/1/521695 http://www.securityfocus.com/bid/52065 http://xforce.iss.net/xforce/xfdb/73286 Description: If PHP bails out in startup stage before setting PG(modules_activated) to 1, the filter_globals struct is not cleaned up on shutdown stage. The subsequence request will use uncleaned value in filter_globals struct. With special crafted request, this problem can lead to information disclosure and remote code execution. Only apache modules SAPI are found to vulnerable to this problem. While other SAPIs are safe because a PHP process exits when PHP bails out before setting PG(modules_activated) to 1. This bug was fixed before releasing 5.3.0. http://svn.php.net/viewvc?view=revision&revision=279522. But the patch is not backported to 5.2 version as described in https://bugs.php.net/bug.php?id=47930 This patch backports it. Index: branches/PHP_5_3/ext/filter/filter.c =================================================================== diff -urNp -x '*.orig' php-5.2.17.org/ext/filter/filter.c php-5.2.17/ext/filter/filter.c --- php-5.2.17.org/ext/filter/filter.c 2021-10-23 19:13:24.436458386 +0200 +++ php-5.2.17/ext/filter/filter.c 2021-10-23 19:13:27.149791720 +0200 @@ -76,6 +76,7 @@ filter_list_entry filter_list[] = { #endif static unsigned int php_sapi_filter(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC); +static unsigned int php_sapi_filter_init(TSRMLS_D); /* {{{ filter_functions[] */ @@ -233,7 +234,7 @@ PHP_MINIT_FUNCTION(filter) REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_RES_RANGE", FILTER_FLAG_NO_RES_RANGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_PRIV_RANGE", FILTER_FLAG_NO_PRIV_RANGE, CONST_CS | CONST_PERSISTENT); - sapi_register_input_filter(php_sapi_filter); + sapi_register_input_filter(php_sapi_filter, php_sapi_filter_init); return SUCCESS; } @@ -302,6 +303,17 @@ static filter_list_entry php_find_filter } /* }}} */ +static unsigned int php_sapi_filter_init(TSRMLS_D) +{ + IF_G(get_array) = NULL; + IF_G(post_array) = NULL; + IF_G(cookie_array) = NULL; + IF_G(server_array) = NULL; + IF_G(env_array) = NULL; + IF_G(session_array) = NULL; + return SUCCESS; +} + static void php_zval_filter(zval **value, long filter, long flags, zval *options, char* charset, zend_bool copy TSRMLS_DC) /* {{{ */ { filter_list_entry filter_func; diff -urNp -x '*.orig' php-5.2.17.org/main/SAPI.c php-5.2.17/main/SAPI.c --- php-5.2.17.org/main/SAPI.c 2021-10-23 19:13:24.446458386 +0200 +++ php-5.2.17/main/SAPI.c 2021-10-23 19:13:27.149791720 +0200 @@ -323,6 +323,9 @@ SAPI_API void sapi_activate_headers_only sapi_module.activate(TSRMLS_C); } } + if (sapi_module.input_filter_init ) { + sapi_module.input_filter_init(TSRMLS_C); + } } /* @@ -389,6 +392,9 @@ SAPI_API void sapi_activate(TSRMLS_D) sapi_module.activate(TSRMLS_C); } } + if (sapi_module.input_filter_init ) { + sapi_module.input_filter_init(TSRMLS_C); + } } @@ -884,13 +890,14 @@ SAPI_API int sapi_register_treat_data(vo return SUCCESS; } -SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)) +SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D)) { TSRMLS_FETCH(); if (SG(sapi_started) && EG(in_execution)) { return FAILURE; } sapi_module.input_filter = input_filter; + sapi_module.input_filter_init = input_filter_init; return SUCCESS; } diff -urNp -x '*.orig' php-5.2.17.org/main/SAPI.h php-5.2.17/main/SAPI.h --- php-5.2.17.org/main/SAPI.h 2010-03-18 23:37:25.000000000 +0100 +++ php-5.2.17/main/SAPI.h 2021-10-23 19:13:27.149791720 +0200 @@ -188,7 +188,7 @@ SAPI_API int sapi_register_post_entry(sa SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC); SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D)); SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC)); -SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC)); +SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, unsigned int val_len, unsigned int *new_val_len TSRMLS_DC), unsigned int (*input_filter_init)(TSRMLS_D)); SAPI_API int sapi_flush(TSRMLS_D); SAPI_API struct stat *sapi_get_stat(TSRMLS_D); @@ -259,6 +259,7 @@ struct _sapi_module_struct { int phpinfo_as_text; char *ini_entries; + unsigned int (*input_filter_init)(TSRMLS_D); }; diff -urNp -x '*.orig' php-5.2.17.org/main/php_content_types.c php-5.2.17/main/php_content_types.c --- php-5.2.17.org/main/php_content_types.c 2010-01-03 10:23:27.000000000 +0100 +++ php-5.2.17/main/php_content_types.c 2021-10-23 19:13:27.149791720 +0200 @@ -75,7 +75,7 @@ int php_startup_sapi_content_types(TSRML { sapi_register_default_post_reader(php_default_post_reader); sapi_register_treat_data(php_default_treat_data); - sapi_register_input_filter(php_default_input_filter); + sapi_register_input_filter(php_default_input_filter, NULL); return SUCCESS; } /* }}} */