Удаленная перезапись переменной в ф-ии parse_str() в PHP. Оригинал http://www.acid-root.new.fr/advisories/14070612.txt . Вступление [II]. Руководство. Функция void parse_str ( string $str [, array &$arr] ) парсит строку str, которая должна иметь формат типа URL и присваивает значения переменным в текущем контексте, если не передан второй аргумент arr. В последнем случае значения будкт сохранены в этой переменной как элементы массива. Замечание: Поддержка необязательного второго аргумента была добавлена в PHP 4.0.3. Замечание: Для получения текущей строки запроса (QUERY_STRING) может быть использована переменная $_SERVER['QUERY_STRING']. Также ознакомьтесь с разделом "Переменные вне PHP". Замечание: Опция magic_quotes_gpc влияет на выходящее значение ф-ии, т.к. parse_str() использует тот же механизм, что пхп использует для заполнения $_GET, $_POST. [III]. Исходный код. Code: --- ./ext/standard/string.c --- 4025. /* 4025. {{{ proto void parse_str(string encoded_string [, array result]) 4026. Parses GET/POST/COOKIE data and sets global variables 4026. */ 4027. PHP_FUNCTION(parse_str) 4028. { 4029. zval **arg; 4030. zval **arrayArg; 4031. zval *sarg; 4032. char *res = NULL; 4033. int argCount; 4034. 4035. argCount = ZEND_NUM_ARGS(); 4036. if (argCount < 1 || 4036. argCount > 2 || 4036. zend_get_parameters_ex(argCount,&arg,&arrayArg) == FAILURE) 4036. { ####. /* Not enough or too many args */ 4037. WRONG_PARAM_COUNT; 4038. } 4039. 4040. convert_to_string_ex(arg); 4041. sarg = *arg; 4042. if (Z_STRVAL_P(sarg) && *Z_STRVAL_P(sarg)) { 4043. res = estrndup(Z_STRVAL_P(sarg), Z_STRLEN_P(sarg)); 4043. ####. /* Allocate Z_STRLEN_P(sarg)+1 bytes of memory and copy ####. Z_STRLEN_P(sarg) bytes from Z_STRVAL_P(sarg) to the ####. newly allocated block */ 4044. } 4045. ####. /* parse_str(argv1) */ 4046. if (argCount == 1) 4046. { 4047. zval tmp; 4048. Z_ARRVAL(tmp) = EG(active_symbol_table); 4049. ####. /* The problem is here, there is no conditions before setting ####. the variable. If a variable already exists, it will overwrite it */ 4049. 4050. sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC); 4051. } ####. /* parse_str(argv1,argv2) */ 4051. else 4051. { 4052. /* Clear out the array that was passed in. */ 4053. zval_dtor(*arrayArg); 4054. array_init(*arrayArg); 4055. 4056. sapi_module.treat_data(PARSE_STRING, res, *arrayArg TSRMLS_CC); 4057. } 4058. } [IV]. Пояснения Как вы уже увидели в мануале, пользователь, использующий эту ф-ию не защищен от перезаписи переменных. Девелоперы просто забыли проверить этот момент. Простой PoC: PHP: <?php # ?var=new ########### $var = 'init'; # parse_str($_SERVER['QUERY_STRING']); # print $var; # new # ?array[]=new # Array ############## # ( $array = array('init'); # [0] => init parse_str($_SERVER['QUERY_STRING']); # [1] => new print_r($array); # ) # ?array=new ############ # Array $array = array('init'); # ( parse_str($_SERVER['QUERY_STRING'],$array); # [array] => new print_r($array); # ) ?> Этот тип уязвимости открывает дверь к многим другим уязвимостям, поэтому в данном случае достаточно сложно обозначить уровень риска. В отлчиие от extract(), тут нет опции на подобии EXTR_SKIP, которая отвечает за защиту от перезаписи переменной (если переменная с таким именем существует, будет сохранено её прежнее значение). Поэтому если вы хотите чтобы ваш код был безопасным - не используйте эту ф-ию. Я не связывался с пхп-тимой, но возможно они зарелизят фикс на эту уязвимость. Избранные мысли из [V]. Комменты 1. Даже если register_globals отключено, уязвимость есть как минимум на пхп 4.4.4 2. Hardened-PHP и PHP с сухосин патчем тоже уязвимы. 3. При тесте уязвимости она имело место на
Сколько двигов перерыл, но что-то эту функцию видел в применении всего несколько раз. Так что особой "опасности" и чего-то сверхестественного тут не вижу. Просто нужно думать, когда используешь. // и не только тут)
2blackybr:маладец, спасибо, только одно замечание - если дословный перевод получается бредом, то можно смело высказать мысль своими словами. RE:"Замечание: Опция magic_quotes_gpc влияет на выходящее значение ф-ии, т.к. parse_str() использует тот же механизм, что пхп использует для заполнения $_GET, $_POST." 2Helios: RE:"Сколько двигов перерыл, но что-то эту функцию видел в применении всего несколько раз. Так что особой "опасности" и чего-то сверхестественного тут не вижу." - оттого что ты не нашел применение данной уязвимости, опасность и актуальность данной баги не уменьшается