TL; DR: QuickCheck для быстрого тестирования функций со случайными значениями в составе набора тестов. Фузеры (основанные на модели или мутации) требуют больше времени для запуска и лучше всего используются для интерфейсов программного обеспечения, обращенных к миру, таких как анализаторы файлов или протоколов. QuickCheck и фаззеры вводят случайные и обычно неверные данные. Какой использовать? Рассмотрите возможность использования обоих.

Этот текст основан на том, что я написал в / r / rust.

QuickCheck для быстрой проверки

QuickCheck (я использовал Haskell one, но у многих языков есть свои особенности) использует систему типов языка программирования для определения своего входного пространства. Для каждого целого числа попробуйте целые числа. Для логического попробуйте логические. Для струнных попробуйте струны. И это не ограничивается примитивными типами. Списки, массивы, структуры, векторы, типы продуктов, типы сумм и т. Д. Получили признание в QuickCheck.

QuickCheck может применяться ко многим функциям внутри программы. Он использует инварианты (логические свойства, которые должны применяться всегда) для вынесения вердикта. Например, рассмотрим reverse(reverse(list)) == list, который, как мы надеемся, всегда верен. В этом случае для списков QuickCheck пробует пустой список, список с одним элементом, список с несколькими элементами и, возможно, список с большим количеством элементов. Сколько юнит-тестов вы бы написали для этого? QuickCheck уже позаботился о вас.

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

QuickCheck лучше всего использовать как часть набора тестов проекта и должен выполняться довольно быстро. Думайте о секундах или минутах, а не о часах или днях. Хорошо подходит для тестирования каждого коммита в непрерывной интеграции.

Фаззинг предназначен для тех мест, где требуется, чтобы обезьяны ударяли по клавиатуре.

Фаззеры обычно лучше всего использовать в интерфейсах программного обеспечения, обращенных к миру. У вас есть библиотека для разбора файлового формата? Используйте фаззер в функции синтаксического анализатора. Сетевой протокол? Используйте фаззер для проверки конечного автомата протокола. Что общего у парсеров файлов и парсеров сетевых протоколов? Их ввод - байтовые строки.

Поскольку ввод можно рассматривать как набор байтов, фаззеру нужен способ уменьшить пространство ввода для тестирования. Один байт может иметь 256 различных значений, два байта - 65536, а 10 байтов - это уже более 10²⁴ значений. Невозможно проверить все возможные значения, поэтому необходим разумный способ их уменьшения.

Фаззеры можно разделить на две категории: основанные на моделях и основанные на мутациях. Оба пытаются решить проблему с входным пространством.

Фаззеры на основе моделей

Фаззер на основе модели знает формат. Например, фаззер PNG-файлов знает структуру и семантику PNG-файла и, таким образом, может создавать допустимые и недопустимые PNG-файлы из воздуха.

Фаззер на основе модели требует, чтобы кто-то построил модель, но тогда модель может содержать полезные вещи, такие как вычисление длины строк или более сложные вещи, такие как конечные автоматы всего сетевого протокола. Также возможно применять уровни криптографии, производить расчеты контрольной суммы и т. Д., Так что такие протоколы, как TLS или IPsec, сильно выигрывают от этого (помните Heartbleed?).

Фаззер на основе модели может быть применен и к черному ящику. Нет необходимости в исходном коде программного обеспечения или его компиляции с некоторыми флагами или библиотеками. Просто веб-сервер с открытым портом, запустите фаззер TLS и начните тестирование.

Фаззеры на основе мутаций

Фаззер на основе мутаций берет входные образцы (например, допустимые файлы PNG) и начинает применять мутации к данным. Переключайте бит здесь и там, меняйте байты с одного значения на другое. Отбрасывать байты, дублировать байты и т. Д. Также фаззер может попытаться изучить модель по входным выборкам. Одним из примеров этого является фаззер под названием Radamsa (Github).

В файле есть контрольная сумма? Нет изменений для фаззера на основе мутаций, чтобы получить правильную контрольную сумму. Он не знает, что это контрольная сумма. Однако что круто в фаззерах на основе мутаций, так это невысокие затраты (как по времени, так и по труду) на подготовку и запуск тестирования. Имейте несколько входных файлов, создайте функцию для анализа файлов и запустите фаззер. Это не займет много времени, и вы сможете начать собирать приятные результаты.

Фаззеры на основе мутаций (такие как AFL и libfuzzer LLVM) имеют инструменты, скомпилированные внутри тестируемого программного обеспечения, поэтому фаззер может видеть, как программа ведет себя внутри. Если мутация нашла новый путь выполнения, стоит проверить ее еще раз. Если мутация не привела к появлению новых путей, возможно, на это не стоит тратить время. Запустите фаззер на основе мутаций в течение длительного времени, и он может создать допустимый файл PNG при тестировании парсера PNG.

Простой пример использования libfuzzer можно найти в проекте OUSPG libfuzzerification.

Инструменты в фаззинге

Теперь, как узнать, обнаружил ли фаззер проблему и когда? Один из способов - посмотреть на тестируемую цель со стороны и понаблюдать за ней. Он разбился? Это потребляло слишком много ресурсов процессора или памяти? В основном фаззеры ищут сбои, потому что они плохие и их легко наблюдать. Сначала выберите низко висящие плоды. Но с помощью таких инструментов, как LLVM Sanitizers (AddressSanitizer, MemorySanitizer, LeakSanitizer, чтобы связать некоторые из них) или различные инструменты Valgrind, можно использовать для поиска утечек памяти, неопределенного поведения и т. Д.

Поскольку входное пространство для фаззинга очень велико, фаззерам лучше оставить работать как можно дольше. Часы или даже дни. После нескольких дней работы оставьте компьютер на ночь для выполнения фазз-тестирования вашего проекта. Кластеры компьютеров, выполняющие фаззинг 24/7, используются в некоторых местах (например, oss-fuzz от Google).

Состояние искусства Fuzzing

Мы собрали Fuzzing State of the Art в ходе одного мозгового штурма прошлым летом (OUSPG Open 2016–06–28). В основном это списки терминов, но они могут быть полезны вместе с поиском в Google и другими ресурсами. Вы можете найти его в Fuzzing SOTA OUSPG.

Вывод

Если вы дочитали до этого места, прокрутите назад и прочтите TL; DR еще раз. :)