
Фаззер на основе покрытия для Python-приложений
pip3 install frelatage
Фаззер на Python, которого заслуживает мир
Установка | Как это работает | Возможности | Использование Frelatage | Конфигурация
Frelatage — это библиотека для фазинга Python на основе покрытия кода, которую можно использовать для фазинга Python-кода. Разработка Frelatage была вдохновлена различными другими фаззерами, включая AFL/AFL++, Atheris и PythonFuzz. Основная цель проекта — объединить лучшие возможности этих фаззеров в одном новом инструменте для эффективного фазинга Python-приложений.
ПРЕДУПРЕЖДЕНИЕ: Этот проект находится на стадии альфа-версии и может вызывать множество неожиданных поведений. На данный момент Frelatage не следует использовать в производственной среде.
pip3 install frelatage
Рекомендуется для разработчиков. Автоматически клонирует основную ветку из репозитория frelatage и устанавливает из исходников.
# Автоматически клонирует репозиторий Frelatage и устанавливает Frelatage из исходников
bash <(wget -q https://raw.githubusercontent.com/Rog3rSm1th/Frelatage/main/scripts/autoinstall.sh -O -)
Идея, лежащая в основе дизайна Frelatage, заключается в использовании генетического алгоритма для генерации мутаций, которые покроют как можно больше кода. Работа цикла фазинга может быть приблизительно описана следующей диаграммой:
graph TB
m1(Мутация 1) --> |входные данные| function(Фаззируемая функция)
m2(Мутация 2) --> |входные данные| function(Фаззируемая функция)
mplus(Мутация ...) --> |входные данные| function(Фаззируемая функция)
mn(Мутация n) --> |входные данные| function(Фаззируемая функция)
function --> generate_reports(Генерация отчётов)
generate_reports --> rank_reports(Ранжирование отчётов)
rank_reports --> select(Выбор n лучших отчётов)
select --> |мутировать| nm1(Мутация 1) & nm2(Мутация 2) & nmplus(Мутация ...) & nmn(Мутация n)
subgraph Мутации цикла
direction LR
m1
m2
mplus
mn
end
subgraph Мутации следующего цикла
direction LR
nm1
nm2
nmplus
nmn
end
style function fill:#5388e8,stroke:white,stroke-width:4px
Frelatage позволяет фаззить функцию, передавая ей файл в качестве входных данных.
import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.parse(data)
input = frelatage.Input(value="initial_value")
f = frelatage.Fuzzer(MyFunctionFuzz, [[input]])
f.fuzz()
Frelatage предоставляет возможность фаззить входные параметры файлового типа. Чтобы инициализировать значение таких файлов, необходимо создать файлы в папке ввода (по умолчанию ./in).
Если мы хотим инициализировать значение файла, используемого для фазинга, мы можем сделать это следующим образом:
echo "initial value" > ./in/input.txt
А затем запустить фаззер:
import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.load_file(data)
input = frelatage.Input(file=True, value="input.txt")
f = frelatage.Fuzzer(MyFunctionFuzz, [[input]])
f.fuzz()
import frelatage
import my_vulnerable_library
input = frelatage.Input(file=True, value="input.txt")
@frelatage.instrument([[input]])
def MyFunctionFuzz_1(data):
my_vulnerable_library.load_file(data)
@frelatage.instrument([[input]])
def MyFunctionFuzz_1(data):
my_vulnerable_library.load_file_but_different(data)
# And so on
# It will fuzz the instrumented methods one after the other
frelatage.Fuzzer.fuzz_all()
Если вам нужно загрузить несколько файлов в корпус за один раз (полезно, если вы используете большой корпус), вы можете использовать встроенную функцию Frelatage load_corpus. Эта функция возвращает список входных данных.
load_corpus(directory: str, file_extensions: list) -> list[Input]
./, ./images["jpeg", "gif"], ["pdf"]import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.load_file(data)
my_vulnerable_library.load_file(data2)
# Load every every file in the ./in directory
corpus_1 = frelatage.load_corpus(directory="./")
# Load every .gif/.jpeg file in the ./in/images subdirectory
corpus_2 = frelatage.load_corpus(directory="./images", file_extension=["gif", "jpeg"])
f = frelatage.Fuzzer(MyFunctionFuzz, [corpus_1, corpus_2])
f.fuzz()
Вы можете скопировать один или несколько словарей, расположенных здесь, в каталог, предназначенный для словарей (по умолчанию ./dict).
Дифференциальный фазинг — это популярная техника тестирования программного обеспечения, которая пытается обнаружить ошибки, передавая одни и те же входные данные нескольким библиотекам/программам и наблюдая за различиями в их поведении. Пример использования дифференциального фазинга с Frelatage с библиотеками json и ujson вы найдете здесь.
Вы можете найти больше примеров фаззеров и корпусов в каталоге examples.
Каждый отчёт о сбое сохраняется в выходной папке (по умолчанию ./out) в папке с именем: id:<crash ID>,err:<error type>,err_pos:<error>,err_file:<error file>.
Каталог отчёта имеет следующий вид:
├── out
│ ├── id:<crash ID>,err:<error type>,err_file:<error file>,err_pos:<err_pos>
│ ├── message
│ ├── input
│ ├── 0
│ ├── <inputfile1>
│ ├── ...
│ ├── ...
Каждый отчёт о сбое содержит файл message, который содержит сообщение об ошибке.
Каждый отчёт об увеличении покрытия сохраняется в папке покрытия (по умолчанию ./cov) в папке с именем: coverage_<ID>, и каталог отчёта имеет ту же форму, что и каталоги отчётов о сбоях.
Входные данные, переданные функции, сериализуются с помощью модуля pickle перед сохранением в файл <report_folder>/input. Поэтому для чтения содержимого файла необходимо его десериализовать. Это действие можно выполнить с помощью команды frelatage-report.
$ frelatage-report input
Существует два способа настройки Frelatage:
Пример конфигурации:
export FRELATAGE_DICTIONARY_ENABLE=1 &&
export FRELATAGE_SAVE_NEW_COVERAGE=1 &&
export FRELATAGE_TIMEOUT_DELAY=2 &&
export FRELATAGE_INPUT_FILE_TMP_DIR="/tmp/frelatage" &&
export FRELATAGE_INPUT_MAX_LEN=4096 &&
export FRELATAGE_MAX_THREADS=8 &&
export FRELATAGE_MAX_STAGES=1000000 &&
export FRELATAGE_MAX_CYCLES_WITHOUT_NEW_PATHS=5000 &&
export FRELATAGE_INPUT_DIR="./in" &&
export FRELATAGE_DICTIONARY_DIR="./dict" &&
python3 fuzzer.py
import frelatage
def myfunction(input1_string, input2_int):
pass
input1 = frelatage.Input(value="initial_value")
input2 = frelatage.Input(value=2)
f = frelatage.Fuzzer(
# The method you want to fuzz
method=myfunction,
# Corpus
corpus=[[input1], [input2]],
# Number of threads
threads_count=8,
# Exceptions that will be taken into account
exceptions_whitelist=(OSError),
# Exceptions that will not be taken into account
exceptions_blacklist=(),
# Directory where the error reports will be stored
output_directory="./out",
# Directory where the coverage increase reports will be stored
coverage_directory="./cov",
# Enable or disable silent mode
silent=False,
# Enable or disable infinite fuzzing
infinite_fuzz=False
)
f.fuzz()
Пожалуйста, имейте в виду, что, как и в случае со многими другими вычислительно-ёмкими задачами, фазинг может создавать нагрузку на ваше оборудование и операционную систему. В частности:
Ваш процессор будет нагреваться и потребует адекватного охлаждения. В большинстве случаев, если охлаждение недостаточно или перестаёт работать должным образом, тактовая частота процессора будет автоматически снижена. Тем не менее, особенно при фазинге на менее подходящем оборудовании (ноутбуки, смартфоны и т. д.), не исключена возможность поломки.
Целевые программы могут непредсказуемо захватывать гигабайты памяти или заполнять дисковое пространство мусорными файлами. Frelatage пытается обеспечить базовые ограничения памяти, но не может предотвратить все возможные инциденты. Суть в том, что не следует заниматься фазингом на системах, где риск потери данных неприемлем.
Фазинг включает миллиарды операций чтения и записи в файловую систему. На современных системах это обычно сильно кэшируется, что приводит к довольно скромной «физической» нагрузке на ввод-вывод, но существует множество факторов, которые могут изменить это уравнение. Вы несёте ответственность за мониторинг потенциальных проблем; при очень высокой нагрузке на ввод-вывод срок службы многих HDD и SSD может сократиться.
Хороший способ отслеживать нагрузку на дисковый ввод-вывод в Linux — команда 'iostat':
$ iostat -d 3 -x -k [...опциональный идентификатор диска...]
Я Rog3rSm1th, мне 21 год, я французский энтузиаст компьютеров и кибербезопасности. Мне нравится разрабатывать инструменты (OSINT, фазинг...) и участвовать в CTF/Wargames. Чтобы узнать больше обо мне и моих проектах, просто нажмите здесь.
➜ Если вы хотите нанять меня для одного из ваших проектов (программирование, кибербезопасность...), просто свяжитесь со мной по адресу [email protected], и мы вместе оценим ваши потребности.
По любым замечаниям, предложениям, сообщениям об ошибках или если вы нашли ошибку с помощью Frelatage, вы можете связаться со мной по адресу [email protected] или в Twitter @Rog3rSm1th.
| Переменная окружения | Описание | Возможные значения | Значение по умолчанию |
|---|
| FRELATAGE_DICTIONARY_ENABLE | Включить использование мутаций на основе элементов словаря | 1 для включения, 0 в противном случае | 1 |
| FRELATAGE_SAVE_NEW_COVERAGE | Сохранять новые входные данные покрытия для повторного использования в будущем | 1 для включения, 0 в противном случае | 1 |
| FRELATAGE_TIMEOUT_DELAY | Задержка в секундах, по истечении которой функция вернет TimeoutError | 1 - бесконечность | 2 |
| FRELATAGE_INPUT_FILE_TMP_DIR | Временная папка, где хранятся входные файлы | абсолютный путь к папке, например /tmp/custom_dir | /tmp/frelatage |
| FRELATAGE_INPUT_MAX_LEN | Максимальный размер входной переменной в байтах | 4 - бесконечность | 4094 |
| FRELATAGE_MAX_THREADS | Максимальное количество одновременных потоков | 8 - бесконечность | 8 |
| FRELATAGE_MAX_STAGES | Максимальное количество этапов для фаззированной функции | 1 - бесконечность | 1000000 |
| FRELATAGE_MAX_CYCLES_WITHOUT_NEW_PATHS | Количество циклов без найденных новых путей, после которого мы переходим к следующему этапу | 10 - бесконечность | 5000 |
| FRELATAGE_INPUT_DIR | Каталог, содержащий начальные входные файлы. Должен быть относительным путём (относительно пути к файлу фазинга) | относительный путь к папке, например ./in | ./in |
| FRELATAGE_DICTIONARY_DIR | Каталог по умолчанию для словарей. Должен быть относительным путём (относительно пути к файлу фазинга) | относительный путь к папке, например ./dict | ./dict |
| FRELATAGE_DEBUG_MODE | Включить режим отладки (показывать ошибку при сбое Frelatage) | 1 для включения, 0 в противном случае | 1 |