Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
PHP-Fuzzer — Фаззер для PHP-библиотек, управляемый покрытием краёв, который обнаруживает ошибки через крахи, тайм-ауты и предупреждения. Поддерживает управление корпусом, минимизацию крахов и отчёты о покрытии кода. | Kitploit
Инструменты/GitHubGitHub/nikic/php-fuzzer
Динамический анализ (песочница)Анализ уязвимостейАнализ КодаФаззинг
GitHubnikic/php-fuzzer

PHP-Fuzzer

Фаззер для PHP-библиотек, управляемый покрытием краёв, который обнаруживает ошибки через крахи, тайм-ауты и предупреждения. Поддерживает управление корпусом, минимизацию крахов и отчёты о покрытии кода.

Репозиторий
441187 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

PHP Фаззер

Эта библиотека реализует фаззер для PHP, который можно использовать для поиска ошибок в библиотеках (особенно в библиотеках парсинга) путём подачи им «случайных» входных данных. Обратная связь от инструментария покрытия рёбер используется для управления выбором «случайных» входных данных, чтобы посещались новые участки кода.

Установка

Phar (рекомендуется): Вы можете загрузить phar-пакет этой библиотеки со страницы релизов. Использование phar рекомендуется, так как это позволяет избежать конфликтов зависимостей с библиотеками, использующими PHP-Parser.

Composer: composer global require nikic/php-fuzzer

Использование

Сначала необходимо определить целевую функцию. Вот пример цели для поиска ошибок в microsoft/tolerant-php-parser:

root@kitploit:~
<?php // target.php

/** @var PhpFuzzer\Config $config */

require 'path/to/tolerant-php-parser/vendor/autoload.php';

// Required: The target accepts a single input string and runs it through the tested
//           library. The target is allowed to throw normal Exceptions (which are ignored),
//           but Error exceptions are considered as a found bug.
$parser = new Microsoft\PhpParser\Parser();
$config->setTarget(function(string $input) use($parser) {
    $parser->parseSourceFile($input);
});

// Optional: Many targets don't exhibit bugs on large inputs that can't also be
//           produced with small inputs. Limiting the length may improve performance.
$config->setMaxLen(1024);
// Optional: A dictionary can be used to provide useful fragments to the fuzzer,
//           such as language keywords. This is particularly important if these
//           cannot be easily discovered by the fuzzer, because they are handled
//           by a non-instrumented PHP extension function such as token_get_all().
$config->addDictionary('example/php.dict');

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

root@kitploit:~
# Запуск без начального корпуса
php-fuzzer fuzz target.php
# Запуск с начальным корпусом (один входной файл на файл)
php-fuzzer fuzz target.php corpus/

Если фаззинг был прерван, его можно позже возобновить, указав тот же каталог корпуса.

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

root@kitploit:~
php-fuzzer minimize-crash target.php crash-HASH.txt

Это создаст последовательность всё более коротких файлов minimized-HASH.txt. Если вы хотите быстро проверить трассировку исключений, создаваемую сбойным входом, вы можете использовать команду run-single:

root@kitploit:~
php-fuzzer run-single target.php minimized-HASH.txt

Наконец, можно сгенерировать HTML-отчёт о покрытии кода, который показывает, какие блоки кода в цели были задействованы при выполнении входных данных из заданного корпуса:

root@kitploit:~
php-fuzzer report-coverage target.php corpus/ coverage_dir/

Дополнительные параметры конфигурации можно посмотреть с помощью php-fuzzer --help.

Во время работы фаззер непрерывно отображает свой статус одной строкой вывода. Эта строка состоит из следующих частей в указанном порядке:

  1. NEW или REDUCED: Действие, вызвавшее эту строку статуса. NEW означает, что в корпус был добавлен новый вход, а REDUCED — что существующая запись корпуса была заменена более коротким входом.
  2. run: N: Общее количество итераций фаззинга (выполнений цели) с момента запуска фаззера
  3. (N/с): Текущая скорость выполнения, измеряемая в запусках в секунду
  4. ft: N: Общее количество уникальных признаков, обнаруженных на данный момент
  5. (N/с): Среднее количество новых признаков, обнаруживаемых в секунду с момента запуска фаззера
  6. corp: N: Количество интересных входов, хранящихся в корпусе на данный момент
  7. (%s): Общий размер всех входов в корпусе
  8. len: %d/%d: Первое число — длина (в байтах) текущего входа, вызвавшего действие, второе число — текущая максимально допустимая длина входа
  9. t: Общее прошедшее время с момента запуска фаззера, в секундах

Типы ошибок

По умолчанию фаззер обнаруживает три вида ошибок:

  • Исключения Error, выбрасываемые целью фаззинга. В то время как исключения Exception считаются нормальным результатом для некорректного ввода, неперехваченные исключения Error всегда указывают на ошибку программирования. Чаще всего они вызываются самим PHP, например при вызове метода на null.
  • Выброшенные уведомления и предупреждения (если они не подавлены). Фаззер регистрирует обработчик ошибок, который преобразует их в исключения Error.
  • Тайм-ауты. Если цель работает дольше указанного тайм-аута (по умолчанию 3 с), считается, что цель вошла в бесконечный цикл. Это реализуется с помощью pcntl_alarm() и асинхронного обработчика сигнала, который выбрасывает Error при тайм-ауте.

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

root@kitploit:~
$fuzzer->setTarget(function(string $input) use($parser1, $parser2) {
    $result1 = $parser1->parse($input);
    $result2 = $parser2->parse($input);
    if ($result1 != $result2) {
        throw new Error('Results do not match!');
    }
});

Технические детали

Многие технические детали этого фаззера основаны на libFuzzer из проекта LLVM. Ниже описаны некоторые детали реализации.

Инструментарий

Для эффективной работы фаззинга требуется обратная связь о путях выполнения кода при тестировании конкретного входного фаззинг-входа. Эта информация о покрытии собирается путём «инструментирования» цели фаззинга. Библиотека include-interceptor используется для преобразования кода всех подключаемых файлов на лету. Библиотека PHP-Parser используется для разбора кода и поиска всех мест, куда нужно вставить дополнительный инструментальный код.

Внутри каждого базового блока вставляется следующий код, где BLOCK_INDEX — уникальный для каждого блока целое число:

root@kitploit:~
$___key = (\PhpFuzzer\FuzzingContext::$prevBlock << 28) | BLOCK_INDEX;
\PhpFuzzer\FuzzingContext::$edges[$___key] = (\PhpFuzzer\FuzzingContext::$edges[$___key] ?? 0) + 1;
\PhpFuzzer\FuzzingContext::$prevBlock = BLOCK_INDEX;

Это предполагает, что индекс блока имеет размер не более 28 бит, и подсчитывает количество пар (prev_block, cur_block), наблюдаемых во время выполнения. Сгенерированный код, к сожалению, довольно дорог из-за необходимости работать с неинициализированными счётчиками рёбер и использования статических свойств. В будущем можно было бы создать PHP-расширение, которое может собирать информацию о покрытии гораздо эффективнее.

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

root@kitploit:~
if ($foo && $bar) { ... }
// становится
if ($foo && \PhpFuzzer\FuzzingContext::traceBlock(BLOCK_INDEX, $bar)) { ... }

В будущем было бы полезно также инструментировать сравнения, чтобы можно было автоматически определять словарные записи из сравнений, таких как $foo == "SOME_STRING".

Признаки

Входные фаззинг-данные считаются «интересными», если они содержат новые признаки, которые не наблюдались у других входов, уже находящихся в корпусе. Эта библиотека использует крупнозернистые счётчики попаданий рёбер в качестве признаков:

root@kitploit:~
ft = (approx_hits << 56) | (prev_block << 28) | cur_block

Приблизительное количество попаданий сводит реальное количество попаданий к 8 категориям (на основе AFL):

root@kitploit:~
0: 0 попаданий
1: 1 попадание
2: 2 попадания
3: 3 попадания
4: 4–7 попаданий
5: 8–15 попаданий
6: 16–127 попаданий
7: >=128 попаданий

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

Если вход имеет уникальные признаки, он добавляется в корпус (NEW). Если вход B был создан путём мутации входа A, но вход B короче и имеет все уникальные признаки входа A, то A заменяется на B в корпусе (REDUCE).

Мутация

На каждой итерации из текущего корпуса выбирается случайный вход, а затем мутируется с помощью последовательности мутаторов. В настоящее время реализованы следующие мутаторы (взяты из libFuzzer):

  • EraseBytes: Удаление нескольких байтов.
  • InsertByte: Вставка нового случайного байта.
  • InsertRepeatedBytes: Вставка случайного байта, повторённого несколько раз.
  • ChangeByte: Замена байта на случайный байт.
  • ChangeBit: Переворот одного бита.
  • ShuffleBytes: Перемешивание небольшой подстроки.
  • ChangeASCIIInt: Изменение ASCII-целого числа путём увеличения/уменьшения/удвоения/уполовинивания.
  • ChangeBinInt: Изменение двоичного целого числа путём добавления небольшой случайной величины.
  • CopyPart: Копирование части строки в другую часть, либо с перезаписью, либо со вставкой.
  • CrossOver: Скрещивание с другой записью корпуса с несколькими стратегиями.
  • AddWordFromManualDictionary: Вставка или замена словом из словаря (если он есть).

Мутация ограничена максимальной длиной. Хотя общая максимальная длина может быть задана целью (setMaxLength()), фаззер также выполняет автоматическое управление длиной (--len-control-factor). Максимальная длина изначально устанавливается на очень низкое значение, а затем увеличивается на log(maxlen) каждый раз, когда не было совершено никаких действий (NEW или REDUCE) за последние len_control_factor * log(maxlen) запусков.

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

Найденные ошибки

  • tolerant-php-parser: #305
  • PHP-CSS-Parser: #181 #182 #183 #184
  • league/uri: #150
  • amphp/http-client #236
  • amphp/hpack #8
  • phpmyadmin/sql-parser: #508 #510
  • club-1/sphinx-inventory-parser: #7
Скачать инструмент
  • mem: Текущее использование памяти процессом PHP