Фаззинг все чаще применяют и программисты — для проверки своих приложений на прочность, и исследователи безопасности, и хакеры. Но пользоваться фаззерами не выйдет, если не понимаешь, что именно они делают. Зато, узнав это, ты освоишь современную технику, с помощью которой сейчас находят все новые и новые уязвимости в самых разных приложениях. В этой статье я расскажу, как работают разные виды фаззинга, и на примере WinAFL покажу, как пользоваться этим инструментом.
В общих чертах смысл фаззинга заключается в передаче в программу (я имею в виду любой исполняемый код, динамическую библиотеку или драйвер) любого нестандартного потока данных, чтобы попытаться вызвать проблемы в ходе исполнения.
Так что же мы ищем при помощи фаззинга? Это достаточно широкий спектр ошибок программного обеспечения, который включает в себя такие вещи, как переполнение буферов, некорректная обработка пользовательских данных, разнообразные утечки ресурсов (в том числе при работе с памятью), различные ошибки синхронизации, приводящие к состоянию гонки, и прочее. Каждое такое событие фиксируется фаззером и более подробно исследуется в дальнейшем.
Техники
Как видишь, сама концепция достаточно простая. Но за счет того, что количество итераций достигает сотен и тысяч миллионов (время тестирования при этом составляет несколько суток даже на мощных машинах), фаззеры находят в программах самые нетривиальные ошибки.
Конечно, существуют и более продвинутые техники. Например, фаззинг с использованием трассировки и построением уравнений для SMT-решателей. В теории это помогает покрывать даже труднодоступные ветки кода. При этом включается трасса внутри ядра ОС, с одновременным исключением известных участков (нет никакого смысла фаззить внутренности функций WinAPI и прочего). Однако заставить все правильно работать непросто, и сегодня это скорее «черная магия», чем распространенная практика.
Типы фаззеров
С техниками фаззинга более-менее разобрались, теперь перейдем к типам фаззеров.
Чем обернется простая проверка, если антивирусный сканер решит, что перед ним файл PE, упакованный UPX, а при распаковке выяснится, что это вовсе не UPX, а что-то, что лишь притворяется им? Естественно, алгоритм распаковки будет другой, но поведение сканера при этом предугадать сложно. Может быть, он обрушится. Может быть, просто повесит на файл флаг «поврежден» и пропустит. И это далеко не полный перечень возможных исходов. Фаззеры форматов файлов помогут протестировать подобные вещи.
Аргументы командной строки и переменные окружения
Достаточно полезная штука, когда нужно посмотреть, как реагируют на запросы IOCTL различные драйверы режима ядра. Помимо устройств и периферии, драйверами зачастую пользуются некоторые программы для взаимодействия с системой. Конечно, структура IRP-запроса почти всегда неизвестна, но перехваченные пакеты можно использовать в качестве основы для корпуса.
Такие фаззеры бывают заточены под известные протоколы, но есть и всеядные экземпляры. Например, фаззер OWASP JBroFuzz тестирует реализации известных протоколов на предмет наличия таких уязвимостей, как межсайтовый скриптинг, переполнение буферов, SQL-инъекции и многое другое. С другой стороны, есть утилита SPIKE, которая может протестировать незнакомые протоколы на многие уязвимости.
Да, даже для поиска дыр в браузерах есть специальные фаззеры. На сегодняшний день современные браузеры очень сложны и содержат множество движков: они обрабатывают различные версии документов, протоколов, CSS, COM, DOM и многое другое. Так что участники различных bug bounty ищут дыры не только голыми руками. ?