🌍 English | Русский
Набор утилит для автоматизации фаззинг-тестирования.
Цели BugBane:
- Упрощение пайплайна CI-фаззинга путём обобщения типичных этапов тестирования и стандартизации конечных артефактов.
- Выполнение фаззинга в эффективной конфигурации с учётом лучших практик.
- Генерация отчётных материалов в соответствии с реально выполняемыми действиями.
Возможности BugBane:
- Сборка приложений для фаззинг-тестирования, в том числе с санитайзерами и покрытием: AFL++, libFuzzer.
- Фаззинг сборок с использованием AFL++, libFuzzer (включая Atheris), dvyukov/go-fuzz, go test на заданном количестве ядер до заданного условия остановки.
- Синхронизация тестовых примеров между рабочей директорией фаззера и хранилищем. Включает отсеивание дубликатов и минимизацию на основе инструментов фаззера.
- Сбор покрытия тестируемого приложения на семплах, полученных в процессе фаззинг-тестирования, а также генерация HTML-отчётов о покрытии (lcov, go tool cover).
- Воспроизведение падений и зависаний, обнаруженных фаззером. Определение места возникновения ошибки и отсеивание дубликатов: C/C++, C#, Go, Python.
- Отправка сведений о воспроизводимых багах в систему управления уязвимостями: Defect Dojo.
- Получение скриншотов работы фаззера и главной страницы отчёта о покрытии исходного кода.
- Генерация отчётов на основе шаблонов Jinja2.
Утилиты BugBane связаны между собой, но использовать их вместе совсем не обязательно.
UNIX-подобная ОС
Python >= 3.6
Зависимости, используемые утилитами BugBane:
bb-build: компиляторы используемого фаззера в PATH (afl-g++-fast, clang, ...).
bb-corpus: утилита минимизации в соответствии с используемым фаззером в PATH (afl-cmin, ...).
bb-fuzz: используемый фаззер в PATH (afl-fuzz, go-fuzz, ...).
bb-coverage: используемые средства сбора покрытия в PATH (lcov, genhtml, go, ...).
bb-reproduce: утилита timeout
, отладчик gdb
.
bb-send: -.
bb-screenshot, bb-report: приложения ansifilter
и pango-view
в PATH, приложение geckodriver
в PATH и браузер Firefox (необязательно, только для Selenium), шрифты mono
(могут отсутствовать в базовых образах Docker).
Примечания:
- скриншоты покрытия с Selenium выглядят лучше, чем с WeasyPrint, но требуют установку браузера Firefox и geckodriver;
- скриншоты покрытия для Go требуют использовать Selenium, потому что Go встраивает в отчёты JavaScript;
- для просмотра отчётов непосредственно в образе Docker с помощью утилит типа less может потребоваться установка локали с поддержкой UTF-8 и указание переменной LANG.
Установить пакет можно локально с помощью pip:
git clone https://github.com/gardatech/bugbane
cd bugbane
pip install .[all]
Проверить выполнение тестов:
pytest
Дополнительные инструкции
Вместо "all" доступны другие группы, позволяющие установить только необходимые Python-зависимости:
Группа pip install | Фаззинг* | Заведение багов в Defect Dojo | Отчёты и скриншоты | Тестирование BugBane | Разработка BugBane |
---|---|---|---|---|---|
- | + | - | - | - | - |
dd | + | + | - | - | - |
reporting | + | - | + | - | - |
test | + | - | - | + | - |
all | + | + | + | + | - |
dev | + | + | + | + | + |
* Выполнение сборок, фаззинг, работа с семплами, сбор покрытия и воспроизведение багов.
Таким образом, можно разделить тестирование и работу с его результатами на разные хосты worker
и reporter
:
pip install . # worker
pip install .[dd,reporting] # reporter
Результат: на хосте worker
не требуются зависимости для генерации отчётов, на хосте reporter
не требуется окружение для запуска тестируемых приложений и фаззеров.
Для удаления использовать следующую команду:
pip uninstall bugbane
Рекомендуется использовать BugBane в среде Docker.
Подразумевается последовательный запуск инструментов в определённом порядке, например:
- bb-build
- bb-corpus (import)
- bb-fuzz
- bb-coverage
- bb-reproduce
- bb-corpus (export)
- bb-send
- bb-report
При этом этап №1 является опциональным, покольку сборки могут быть выполнены другими способами, а этапы №7 и №8 могут выполняться в отдельном образе Docker или на отдельной машине.
Большинство инструментов BugBane работают с конфигурационным файлом bugbane.json: получают входные переменные, обновляют их значения и добавляют новые переменные в существующий файл конфигурации.
Пример исходного файла конфигурации, достаточного для последовательного запуска всех инструментов BugBane
{
"fuzzing": {
"os_name": "Arch Linux",
"os_version": "Rolling",
"product_name": "RE2",
"product_version": "2022-02-01",
"module_name": "BugBane RE2 Example",
"application_name": "re2",
"is_library": true,
"is_open_source": true,
"language": [
"C++"
],
"parse_format": [
"RegExp"
],
"tested_source_file": "re2_fuzzer.cc",
"tested_source_function": "TestOneInput",
"build_cmd": "./build.sh",
"build_root": "./build",
"tested_binary_path": "re2_fuzzer",
"sanitizers": [
"ASAN", "UBSAN"
],
"builder_type": "AFL++LLVM",
"fuzzer_type": "AFL++",
"run_args": null,
"run_env": null,
"timeout": null,
"fuzz_cores": 16
}
}
Утилиты corpus, coverage, reproduce и report поддерживают альтернативный режим запуска (manual run mode), утилита screenshot работает только в этом режиме. Режим запуска manual предназначен для более тонкой настройки параметров или для использования отдельно от других инструментов BugBane.
Создаёт сборки тестируемого приложения с использованием компиляторов фаззера.
Инструмент предназначен только для C/C++, цели go-fuzz и go-test не поддерживаются.
Пример запуска:
bb-build -i /src -o /fuzz
При этом директория /src должна содержать файл bugbane.json.
В результате в пути /fuzz появляются папки с полученными сборками, например: /fuzz/basic, /fuzz/asan, /fuzz/coverage. Также в папке /fuzz сохраняется журнал выполнения всех сборок с указанием команд запуска и использованных переменных окружения.
Подробности о работе bb-build
На вход инструменту подаются:
- Исходный код тестируемого приложения
- Команда или скрипт сборки
- Файл с переменными bugbane.json
В файле bugbane.json должны быть заданы переменные: builder_type
, build_cmd
, build_root
, sanitizers
.
Команда, указанная в переменной build_cmd
, должна учитывать значения переменных окружения CC, CXX, LD, CFLAGS, CXXFLAGS, LDFLAGS и при запуске выполнять сборку тестируемого компонента в режиме фаззинг-тестирования. После выполнения одного запуска команды build_cmd
в папке build_root
должна оказаться сборка тестируемого приложения. Переменная sanitizers
должна содержать список санитайзеров, с которыми требуется выполнить сборки. Для каждого санитайзера BugBane выполняет отдельную сборку.
Приложение последовательно выполняет несколько сборок (с различными санитайзерами + для сбора покрытия + дополнительные сборки для фаззинга) и после каждой сборки сохраняет результаты сборки из папки build_root
в папку, указанную аргументом запуска -o
. При этом обновляются некоторые переменные в файле bugbane.json (в частности, sanitizers
- заполняется названиями санитайзеров, для которых удалось выполнить сборку).
Пример скрипта, путь к которому может быть указан в команде сборки build_cmd
:
#!/bin/bash
set -x
export CXX="${CXX:-afl-clang-fast++}"
rm -rf build
mkdir -p build
test -e Makefile && make clean
make -j obj/libre2.a
$CXX $CXXFLAGS --std=c++11 -I. re2/fuzzing/re2_fuzzer.cc /AFLplusplus/libAFLDriver.a obj/libre2.a -lpthread -o build/re2_fuzzer
При использовании подобного скрипта флагами компиляции можно управлять извне с помощью переменных окружения и получать сборки с любыми санитайзерами, с инструментацией для сбора покрытия, с отладочной информацией и т.д.
В таблице показано, в какие папки инструмент bb-build сохраняет результаты сборки
Имя папки | Описание | builder_type |
---|---|---|
basic | Сборка для фаззинга. Это должна быть наиболее производительная сборка: без санитайзеров, без покрытия | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
gofuzz | Сборка для фаззинга с использованием dvyukov/go-fuzz (zip-архив). Не поддерживается bb-build, поддерживается остальными утилитами | - |
gotest | Сборка для фаззинга, скомпилированная с помощью go test . Не поддерживается bb-build, поддерживается остальными утилитами |
- |
laf | Сборка для фаззинга, скомпилированная с переменной окружения AFL_LLVM_LAF_ALL | AFL++LLVM, AFL++LLVM-LTO |
cmplog | Сборка для фаззинга, скомпилированная с переменной окружения AFL_USE_CMPLOG | AFL++LLVM, AFL++LLVM-LTO |
asan | Сборка для фаззинга с адресным санитайзером (Address Sanitizer) | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
ubsan | Сборка для фаззинга с санитайзером неопределённого поведения (Undefined Behavior Sanitizer) | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
cfisan | Сборка для фаззинга с санитайзером целостности потока выполнения (Control Flow Integrity Sanitizer) | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
tsan * | Сборка для фаззинга с санитайзером потоков (Thread Sanitizer) | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
lsan * | Сборка для фаззинга с санитайзером утечек памяти (Leak Sanitizer). Этот функционал поддерживается адресным санитайзером, но также может использоваться отдельно | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
msan * | Сборка для фаззинга с санитайзером памяти (Memory Sanitizer) | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
coverage | Сборка для получения информации о покрытии | AFL++GCC, AFL++GCC-PLUGIN, AFL++LLVM, AFL++LLVM-LTO, libFuzzer |
* Работоспособность не тестировалась.
Не всегда удобно выполнять сборки с помощью bb-build, например, если сборками и фаззингом занимаются разные люди. Также bb-build не поддерживает автоматические сборки для целей на языке Go.
Далее следуют инструкции, позволяющие обеспечить совместимость собственных сборок и утилит BugBane.
Все сборки рекомендуется выполнять компиляторами фаззера, в том числе сборку для получения информации о покрытии.
Все сборки должны выполняться с отладочной информацией, содержащей сведения о строках исходного кода (-g
для gcc, -g
или -gline-tables-only
- для clang).
Все сборки должны выполняться с флагом -fno-omit-frame-pointer
для получения более точных стеков вызовов в случае обнаружения багов или при ручной отладке.
Если компиляторы фаззера поддерживают переменные окружения для включения санитайзеров (AFL_USE_ASAN и т.д.), то использование этих переменных предпочтительнее ручного указания флагов компиляции.
Сборки следует размещать в папках под соответствующими названиями. Например, если фаззинг запускается из директории /fuzz, то сборка с ASAN должна быть сохранена в папке /fuzz/asan. Сборку, в которой одновременно присутствуют несколько санитайзеров, достаточно разместить в одном экземпляре в любой одной папке для сборки с санитайзером. Например, сборку с ASAN+UBSAN+CFISAN можно разместить в любой из папок: asan, ubsan, cfisan, lsan, tsan или msan - это не снизит эффективность фаззинга и воспроизведения падений. При этом рекомендуется создать несколько копий или символьных ссылок в соответствии с санитайзерами (/fuzz/asan, /fuzz/ubsan, ...).
Если процесс сборки в CI занимает время, сопоставимое с временем фаззинг-тестирования, то можно обойтись единственной сборкой, одновременно включающей инструментацию фаззера, покрытия и санитайзеров. Это негативно скажется на скорости фаззинга, а также создаст дополнительную нагрузку на диск в процессе тестирования, но может быть предпочтительнее выполнения нескольких сборок. Чтобы использовать единственную сборку приложения, скомпилированную одновременно с ASAN и с покрытием, её можно разместить в папке /fuzz/asan, а затем скопировать её (или создать символьную ссылку) в путь /fuzz/coverage.
Перейти в папку тестируемого проекта и выполнить:
go-fuzz-build
Дополнительная информация доступна на странице проекта.
Следующие инструкции относятся ко встроенному фаззеру, появившемуся с выходом go1.18.
Перейти в папку проекта и выполнить:
go test . -fuzz=FuzzMyFunc -o fuzz -c -cover
Вместо FuzzMyFunc следует подставить название любого фаззинг-теста, присутствующего в кодовой базе. Название функции обязано начинаться с "Fuzz" (см. документацию фаззера).
В результате получится исполняемый файл fuzz
с возможностью запуска любого из доступных фаззинг-тестов. Например, если в коде есть тесты FuzzHttp и FuzzJson, то можно выполнить сборку с опцией -fuzz=FuzzHttp
, а в результате можно будет запускать фаззинг как с опцией -test.fuzz=FuzzHttp
, так и с -test.fuzz=FuzzJson
.
Опция сборки -cover
пока не даёт никакого эффекта, поскольку фаззинг и покрытие в Go временно несовместимы. Использование опции необязательно, но позволит не вносить изменения в будущем, когда разработчики Go вернут совместимость фаззинга и покрытия.
Синхронизирует тестовые примеры в рабочей директории фаззера с хранилищем.
Пример импорта входных тестовых примеров перед фаззинг-тестированием:
bb-corpus suite /fuzz import-from /storage
Папка /fuzz в данном случае является рабочей директорией фаззера (содержит bugbane.json), папка /storage - директория хранилища, в которой присутствует папка samples. Папка /storage/samples содержит файлы тестовых примеров.
После фаззинг-тестирования следует добавить новые тестовые примеры в хранилище:
bb-corpus suite /fuzz export-to /storage
Поддержка встроенного фаззера Go (go test) ограничена
Экспорт в хранилище функционирует нормально, а для импорта придётся использовать один из следующих вариантов:
- использовать
bb-corpus manual
и указать выходной директорией папку конкретного фаззинг-теста (out/FuzzXxx) - использовать
bb-corpus suite
, но предварительно определить переменнуюfuzz_in_dir
в конфигурационном файле (как в примере выше: out/FuzzXxx) - копировать семплы другими средствами (rsync, cp)
Подробности о работе bb-corpus
Инструмент поддерживает импорт тестовых примеров из хранилища в папку фаззера и экспорт из папки фаззера в хранилище.
Хранилище является примонтированной папкой и в свою очередь может быть каталогом Samba, NFS и т.д.
Синхронизация происходит в два этапа:
- Копирование (в случае импорта) или перемещение (в случае экспорта) из папки-источника во временную папку без создания дубликатов по содержимому (вычисляются хэш-суммы SHA1).
- Минимизация семплов из временной папки в конечную папку с использованием инструментов фаззера (например, afl-cmin).
В конфигурационном файле bugbane.json должна быть объявлена переменная fuzzer_type
.
Для минимизации с использованием afl-cmin на диске должны присутствовать сборки тестируемого приложения. Наиболее предпочтительной сборкой для минимизации семплов является сборка в папке laf
, т.к. она "различает" больше путей выполнения, но, если она отсутствует, то для минимизации используются другие сборки.
Имена результирующих файлов соответствуют хэш-сумме SHA1 их содержимого. При совпадении имён в конечной папке перезапись не происходит.
Запускает фаззинг тестируемого приложения на указанном количестве ядер, останавливает фаззинг при наступлении указанного условия остановки.
Пример запуска:
FUZZ_DURATION=1800 bb-fuzz --max-cpus $(nproc) suite /fuzz
В результате запускаются несколько экземпляров фаззера в сессии tmux.
Инструмент bb-fuzz будет периодически печатать статистику работы фаззера, пока не обнаружит наступление условия остановки, в данном случае, пока не накопится время работы 1800 секунд (30 минут).
Затем в папку /fuzz/screens будут сохранены дампы (текстовые представления) экранов фаззера. Эти дампы используются на следующих этапах приложениями bb-report или bb-screenshot для создания скриншотов.
Подробности о работе bb-fuzz
Инструмент обнаруживает сборки приложения на диске и распределяет их по разным ядрам процессора.
Алгоритм распределения сборок C/C++:
- сборкам с санитайзерами выделяется по одному ядру;
- вспомогательные сборки (AFL_LLVM_LAF_ALL, AFL_USE_CMPLOG) назначаются на определённую долю от доступных ядер;
- сборка basic (без санитайзеров) занимает остальные ядра;
- сборки для определения покрытия исходного кода в фаззинг-тестировании участие не принимают (см. bb-coverage).
Для Go используется единственная сборка (в папке gofuzz
или gotest
), которая назначается на все доступные ядра.
Для встроенного фаззера go test работа bb-fuzz завершается сразу же, как только будет обнаружен первый баг. Это вызвано особенностями работы фаззера. В случае отсутствия обнаруженных багов работа продолжается до наступления условия остановки.
В конфигурационном файле bugbane.json должны быть определены переменные fuzzer_type
, tested_binary_path
, fuzz_cores
, src_root
, run_args
, run_env
и timeout
. Переменная timeout
указывается в миллисекундах.
На диске должны присутствовать сборки приложения, размещённые в папках, соответствующих названию сборки, точно так же, как их размещает инструмент bb-build.
Также на диске могут присутствовать файлы словарей с расширением ".dict" в папке "dictionaries". Они объединяются в один общий словарь, который передаётся фаззеру при условии поддержки со стороны фаззера.
Доступные значения переменной fuzzer_type
: AFL++, libFuzzer, go-fuzz, go-test. Для фаззинга с помощью SharpFuzz следует указывать значение AFL++, для Atheris - libFuzzer.
Переменная tested_binary_path
содержит путь к тестируемому приложению относительно входной папки (где будет осуществлён поиск сборок). Пример: есть папка "build" с результатом сборки, исполняемый файл "app" сохранён по пути build/test/app, инструмент bb-build последовательно выполнил несколько сборок, каждый раз копируя папку "build" в путь /fuzz, т.е. получились пути /fuzz/basic/test/app, /fuzz/coverage/test/app и т.д. В этом случае переменная tested_binary_path
должна равняться "test/app". Для Atheris tested_binary_path
должна содержать имя исполняемого Python-скрипта, в начале которого присутствует shebang интерпретатора Python (строка запуска интерпретатора, такая как #!/usr/bin/env python3
).
Переменная src_root
не используется напрямую, но без её указания потерпят неудачу утилиты, подлежащие запуску после bb-fuzz.
run_args
- строка с аргументами запуска тестируемого приложения. Переменная может включать последовательность "@@", вместо которой фаззер может подставлять тестовые примеры на вход тестируемой программе.
Для встроенного фаззера Go переменная run_args
обязана содержать опцию запуска -test.fuzz
с указанием конкретного фаззинг-теста, например, -test.fuzz=FuzzHttp
.
run_env
- переменные окружения, которые необходимо установить для запуска тестируемого приложения. Переменная LD_PRELOAD будет автоматически заменена на соответствующую переменную фаззера (например, AFL_PRELOAD для AFL++).
Пример переменной run_env
в конфигурационном файле:
"run_env": {
"LD_PRELOAD": "/src/mylib.so",
"ENABLE_FUZZ_TARGETS": "1"
}
Доступные условия остановки фаззинг-тестирования:
- реальная продолжительность фаззинга достигла X секунд (затраченное время независимо от количества ядер / экземпляров фаззера);
- новые пути выполнения кода не обнаруживались в течение последних X секунд среди всех экземпляров фаззера.
Условие остановки задаётся с помощью переменных окружения:
- CERT_FUZZ_DURATION=X - X определяет количество секунд, в течение которых не должны обнаруживаться новые пути выполнения; переменная имеет наивысший приоритет, если установлены другие переменные;
- CERT_FUZZ_LEVEL=X - X определяет уровень контроля, что в свою очередь определяет время, в течение которого не должны обнаруживаться новые пути выполнения; допустимые значения X: 2, 3, 4; средний приоритет;
- FUZZ_DURATION=X - X определяет реальную продолжительность тестирования; низший приоритет.
Переменные CERT_FUZZ_* подходят для сертификационных испытаний, FUZZ_* - для использования в CI/CD.
Если не объявлена ни одна из указанных переменных, используется FUZZ_DURATION=600.
Количество используемых ядер процессора определяется минимальным значением среди перечисленных:
- Количество доступных в системе ядер.
- Значение переменной
fuzz_cores
в файле конфигурации. Если значение не указано, будет выбрано 8 ядер. - Аргумент запуска
--max-cpus
(значение по умолчанию: 16).
Таким образом, ограничение на количество ядер накладывает как автор конфигурационного файла (предположительно, разработчик тестируемого ПО), так и конечный пользователь bb-fuzz (предположительно, команда AppSec).
Собирает покрытие тестируемого приложения на семплах, сгенерированных фаззером.
Пример запуска:
bb-coverage suite /fuzz
В результате в папке /fuzz/coverage_report появляются файлы отчёта о покрытии, в том числе /fuzz/coverage_report/index.html - главная страница отчёта.
Инструмент не работает для встроенного фаззера Go (go test). Это вызвано особенностями работы фаззера.
Также не реализован сбор покрытия с фаззинг-целей Python.
Подробности о работе bb-coverage
Работа инструмента для C/C++-приложений:
- Запускает тестируемое приложение на семплах в директории синхронизации фаззера
- Строит отчёт о покрытии
Для приложений на языке Go инструмент работает иначе:
- Строит отчёт о покрытии с использованием данных, полученных при фаззинге с ключом запуска
-dumpcover
* - Изменяет цвет фона в отчёте о покрытии с чёрного на белый
* Инструмент bb-fuzz использует этот ключ.
В конфигурационном файле bugbane.json должны быть объявлены переменные tested_binary_path
, run_args
, run_env
, coverage_type
, fuzzer_type
, fuzz_sync_dir
и src_root
.
Переменная coverage_type
заполняется приложением bb-build и соответствует использованному сборщику.
src_root
- путь к исходному коду тестируемого приложения на момент выполнения сборок; путь не обязан реально существовать в файловой системе: если директория не существует, отчёт о покрытии будет содержать проценты, но не исходный код.
Возможные значения coverage_type
coverage_type | Описание |
---|---|
lcov | Для целей, собранных компиляторами GCC с флагом --coverage |
lcov-llvm | Для целей, собранных компиляторами LLVM с флагом --coverage |
go-tool-cover | Для целей на языке Go |
Воспроизводит обнаруженные фаззером падения и зависания и обобщает результаты работы фаззера.
Пример запуска:
bb-reproduce suite /fuzz
В результате формируется файл /fuzz/bb_results.json, содержащий статистику работы фаззера и сведения о воспроизводимых багах. Семплы, соответствующие воспроизводимым багам, сохраняются в папке /fuzz/bug_samples.
Подробности о работе bb-reproduce
Инструмент bb-reproduce выполняет следующие действия:
- Получает общую статистику работы фаззеров
- Минимизирует падения и зависания путём их воспроизведения
- Составляет информацию о каждом уникальном воспроизводимом баге
- Формирует JSON-файл со статистикой и данными о багах
- Сохраняет на диск тестовые примеры, приводящие к воспроизводимым падениям и зависаниям
Для каждого бага сохраняются такие сведения как заголовок issue/бага, место возникновения бага в исходном коде, команда запуска с конкретным семплом, вывод приложения (stdout+stderr), переменные окружения и т.д.
Поддерживаются цели, инструментированные с помощью SharpFuzz.
В конфигурационном файле bugbane.json должны быть определены переменные src_root
, fuzz_sync_dir
, fuzzer_type
, reproduce_specs
, run_args
и run_env
. Переменные fuzz_sync_dir
и reproduce_specs
добавляются инструментом bb-fuzz.
fuzz_sync_dir
- директория синхронизации фаззера; bb-fuzz использует директорию "out".
src_root
- путь к исходному коду тестируемого приложения на момент выполнения сборок; не обязан реально существовать в файловой системе, используется для более точного определения места падений/зависаний в исходном коде.
reproduce_specs
- словарь, определяющий тип фаззера, и задающий соответствие между сборками приложения и папками, на которых требуется выполнить воспроизведение:
"fuzz_sync_dir": "/fuzz/out",
"reproduce_specs": {
"AFL++": {
"/fuzz/basic/app": [
"test1"
],
"/fuzz/ubsan/app": [
"test2",
"test3"
]
}
}
В данном случае сборка basic (/fuzz/basic/app) будет запущена на семплах /fuzz/out/test1/{crashes,hangs}/id*
, а сборка ubsan (/fuzz/ubsan/app) - на семплах /fuzz/out/test{2,3}/{crashes,hangs}/id*
.
При каждом запуске анализируется вывод приложения в терминал, например, инструмент ищет сообщения санитайзеров. Каждый баг воспроизводится до успешного воспроизведения, но не более N раз. Число N определяется аргументом запуска bb-reproduce --num-reruns
(значение по умолчанию: 3). Если при воспроизведении падения не обнаруживается стек вызовов, приложение запускается под отладчиком gdb. Зависания воспроизводятся сразу под отладчиком gdb.
Информацию о найденных багах можно вывести в терминал с использованием утилиты jq (устанавливается отдельно).
Это позволяет просматривать и заводить баги вручную, например, если не используется система Defect Dojo или утилита bb-send.
Простой текстовый формат для удобного просмотра в терминале:
jq '.issue_cards[] | "-" * 79, .title, .reproduce_cmd, .output, "Saved sample name", .sample, ""' -rM bb_results.json
Готовое описание issue для GitHub:
jq '.issue_cards[] | "## \(.title)", "Originally reproduced by executing: \n```shell\n\(.reproduce_cmd)\n```", "Output:\n```\n\(.output)```", "Saved sample name: \(.sample)", ""' -rM bb_results.json
Готовое описание issue для Jira:
jq '.issue_cards[] | "h1. \(.title)", "Originally reproduced by executing: \n{noformat}\n\(.reproduce_cmd)\n{noformat}", "Output:\n{noformat}\n\(.output){noformat}", "Saved sample name: \(.sample)", ""' -rM bb_results.json
Рекомендуется заводить issue на каждый отдельный баг, поскольку баги уже прошли дедупликацию с помощью bb-reproduce и с высокой долей вероятности являются уникальными.
Если предпочтительнее создавать одно issue на все обнаруженные баги, то к нему достаточно приложить архив с директорией bug_samples
.
Заводит воспроизводимые баги в системе управления уязвимостями Defect Dojo.
Входные данные берутся из файла bb_results.json, полученного в результате работы инструмента bb-reproduce.
Файл bugbane.json не используется.
Пример запуска:
export BB_DEFECT_DOJO_SECRET="DD_TOKEN"
bb-send --host https://dojo.local \
--user-name ci_fuzz_user --user-id 2 \
--engagement 1 --test-type 141 \
--results-file bb_results.json
В результате на сервере Defect Dojo по адресу https://dojo.local
будет создан новый тест с типом 141 в engagement 1. Каждый баг будет заведён отдельно в пределах нового теста.
Описание некоторых аргументов запуска bb-send
Здесь и далее в качестве адреса сервера Defect Dojo используется https://dojo.local
.
--user-id
: id указанного в --user-name
пользователя; можно посмотреть в адресной строке Defect Dojo, выбрав нужного пользователя на странице https://dojo.local/user
.
--engagement
: engagement id; также можно посмотреть в адресной строке в браузере (выбрать нужный engagement на странице https://dojo.local/engagement
).
--test-type
: id вида теста; брать также из адресной строки (выбрать нужный тест на странице https://dojo.local/test_type
).
--token
: ключ API; берётся из Defect Dojo по ссылке: https://dojo.local/api/key-v2
(нужно быть авторизованным от имени, указанного в --user-name
, ключ нужен из раздела "Your current API key is ....").
Рекомендуется вместо опций --user-name
и --token
использовать переменные окружения BB_DEFECT_DOJO_LOGIN
и BB_DEFECT_DOJO_SECRET
.
Если подлинность сертификата сервера Defect Dojo не может быть проверена, то следует добавить аргумент запуска --no-ssl
.
Создаёт отчёт о выполненном фаззинг-тестировании в формате Markdown на основе указанного шаблона Jinja2.
По умолчанию используется шаблон с описанием процесса фаззинга на русском языке и включает команды, использованные для запуска фаззеров, скриншоты фаззеров, статистику работы и т.д.
Инструмент создаёт скриншоты:
- Окон фаззера - из дампов tmux, сохранённых инструментом bb-fuzz
- Главной страницы отчёта о покрытии кода, созданного инструментов bb-coverage
Скриншоты сохраняются в папку screenshots и вставляются в отчёт в виде ссылок.
В файле конфигурации bugbane.json должны быть объявлены переменные fuzzer_type
, coverage_type
и fuzz_sync_dir
.
Пример запуска:
bb-report --name myapp_fuzz suite /fuzz
Запуск с использованием Selenium:
bb-report --html-screener selenium --name myapp_fuzz suite /fuzz
В результате в папке /fuzz появляется директория screenshots с изображениями и файл с отчётом myapp_fuzz.md
.
Для создания документа в формате DOCX можно использовать утилиту pandoc (устанавливается отдельно):
pandoc -f markdown -t docx myapp_fuzz.md -o myapp_fuzz.docx
Создаёт скриншоты из указанных пользователем HTML-файлов, текстовых файлов, а также из файлов, содержащих ANSI-последовательности. Изображения создаются так же, как в приложении bb-report, но пользователь может указать имена входного и выходного файлов.
Примеры запуска:
bb-screenshot -S pango -i tmux_dump.txt -o tmux_screenshot.png
bb-screenshot -S weasyprint -i index.html -o coverage.png
bb-screenshot -S selenium -i index.html -o coverage2.png
Планы по улучшению BugBane:
- поддержка других фаззеров
- добавление других утилит
- генерация отчётов в других форматах и по другим шаблонам
Установка в режиме editable в виртуальное окружение:
python -m venv .venv
. .venv/bin/activate
pip install -e .[dev]
Запуск юнит-тестов pytest:
pytest
Спасибо всем участникам проекта!
Отдельные благодарности:
- Илья Уразбахтин: идеи, консультации, менторство.