Фаззинг-тестирование для повышения безопасности ПО

Фаззинг-тестирование для повышения безопасности ПО


Апрель 27, 2023


В одной из предыдущих статей мы говорили о нормативных требованиях к обеспечению безопасности на протяжении всего жизненного цикла ПО. Важная процедура контроля безопасности — фаззинг-тестирование. В этой статье мы разберем, что такое фаззинг, где он применяется и как повысить его эффективность.

  1. Что такое фаззинг-тестирование
  2. Когда следует применять фаззинг
  3. Рекомендации по проведению фаззинга
  4. Как повысить эффективность фаззинга
  5. Плюсы, минусы и подводные камни фаззинга
  6. Заключение

Что такое фаззинг-тестирование

Фаззинг — это процесс автоматического тестирования программного кода, который заключается в генерации разнообразных входных данных с целью поиска ошибок в коде. В рамках тестирования на вход передается большое количество образцов случайных данных, и каждый образец, число которых может доходить до миллиарда, запускается для проверки кода отдельно.

У процедуры фаззинг-тестирования две главных цели:

  • Формирование набора образцов входных данных, которые позволяют выполнить наибольшее количество фрагментов кода, повышая тестовое покрытие.
  • Мутирование входных данных так, чтобы они не соответствовали ограничениям и гипотетически могли вызывать недекларированное поведение. Недекларированное поведение возникает, когда из-за ошибки результат вычислений получается совсем не таким, какого ожидал разработчик.

Для фаззинга подойдут любые «экстремальные» случаи, которые, с одной стороны, укладываются в ограничения, а с другой не предусмотрены разработчиком специально. Именно обработка таких входных данных интересна для верификации надлежащей работы программы.

В настоящее время фаззинг — один из самых эффективных методов динамического тестирования, которому посвящено множество научных исследований и конференций. В современной практике тестирования ПО фаззинг является ключевой технологией автоматической валидации сложных программных продуктов.

Когда следует применять фаззинг

Фаззинг особенно актуален, когда для программного продукта разработан интерфейс, принимающий на вход пользовательские данные (например, форму с полями для ввода текста или возможностью загрузки файла).

Обычно фаззинг используется для проверки корректности работы парсера входных данных. Парсеры могут иметь внутри сложную логику и множество ветвлений, поэтому их важно хорошо протестировать. Однако с помощью фаззинга можно проверять корректность работы почти любого кода, обрабатывающего входные данные, даже если они поступают не от внешнего интерфейса.

Есть и кейсы, когда применение фаззинга не обосновано. Такой метод тестирования обычно не актуален для простых функций, например, с единственным аргументом типа bool. Но в более сложных случаях его так или иначе можно применять.

Рекомендации по проведению фаззинга

Ниже приведены несколько простых советов для успешного выполнения фаззинг-тестирования:

  1. Используйте мутационный фаззинг, учитывающий покрытие при обработке каждого образца. Каждый из образцов мутируется отдельно. Это можно сделать с помощью инструментирования на этапе компиляции целевого кода или эмулятора.
  2. Определите функции в коде, использующиеся для обработки входных данных, чтобы учитывать покрытие и применять детекторы ошибок только в этих функциях.
  3. Зафиксируйте формат входных данных для фаззинга.
  4. Создайте обертку для передачи данных от фаззера в парсер. Оптимизируйте ее так, чтобы она работала максимально быстро.
  5. Создайте набор входных данных, удовлетворяющих ограничениям и формату, чтобы откалибровать фаззер и создавать новые образцы.
  6. Используйте словари для генерации новых входных данных. Словари позволяют задать «контекст грамматики» для генератора входных данных. Например, они могут содержать образцы значений определенных полей в сложной структуре данных.
  7. Выполняйте фаззинг параллельно на всех ядрах процессора с использованием кластера фаззеров.

Как повысить эффективность фаззинга

Несколько факторов делают фаззинг более эффективным:

  1. Использование отклика от тестируемой программы, благодаря чему мутирование образцов входных данных будет выполняться не «вслепую», а с учетом результатов обработки предыдущих образцов. Это позволяет достигнуть большего покрытия по строкам кода.
  2. Использование санитайзеров ошибок для обнаружения опасных мест, которые не приводят к аварийному завершению работы программы, но могут быть источником серьезной проблемы, вплоть до уязвимостей безопасности.
  3. Быстрое выполнение фаззинга, что повышает шансы обнаружить что-то интересное.
  4. Генерация входных данных с учетом формата входных данных, что сокращает количество «холостых» итераций фаззинга, когда входные данные не проходят первый этап проверки.
  5. Определение информации о покрытии только интересующего нас кода.
  6. Хорошая стабильность: при сборе покрытия от каждой итерации следует по возможности не учитывать все источники энтропии. Например, можно не учитывать генераторы случайных чисел. Это важно, ведь при низкой стабильности теряется эффективность во время работы по отклику о покрытии.

Плюсы, минусы и подводные камни фаззинга

Одно из основных преимуществ фаззинга — возможность автоматически находить ошибки в сложном коде с большим количеством ветвлений. Фаззинг может обнаружить ошибки, которые почти невозможно обнаружить при ручном и статическом анализе. Второе преимущество заключается в том, что после этапа начальной подготовки расходуется только машинное время, а это гораздо дешевле, чем если бы ту же работу вручную выполняла команда разработчиков.

Однако у этой методики есть и недостатки. Основной минус заключается в том, что для фаззинга необходимы специалисты, обладающие высоким уровнем экспертности. Специалист должен хорошо понимать особенности тестируемого продукта, разбираться в компьютерной безопасности, низкоуровневой работе программного кода и его компиляции и даже нюансах работы операционных систем. Наконец, при внедрении фаззинг-тестирования стоит учитывать затраты на аппаратные ресурсы.

Подводные камни варьируются в зависимости от языка программирования, на котором написан тестируемый код. Например, при работе с C/C++ могут возникать проблемы, связанные с несовместимостью существующей системы сборки с инструментирующим компилятором. На этапе линковки в объектных и исполняемых файлах могут появляться неопределенные (undefined) символы. Это происходит по разным причинам: от использования неподходящего набора утилит для компиляции до использования некорректных линковочных map-файлов в системе сборки или установки разных уровней видимости в программном коде.

Работа санитайзеров ошибок может мешать корректной работе тестируемого кода. Источники энтропии могут создавать проблемы со стабильностью. А если компоненты кода сильно связаны, это может усложнить отделение тестируемого кода от всего остального проекта.

Заключение

Несмотря на то, что фаззинг — это сложная, требующая высокой квалификации процедура с высоким порогом входа, ее преимущества стоят затраченных усилий на ее внедрение. Команда Axiom JDK активно использует фаззинг при тестировании своих продуктов. Он является важной частью реализации концепции безопасной разработки (Secure Development Lifecycle, SDL), в соответствии с которой разрабатываются все продукты линейки Axiom JDK.

Помимо фаззинга инженеры Axiom JDK проводит множество других испытаний, гарантирующих качество и безопасность всех сборок. Также мы предоставляем дополнительные функции безопасности для наших клиентов, такие как доверенный репозиторий с проверенными исходным кодами самых популярных Java библиотек, российские TLS-сертификаты, выпущенные Минцифры, экстренные патчи безопасности и техподдержку 24/7 на русском языке.

Более того, в линейку продуктов Axiom JDK входит Axiom JDK Certified, среда исполнения Java, сертифицированная ФСТЭК по 4 уровню доверия (УД), что позволяет обезопасить приложения на ее основе и упростить процесс их сертификации в соответствии с нормативными требованиями.

С нами вы можете быть уверены в безопасности среды исполнения ваших приложений. Свяжитесь с нами: наши инженеры расскажут про продукты Axiom JDK, предоставляют демо-версию и помогут с миграцией.

Присоединяйтесь к нашему Telegram-каналу, чтобы оставаться в курсе новостей из мира Java.

Author image

Олег Чирухин

Директор по коммуникациям с разработчиками (DevRel)

Команда Axiom JDK roman.karpov@axiomjdk.ru Команда Axiom JDK logo Axiom Committed to Freedom 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67 Команда Axiom JDK 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67