Fuzzing. Технология охоты за багами
Современные приложения просто кишат уязвимостями различного рода: переполнение буфера, утечки памяти, плохое шифрование, недостаточная проверка входных данных и прочее. И это не удивительно, ведь большое число программного обеспечения пишется для получения прибыли, причем мало кто заботится о безопасности своего детища, выпуская на рынок дырявые приложения. Самое парадоксальное то, что затраты на постоянные обновления этих самых ошибок приравниваются почти к одной третьей дохода от продаж, а иногда и больше, не говоря уже об испорченной репутации. Взять ту же Microsoft. Посмотрите на любые bug-траки, там можно найти кучу самых разнообразных багов, их описания и эксплоиты к ним. И недобросовестные дяди этим пользуются, получая возможность эксплуатировать эти самые недоработки разработчиков для написания вредоносного кода. Чтобы не допустить подобного безобразия у нас, я хочу в рамках этой статьи рассмотреть давно известную на Западе и перспективную технологию поиска ошибок - фаззинг. О ней, кстати, как об одном из этапов SDL, говорилось на недавно прошедшей конференции Microsoft, отчет о котором недавно публиковался на страницах Компьютерной Газеты.
Интро
Прежде всего посетим Википедию, чтобы определится с теорией. Итак, фаззинг (Fuzzing) - технология тестирования программного обеспечения, когда вместо ожидаемых входных данных программе передаются случайные или специально сформированные данные. В большинстве своем это некорректно составленные данные. Смысл такой проверки сводится к тому, что программист не знает, какие данные будут переданы приложению/протоколу/функции, поэтому его задача предусмотреть и проверить как можно больше вариантов.
Данные передаются на вход программным интерфейсам, включающим:
– Файлы,
– Сетевые порты,
– API.
В случае если программа зависает или аварийно завершает работу, это считается нахождением дефекта в программе, который может привести к обнаружению определенной уязвимости. Самым простым примером может служить переполнение буфера. Умный злоумышленник может составить грамотный запрос, содержащий вредоносный код и данные, которые вызовут переполнение. Причем приложение может и не завершить свою работу, но обязательно выполнит код. Та же самая ситуация складывается и с обработкой данных из файлов и протоколов, обработкой передаваемых параметров функции и прочим. Примером неверной обработки файлов служит найденные мелко-мягкими с помощью фаззинга ошибки в файлах XLS, PPT, DOC и BMP. И это неудивительно, ведь синтаксический анализ сложных структур данных – задача не из легких, сложный код наверняка будет иметь ошибки, и некоторые из этих ошибок могут вылиться в уязвимости безопасности. Именно такие участки кода, занимающиеся анализом каких-либо данных, должны быть проверены в первую очередь. Хотите живой пример? ОК, тогда посмотрим баг-трак за 08.10.2009 на xakep.ru. Находим первую уязвимость ( сайт ) и читаем ее описание: «Уязвимость позволяет удаленному злоумышленнику выполнить произвольный код на целевой системе. Уязвимость существует из-за ошибки в проверке входных данных при обработке содержимого AVI-файлов и заголовков AVI-файлов. Атакующий может передать специально сформированные файлы, что приведет к выполнению произвольного кода». Вот и наглядный пример такой ошибки, которую теоретически можно было устранить путем фаззинга. Что же там неправильно обрабатывается, можно посмотреть в эксплоите, который есть на страничке с описанием уязвимости (смотрим ссылку выше).
Фаззинг по своей сути является динамической технологией тестирования безопасности. Под статической технологией я подразумеваю любые программные средства, которые производят тестирование кода по каким-то определенным шаблонам. Средства статического анализа кода позволяют обрабатывать большее количество кода благодаря автоматизации, но результаты строго ограничены и могут быть ложными, что не есть гуд. Фаззинг же динамичен, он не имеет строгих шаблонов и критериев и может быть просто автоматизирован, выполняясь непрерывно, но он работает случайным образом и может иметь проблемы при работе с более глубокими частями кода. Поэтому наилучшим решением проблемы будет сочетание нескольких этапов проверки исходного кода:
1. Проверка на наличие багов человеком.
2. Проверка средствами статического анализатора.
3. Фаззинг.
Такой анализ позволит достичь наиболее качественного результата, но не гарантирует 100% отсутствие ошибок в коде. «Зачем тогда производить такую сложную проверку, если она не дает требуемого результата?» - спросят некоторые. Затем, чтобы не тратить свое время, средства и нервы на закрытие найденных кем-то багов в нашем продукте в будущем. И как говорил мой преподаватель по программированию, «Любая программа содержит хотя бы одну ошибку» ;).
Что касается преимуществ фаззинга, то их довольно-таки много:
. Легко автоматизируется.
. Вызывает выполнения большинства проверок в приложении.
. Находит очень много ошибок.
. Большой объем тестирования с множеством вариаций.
. Находит множество проблем, связанных с надежностью (многие из них являются и потенциальными проблемами безопасности).
На постсоветской территории фаззинг пока широко не практикуется, поэтому специалистов в данном направлении очень мало. Это связано с тем, что у нас не хватает литературы на русском по данной тематике. В конце статьи я приведу названия некоторых книг, которые можно найти на прилавках книжных магазинов или заказать в Интернете. Именно они повысят вашу осведомленность по данной тематике, а она, поверьте, заслуживает не одной книги. А пока приступим к рассмотрению фаззеров.
Программы для фаззинга
Фаззер – средство (приложение или фреймворк), позволяющее проводить автоматизированный фаззинг исходного кода, файлов, приложений и прочего. Проведенный мной поиск в Сети показал, что на момент написания статьи существует не так уж и много фаззеров, доступных для обычных пользователей. В основном существующие фаззеры предназначены для работы с UNIX-системами и приложениями, но и Windows не обошли стороной. Рассмотрим самые востребованные из них:
1. OWASP JBroFuzz
OWASP JBroFuzz – фаззер уязвимостей, работающий с HTTP, SOAP, XML, LDAP и прочими сетевыми протоколами. Данный фаззер поддерживает довольно большое количество самых разнообразных проверок на:
1. межсайтовый скриптинг (Cross Site Scripting - XSS),
2. SQL-инъекции (SQL-inj),
3. переполнения буфера (buffer overflows - BFO),
4. ошибки форматной строки (format string errors - FSE),
5. целочисленное переполнение (integer overflows - INT)
и многие другие уязвимости крайне нестандартными методами. Отличительной особенностью этого фаззера является возможность редактировать содержимое так называемых «генераторов», на основе которых и производится анализ. Скачать и попробовать его в работе можно по ссылке сайт .
2. Bunny the Fuzzer
На небезызвестном среди ИТ-специалистов проекте Google Code можно найти еще один фаззер - Bunny the Fuzzer . Он предназначен для анализа приложений, написанных на C. Работает на уровне компилятора, устанавливая «ловушки» на вызываемые функции, имея возможность исследовать передаваемые параметры и результаты работы. Такой подход позволяет проводить глубокий и последовательный анализ, что положительно отражается на результатах тестирования. Работает под Linux, FreeBSD, OpenBSD и Cygwin. Скачать можно тут - сайт .
3. SPIKE – это попытка написать удобный и универсальный фаззер, предназначенный для тестирования новых и неизвестных сетевых протоколов. Включает в себя тестирование NTLM-аутентификации методом грубой силы, проверку на переполнение буфера, парсер web-приложений и DCE-RPC (MSRPC), а также много другого полезного функционала для профессионального специалиста по тестированию безопасности. Работает только под управление Linux. Скачать можно по ссылке сайт .
4. PFF (Php Fuzzing Framework)
Данная маленькая утилита была разработана с целью поиска ошибок в PHP-коде. Написана на C, работает под управлением unix-based систем. Линк - сайт .
5. ProxyFuzz
Данный фаззер, написанный на Python, предназначен для случайного изменения сетевого трафика, что позволяет тестировать сетевые протоколы. Работает по принципу man-in-the-middle, поддерживает TCP и UDP протоколы (причем можно настроить на фаззинг только определенного протокола). Пример его работы можно найти на сайт , а скачать и самому проверить в работе - сайт .
Существуют и другие фаззеры, например, для анализа XML-файлов или Oracle. Найти их можно по следующим адресам, там же есть и описание, зачем, как и что именно они тестируют:
сайт ,
сайт .
Заключение
Вот я и закончил рассмотрение самых основных понятий, связанных с процессом фаззинга. Если вас заинтересовала эта технология тестирования программного обеспечения, то советую почитать некоторые книги, посвященные ей. Это:
- «The Security Development Lifecycle» (авторы Michael Howard и Steve Lipner) - рассматриваются способы фаззинга исходного кода на C++, средства фаззинга файлов, методика исследования безопасности и прочее;
- «Искусство взлома и защиты систем» (Козиол Дж. Личфилд Д. Эйтэл Д. и другие) – рассмотрены различные способы тестирования самого
разнообразного программного обеспечения, начиная от простых программ и заканчивая операционными системами и базами данных;
- «Fuzzing: исследование уязвимостей методом грубой силы» (Педрам Амини) – рассмотрены все основные принципы фаззинга, способы создания фаззеров и использование уже готовых, а также много чего интересного.
Кстати, о последней книге есть много теплых отзывов от авторитетных западных коллег, что показывает качество изложения материала.
И напоследок я бы хотел процитировать слова Майкла Ховарда: «Если у вас произошел сбой программы, не думайте, что это просто сбой. Вполне вероятно, что некоторая часть так называемых сбоев – это приглашение для злоумышленника написать атакующий код. Не воспринимайте сбой, как "просто сбой"».
Булай Никита, q@sa-sec.org
Интро
Прежде всего посетим Википедию, чтобы определится с теорией. Итак, фаззинг (Fuzzing) - технология тестирования программного обеспечения, когда вместо ожидаемых входных данных программе передаются случайные или специально сформированные данные. В большинстве своем это некорректно составленные данные. Смысл такой проверки сводится к тому, что программист не знает, какие данные будут переданы приложению/протоколу/функции, поэтому его задача предусмотреть и проверить как можно больше вариантов.
Данные передаются на вход программным интерфейсам, включающим:
– Файлы,
– Сетевые порты,
– API.
В случае если программа зависает или аварийно завершает работу, это считается нахождением дефекта в программе, который может привести к обнаружению определенной уязвимости. Самым простым примером может служить переполнение буфера. Умный злоумышленник может составить грамотный запрос, содержащий вредоносный код и данные, которые вызовут переполнение. Причем приложение может и не завершить свою работу, но обязательно выполнит код. Та же самая ситуация складывается и с обработкой данных из файлов и протоколов, обработкой передаваемых параметров функции и прочим. Примером неверной обработки файлов служит найденные мелко-мягкими с помощью фаззинга ошибки в файлах XLS, PPT, DOC и BMP. И это неудивительно, ведь синтаксический анализ сложных структур данных – задача не из легких, сложный код наверняка будет иметь ошибки, и некоторые из этих ошибок могут вылиться в уязвимости безопасности. Именно такие участки кода, занимающиеся анализом каких-либо данных, должны быть проверены в первую очередь. Хотите живой пример? ОК, тогда посмотрим баг-трак за 08.10.2009 на xakep.ru. Находим первую уязвимость ( сайт ) и читаем ее описание: «Уязвимость позволяет удаленному злоумышленнику выполнить произвольный код на целевой системе. Уязвимость существует из-за ошибки в проверке входных данных при обработке содержимого AVI-файлов и заголовков AVI-файлов. Атакующий может передать специально сформированные файлы, что приведет к выполнению произвольного кода». Вот и наглядный пример такой ошибки, которую теоретически можно было устранить путем фаззинга. Что же там неправильно обрабатывается, можно посмотреть в эксплоите, который есть на страничке с описанием уязвимости (смотрим ссылку выше).
Фаззинг по своей сути является динамической технологией тестирования безопасности. Под статической технологией я подразумеваю любые программные средства, которые производят тестирование кода по каким-то определенным шаблонам. Средства статического анализа кода позволяют обрабатывать большее количество кода благодаря автоматизации, но результаты строго ограничены и могут быть ложными, что не есть гуд. Фаззинг же динамичен, он не имеет строгих шаблонов и критериев и может быть просто автоматизирован, выполняясь непрерывно, но он работает случайным образом и может иметь проблемы при работе с более глубокими частями кода. Поэтому наилучшим решением проблемы будет сочетание нескольких этапов проверки исходного кода:
1. Проверка на наличие багов человеком.
2. Проверка средствами статического анализатора.
3. Фаззинг.
Такой анализ позволит достичь наиболее качественного результата, но не гарантирует 100% отсутствие ошибок в коде. «Зачем тогда производить такую сложную проверку, если она не дает требуемого результата?» - спросят некоторые. Затем, чтобы не тратить свое время, средства и нервы на закрытие найденных кем-то багов в нашем продукте в будущем. И как говорил мой преподаватель по программированию, «Любая программа содержит хотя бы одну ошибку» ;).
Что касается преимуществ фаззинга, то их довольно-таки много:
. Легко автоматизируется.
. Вызывает выполнения большинства проверок в приложении.
. Находит очень много ошибок.
. Большой объем тестирования с множеством вариаций.
. Находит множество проблем, связанных с надежностью (многие из них являются и потенциальными проблемами безопасности).
На постсоветской территории фаззинг пока широко не практикуется, поэтому специалистов в данном направлении очень мало. Это связано с тем, что у нас не хватает литературы на русском по данной тематике. В конце статьи я приведу названия некоторых книг, которые можно найти на прилавках книжных магазинов или заказать в Интернете. Именно они повысят вашу осведомленность по данной тематике, а она, поверьте, заслуживает не одной книги. А пока приступим к рассмотрению фаззеров.
Программы для фаззинга
Фаззер – средство (приложение или фреймворк), позволяющее проводить автоматизированный фаззинг исходного кода, файлов, приложений и прочего. Проведенный мной поиск в Сети показал, что на момент написания статьи существует не так уж и много фаззеров, доступных для обычных пользователей. В основном существующие фаззеры предназначены для работы с UNIX-системами и приложениями, но и Windows не обошли стороной. Рассмотрим самые востребованные из них:
1. OWASP JBroFuzz
OWASP JBroFuzz – фаззер уязвимостей, работающий с HTTP, SOAP, XML, LDAP и прочими сетевыми протоколами. Данный фаззер поддерживает довольно большое количество самых разнообразных проверок на:
1. межсайтовый скриптинг (Cross Site Scripting - XSS),
2. SQL-инъекции (SQL-inj),
3. переполнения буфера (buffer overflows - BFO),
4. ошибки форматной строки (format string errors - FSE),
5. целочисленное переполнение (integer overflows - INT)
и многие другие уязвимости крайне нестандартными методами. Отличительной особенностью этого фаззера является возможность редактировать содержимое так называемых «генераторов», на основе которых и производится анализ. Скачать и попробовать его в работе можно по ссылке сайт .
2. Bunny the Fuzzer
На небезызвестном среди ИТ-специалистов проекте Google Code можно найти еще один фаззер - Bunny the Fuzzer . Он предназначен для анализа приложений, написанных на C. Работает на уровне компилятора, устанавливая «ловушки» на вызываемые функции, имея возможность исследовать передаваемые параметры и результаты работы. Такой подход позволяет проводить глубокий и последовательный анализ, что положительно отражается на результатах тестирования. Работает под Linux, FreeBSD, OpenBSD и Cygwin. Скачать можно тут - сайт .
3. SPIKE – это попытка написать удобный и универсальный фаззер, предназначенный для тестирования новых и неизвестных сетевых протоколов. Включает в себя тестирование NTLM-аутентификации методом грубой силы, проверку на переполнение буфера, парсер web-приложений и DCE-RPC (MSRPC), а также много другого полезного функционала для профессионального специалиста по тестированию безопасности. Работает только под управление Linux. Скачать можно по ссылке сайт .
4. PFF (Php Fuzzing Framework)
Данная маленькая утилита была разработана с целью поиска ошибок в PHP-коде. Написана на C, работает под управлением unix-based систем. Линк - сайт .
5. ProxyFuzz
Данный фаззер, написанный на Python, предназначен для случайного изменения сетевого трафика, что позволяет тестировать сетевые протоколы. Работает по принципу man-in-the-middle, поддерживает TCP и UDP протоколы (причем можно настроить на фаззинг только определенного протокола). Пример его работы можно найти на сайт , а скачать и самому проверить в работе - сайт .
Существуют и другие фаззеры, например, для анализа XML-файлов или Oracle. Найти их можно по следующим адресам, там же есть и описание, зачем, как и что именно они тестируют:
сайт ,
сайт .
Заключение
Вот я и закончил рассмотрение самых основных понятий, связанных с процессом фаззинга. Если вас заинтересовала эта технология тестирования программного обеспечения, то советую почитать некоторые книги, посвященные ей. Это:
- «The Security Development Lifecycle» (авторы Michael Howard и Steve Lipner) - рассматриваются способы фаззинга исходного кода на C++, средства фаззинга файлов, методика исследования безопасности и прочее;
- «Искусство взлома и защиты систем» (Козиол Дж. Личфилд Д. Эйтэл Д. и другие) – рассмотрены различные способы тестирования самого
разнообразного программного обеспечения, начиная от простых программ и заканчивая операционными системами и базами данных;
- «Fuzzing: исследование уязвимостей методом грубой силы» (Педрам Амини) – рассмотрены все основные принципы фаззинга, способы создания фаззеров и использование уже готовых, а также много чего интересного.
Кстати, о последней книге есть много теплых отзывов от авторитетных западных коллег, что показывает качество изложения материала.
И напоследок я бы хотел процитировать слова Майкла Ховарда: «Если у вас произошел сбой программы, не думайте, что это просто сбой. Вполне вероятно, что некоторая часть так называемых сбоев – это приглашение для злоумышленника написать атакующий код. Не воспринимайте сбой, как "просто сбой"».
Булай Никита, q@sa-sec.org
Компьютерная газета. Статья была опубликована в номере 42 за 2009 год в рубрике безопасность