Инструменты пользователя

Инструменты сайта


что_такое_фаззинг

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

что_такое_фаззинг [2013/09/02 17:33] (текущий)
81.222.241.194 создано
Строка 1: Строка 1:
 +Что такое фаззинг?​
  
 +В зависимости от того, где осуществляется манипуляции с данными,​ фаззинг разделяется на множество категорий. Один из самых простых видов — файловый фаззинг,​ подразумевающий,​ что некой программе предлагается открыть некорректно составленный файл. Возьмем,​ к примеру,​ прогу для просмотра картинок. Если взять JPEG-файл и интересным образом поменять несколько байтов,​ то эта программа вполне возможно выругается:​ "​Что это ты мне подсунул?"​. А, возможно,​ вообще не сможет его переварить и вылетит,​ к примеру,​ с проблемой переполнения буфера. Значит,​ ее теоретически можно расковырять,​ доведя дело до рабочего эксплойта.
 +
 +Если говорить о способе манипуляции с данными,​ то фаззинг распределяется на генерацию и мутацию. Генерация — это случайным образом придуманный набор байтов,​ который подсовывается той же проге для просмотра картинок со словами:​ "​Это на самом деле JPEG-файл,​ читай его"​. Мутация — прием намного более изящный,​ подразумевающий внесение изменений в "​хороший",​ то есть вполне корректный файл. Если в случае с файловым фаззингом еще можно использовать "​генерацию",​ то в таких вещах, как сетевые протоколы,​ имеет смысл применять исключительно подход мутации. Более того, крайне желательно иметь представление,​ за что отвечает то или иное поле пакета и намеренно манипулировать с теми данными,​ которые могут быть некорректно обработаны. В зависимости от интеллекта,​ фаззеры бывают глупые и умные:
 +*Глупый (dump) фаззер ничего не знает о структуре файлов. Если говорить о сетевых протоколах,​ то единственное,​ что он может сделать — это изменить несколько байтов в исходном пакете и отправить его в надежде,​ что это может вызвать сбой.
 +*Умный (smart) фаззер имеет некоторое представленные о структуре данных. Вместо того, чтобы полностью надеяться на удачу, он может играться только с теми данными,​ которые отвечают,​ например,​ за размер буфера. Или подставлять в поля такие значения,​ которые заведомо,​ с учетом известного формата,​ будут некорректными.
 +
 +Фаззим файлы
 +
 +Одна из простейших утилит для реализации глупого фаззинга —
 +MiniFuzz . Проект разработан внутри Microsoft для тестирования своих собственных проектов. Дело в том, что использование фаззеров является обязательным этапом методологии SDL (Security Development Lifecycle ), принятой в Microsoft для разработчиков безопасного кода, включающей помимо прочего обильное fuzz-тестирование. Minifuzz можно натравить на любое приложение;​ главное,​ чтобы в качестве параметра для запуска оно воспринимало указание на файл, который ему необходимо открыть (скажем,​ winword.exe test_sample.doc). Для начала работы необходимо набрать несколько образцов "​правильных"​ файлов и положить их каталог,​ обозначенный как Template files, а также выбрать приложение для проверки,​ указав формат параметров для его запуска. Когда ты нажмешь на кнопку Start Fuzzing, программа возьмет один из образцов,​ изменит некоторые байты внутри него (количество изменяемых данных зависит от параметра Aggressiveness) и скормит его исследуемому приложению. Если тестируемая программа не вылетит через некоторый таймаут (по умолчанию 2 секунды),​ значит,​ тест пройден успешно.
 +
 +Приложение будет закрыто,​ и начнется следующая итерация проверки. Если же во время тестирования программа вылетит (бинго!),​ то для анализа у тебя будет, во-первых,​ файл-образец,​ который вызвал сбой при открытии,​ а, во-вторых,​ crash-файл с дампом программы. Для большего удобства Minifuzz легко прикручивается в Visual Studio, позволяя запускать fuzz-тестирование прямо из среды разработки через меню "Tools -> MiniFuzz"​. Впрочем,​ если по каким-то причинам MiniFuzz тебе не подойдет,​ то можно попробовать другой инструмент для dumb-фаззинга — FileFuzz , который разработан не Microsoft, а известной security-командой iDefense Labs.
 +
 +Фаззим протоколы
 +
 +Если MiniFuzz — это очень простой (хотя и эффективный) dump-фаззер,​ то проект Peach (в переводе — персик),​ разработанный Майком Эддингтоном — это уже мощное решение для smart-фаззинга,​ поддерживающее как режим мутации,​ так и генерации. Для проведения умного фаззинга программе необходимо знать структуру данных,​ с которыми она будет экспериментировать. Поэтому на вход фаззера подаются так называемые PeachPit’ы ("​косточки от персика"​) — специальные XML-конфиги,​ в которых задается структура данных,​ описание взаимоотношений между различными ее элементами,​ а также подходы для реализации мутаций. В отличие от Minifuzz, Peach может фаззить не только файлы, но и сетевые сервисы,​ RPC, COM/DCOM, SQL-хранимые процедуры и многое другое. Правда,​ такая универсальность приводит и к некоторым трудностям в использовании.
 +
 +Сразу предупреждаю:​ это не та программа,​ которую запускаешь и сразу понимаешь,​ что к чему. Чтобы внести ясность,​ предлагаю разобраться с Peach на конкретном примере,​ но вместо фаззинга файлов обратиться к другой области,​ а именно — поиску уязвимостей в сетевых сервисах. Для успеха придется дополнительно установить WinDBG в качестве отладчика,​ а также сниффер Wireshark и драйвер Winpcap, чтобы иметь возможность перехватывать сетевые пакеты во время фаззинга сетевых протоколов.
 +
 +Любой фаззинг в Peach'​е начинается с создания PeachPit. Как я уже сказал,​ в этом XML-файле определяется цель фаззинга,​ описывается структура данных,​ с которой будет работать фаззер,​ а также определяются правила манипуляции с ними. Для удобства автор фреймворка предлагает библиотеку для Visual Studio, серьезно упрощающую работу с PeachPit'​ами,​ в том числе с помощью автодополнения кода. Любая "​косточка"​ состоит из нескольких функциональных блоков. Чтобы не составлять весь файл с нуля, в корневом каталоге фаззера есть файл-шаблон template.xml,​ который мы и возьмем за основу.
 +
 +Важная часть любого PeachPit'​а — описание модели данных. Именно в этом месте мы делаем фаззер "​умным",​ рассказываем ему о структуре файле или протокола (размерах полей, смещениях и т.д.), с которым предстоит работать. Возьмем для примера простейший протокол TFTP и попробуем профаззить запрос на чтение файла (Read). Если верить RFC, то выглядит он следующим образом:​
 +
 +
 +TFTP PACKET
 +
 +--------------------------------------
 +| \x00\x01 | Filename | 0 | Mode | 0 |
 +--------------------------------------
 +
 +Получается,​ что запрос начинается с HEX-символов "​\x00\x01",​ после которых следует название файла и флаги режима передачи файла. При этом после полей Filename и Mode идут нулевые байты. Итак, задача — написать фаззер,​ который будет играться со значением Filename. Начнем с создания модели запроса в нашем PeachPit'​е в соответствии с RFC:
 +
 +<​DataModel name="​tftprrx">​
 +<Blob name="​opcode"​ valueType="​hex"​ value="​00 01" token="​true"/>​
 +<String name="​filename"​ value="​filename.txt"​ nullTerminated="​true"/>​
 +<String name="​mode"​ value="​NETASCII"​ token="​true"​ nullTerminated="​true"/>​
 +</​DataModel>​
 +
 +В первой строке модели мы задаем двухбайтный код, обозначающий запрос на чтение. Указанный здесь параметр token="​true"​ мы будем использовать каждый раз, чтобы дать понять Peach, что это поле остается как есть, и его не нужно фаззить. Обрати внимание,​ что в следующей строке,​ которая описывает поле filename, этого флага как раз нет, и именно поэтому фаззер будет манипулировать со значением в этом поле (или, другими словами,​ фаззить). В последней строке описывается поле, обозначающее режим работы. Для полей "​filename"​ и "​mode"​ мы подставляем флаг nullTerminated,​ указывая на то, что после них идут нулевые байты-разделители. Обрати внимание,​ что для каждого из трех полей указывается его тип (blob или string). Таким образом мы рассказываем фаззеру,​ с каким типом данных он будет иметь дело. Понятно,​ что это очень простая модель,​ в большинстве случаев с ее составлением придется поработать намного плотнее.
 +
 +После того, как модель данных готова,​ необходимо описать логику работы фаззера,​ которая описывается в следующем блоке PeachPit'​а. Поскольку единственное место, где мы будем осуществлять фаззинг — это поле filename, то и логика нас будет очень простая. Укажем Peach'​у,​ что необходимо отправлять данные (Action type="​output"​),​ используя ранее описанную модель данных "​tftprrx":​
 +
 +
 +<​StateModel name="​state1"​ initialState="​Initial">​
 +<State name="​Initial">​
 +<Action type="​output">​
 +<​DataModel ref="​tftprrx"/>​
 +</​Action>​
 +</​State>​
 +</​StateModel>​
 +
 +Следующий блок конфигурации фаззера — описание агентов. Агенты присоединяют к нужному процессу отладчик и постоянно следят за его состоянием. В случае вылета приложения из-за ошибки агенты записывают различные детали падения в логфайл,​ в том числе и вызвавший сбой запрос (в случае,​ если речь идет о снифинге сетевого протокола). Для того, чтобы классифицировать падение (Exploitable,​ Probably Exploitable,​ Probably Not Exploitable,​ Unknown), разработчик рекомендует дополнительно к отладчику WinDBG установить плагин !exploitable. Обозначим в этом блоке, что будем отслеживать состояние приложения TFTPD32 и весь UDP-трафик,​ поступающий на 69 порт (TFTP):
 +
 +<Agent name="​RemoteAgent"​ location="​http://​192.168.1.10:​9000">​
 +<Monitor class="​debugger.WindowsDebugEngine">​
 +<Param name="​Service"​ value="​TFTPD32"​ />
 +</​Monitor>​
 +<Monitor class="​network.PcapMonitor">​
 +<Param name="​filter"​ value="​udp port 69" />
 +</​Monitor>​
 +</​Agent>​
 +
 +Вот теперь почти все готово. Осталось связать между собой модель данных,​ логику и агентов,​ объединив их в единое целое — secuiryt-тест . У нас будет только один тест (для фаззинга поля filename), но в реальной ситуации можно написать столько тестов,​ сколько необходимо. По сути, нужен один тест для каждого описанного блока с моделью данных.
 +
 +<Test name="​tftprrx">​
 +<Agent ref="​RemoteAgent"/>​
 +<​StateModel ref="​state1"/>​
 +<​Publisher class="​udp.Udp">​
 +<Param name="​host"​ value="​192.168.1.10"​ />
 +<Param name="​port"​ value="​69"​ />
 +</​Publisher>​
 +</​Test>​
 +
 +После "​publisher"​ указывается,​ каким образом будут передаваться данные. Поскольку TFTP работает по UDP-протоколу,​ то его мы и используем при составлении теста. Последний блок, который необходимо изменить в файле-шаблоне — это блок для запуска фаззера ("​Run"​). Здесь определяется,​ куда ты хочешь сохранить логи с результатами и какие тесты хочешь провести:​
 +
 +<Run name="​DefaultRun">​
 +<Logger class="​logger.Filesystem">​
 +<Param name="​path"​ value="​logs"/>​
 +</​Logger>​
 +<Test ref="​tftprrx"/>​
 +</​Run>​
 +</​Peach>​
 +
 +Составление "​косточек"​ для Peach'​а может показаться непростой задачей,​ и это действительно так. А как иначе объяснить фаззеру особенности формата данных и то, каким образом ему эффективнее играться с теми или иными параметрами?​ В этом и есть смысл умного фаззинга. С другой стороны,​ если прямо сейчас попробовать реализовать другой метод того же протокола TFTP (скажем,​ метод write), то сразу осознаешь,​ что кода потребуется намного меньше — большая часть XML-конфига уже готова. Специально для проверки корректности PeachPits'​ов в состав фаззера входит специальный скрипт peachvalidator.pyw. Если валидатор отдаст отмашку на старт фаззера,​ можно запускать Peach:
 +
 +peach.py -a
 +peach.py tftpfuzzer.xml
 +
 +Первая команда активирует агентов,​ а вторая позволяет запустить фаззер с использованием только что составленного XML-конфига.
 +
 +Фаззим драйвера
 +
 +Итак, мы уже разобрались с фаззингом файлов,​ протоколов — теперь попробуем использовать фаззинг для поиска ошибок в драйверах. Тут надо понимать,​ что драйверы используются не только для управления устройствами,​ вовсе нет. Многие программы устанавливают в систему драйвер в качестве посредника для доступа в более привилегированный режим — Ring0. Прежде всего, это антивирусы и утилиты,​ обеспечивающие (по крайней мере, обещающие обеспечить) безопасность системы. Драйверы,​ в общем, ничем не отличаются от программы в плане безопасности:​ как и везде, большое количество уязвимостей связано с неправильной обработкой данных,​ в особенности тех, что поступают в IRP-запросах. I/O request packets (IRP) — это специальные структуры,​ использующиеся моделью драйверов Windows для взаимодействия и обмена данными драйверов друг с другом и самой системой. Получается,​ и здесь есть все условия для того, чтобы автоматизировать поиск уязвимостей. Конечно,​ инструмент тут нужен совершенно особенный,​ потому как обычным фаззерам доступ в недра системы закрыт.
 +
 +Одна из немногих разработок в этой области — IOCTL Fuzzer , которая изначально нацелена на проведение fuzzing-тестов,​ манипулируя с данными в IRP-запросах. Программа устанавливает в систему вспомогательный драйвер (не удивляйся,​ что подобную активность антивирус посчитает подозрительной),​ который перехватывает вызовы NtDeviceIoControlFile,​ тем самым получая возможность контролировать все IRP-запросы от любого приложения к драйверам режима ядра. Это нужно потому,​ что изначально формат IRP-запроса для конкретного драйвера или программы неизвестен. А имея на руках перехваченный IRP-запрос,​ его можно легко изменить — получается классический фаззинг с помощью мутации. Проспуфенный IRP-запрос ничем не отличается от оригинального за исключением поля с данными,​ которые заполняется фаззером псевдослучайным образом. Поведение фаззера,​ лог-файл,​ названия драйверов для спуфинга и другие параметры задаются с помощью простейшего XML-конфига,​ который находится в корне программы. Но прежде чем рваться в бой, необходима некоторая подготовка.
 +
 +Из эксперимента с драйверами на рабочей машине ничего хорошего не выйдет. Если IOCTL Fuzzer удастся нащупать слабое место в каком-нибудь из драйверов,​ то система легко улетит в BSOD, а это едва ли прибавит удобства для идентификации уязвимости . По этой причине для использования фаззера нам понадобится отдельная виртуальная машина,​ к которой мы подключим удаленный дебаггер ядра. Тут честь и хвала Microsoft, которые не только смогли сделать толковый отладчик WinDbg, поддерживающий удаленный дебаггинг,​ но и распространяют его бесплатно. Взаимодействие между гостевой системой в VMware и удаленным отладчиком WinDbg осуществляется с помощью именованного канала (named pipe), который мы сейчас и создадим.
 +
 +1. Сначала создаем именованный канал в VMware. Для этого переходим в меню "​Settings „p Configuration Editor",​ нажимаем на кнопку добавить оборудование ("​Add"​),​ выбираем "​Serial Port", жмем "​Next",​ далее из списка выбираем тип порта — "Use named pipe" и оставляем дефолтное название для именованного канала (\\.\pipe\com_1). После этого задаем режим работы "This end is server. The other end is application"​ в двух выпадающих полях и напоследок нажимаем кнопку "​Advanced",​ где активируем опцию "Yiled CPU on poll" (иначе ничего не заработает).
 +
 +Осталось реализовать возможность загрузки гостевой системы с включенным режимом удаленной отладки. Для этого в boot.ini (будем считать,​ что в качестве гостевой системы используется Windows XP) необходимо вставить новую строку для запуска системы,​ добавив два важных ключа /debugport и /baudrate:
 +
 +[operating systems]
 +multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="​Microsoft Windows XP Professional"​ /fastdetect
 +multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="​Microsoft Windows XP Professional - Debug" /fastdetect /​debugport=com1 /​baudrate=115200
 +
 +Во время следующей перезагрузки необходимо в загрузчике выбрать ту версию системы,​ для которой мы включили режим отладки. Остается настроить сам отладчик,​ но для этого нужно лишь во время запуска передать ему параметры именованного канала:​
 +
 +windbg -b -k comipe,​port=\\.\pipe\com_1,​resets=0
 +
 +Вот теперь можно запускать IOCTL Fuzzer в режиме фаззинга,​ не опасаясь BSOD’а на основной системе. Выполняем произвольные манипуляции с тестируемым ПО до тех пор, пока отладчик не сообщит нам о возникновении необрабатываемого исключения (это значит,​ что в обычных условиях,​ скорее всего, это закончилось бы аварийным завершением работы системы).
 +
 +Далее необходимо возобновить выполнение кода на виртуальной машине (в случае с WinDbg надо просто нажать F5), после чего ОС, работающая на виртуальной машине,​ запишет аварийный дамп (crash dump) на диск. Готово:​ теперь у нас есть подробные логи, дамп и сам запрос,​ который привел к падению. Дело за малым — понять,​ как это можно эксплуатировать .
 +
 +А как же веб-фаззеры?​
 +
 +Я намеренно не стал упоминать в рамках этой статьи так называемые web-based фаззеры,​ которые работают на уровне HTTP и заваливают веб-сервер специально составленными запросами в поиске ошибок веб-приложения. Такая опция есть в каждом втором сканере веб-безопасности,​ которые мы не так давно рассматривали в рамках цикла "​Инструменты пентестера ". Если говорить об универсальных платформах для создания фаззеров,​ то грех не вспомнить о фреймворке Sulley , представленном на Blackhat'​е в 2007 году. К сожалению,​ с тех самых пор он и не развивается,​ но несмотря на это остается эффективным решением.
 +
 +Каждый отдельный фаззер с его помощью конструируется отдельно,​ но в отличие от Peach, где все описывается декларативно в XML-файле,​ здесь тебе придется написать немного кода на Python. Есть еще один популярный конструктор фаззеров — проект SPIKE , но подружиться с ним смогут только те, кто хорошо знает язык C. Помимо этого можно было долго говорить о фаззерах для поиска уязвимостей в ActiveX, COM-объектах и где угодно еще. Но это не главное. Важно понять,​ что во многих местах поиск уязвимостей можно автоматизировать:​ именно с помощью фаззинга находится большое количество багов в современных браузерах и смежных с ними продуктов. А если есть понимание того, где может быть выявлена ошибка и как ее искать,​ то фаззер уже несложно написать самому или подобрать готовое решение.
 +
 +                                                                                                Автор: <​STEP> ​
что_такое_фаззинг.txt · Последние изменения: 2013/09/02 17:33 — 81.222.241.194