EnglishРусский Map
Supply Chain Security

Дифференциальный fuzzing

title
Дифференциальный fuzzing
type
concept
summary
Подача одного входа двум реализациям спецификации и поиск расхождений: находит ошибки соответствия спецификации, которые одна реализация не выявит
tags
fuzzing, security, testing
created
2026-05-12
updated
2026-07-29
lang
ru
translation_of
differential-fuzzing
source_updated
2026-07-29
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Большая часть coverage-guided fuzzing'а ищет падения - segfault'ы, panic'и, assert'ы, срабатывания sanitizer'ов. Дифференциальный fuzzing ищет расхождения: один и тот же вход подаётся двум независимым реализациям одной спецификации, их вывод сравнивается, а любое расхождение считается багом. Реализации валидируют друг друга; чтобы тест провалился, ни одной из них не нужно падать.

Метод подходит, когда:

  • Тестируемым контрактом выступает сама спецификация, а не отдельная реализация
  • Цена расхождений между реализациями высока - системы консенсуса, криптографические протоколы, компиляторы с воспроизводимой сборкой бинарников
  • В экосистеме есть как минимум две достаточно зрелые реализации для сравнения

Где применяется на практике

  • Клиенты Ethereum L1/L2 - geth против nethermind и reth, op-node против Kona, EVM против Revm. Несовпадение state-root на одном и том же блоке приводит к разделению цепочки (chain split).
  • TLS - OpenSSL против BoringSSL и Rustls, иногда также против спецификации wire-формата
  • JSON / сериализация - обработка "экзотических" входных данных (дубликаты ключей, ведущие нули, NaN) в кодировщиках часто расходится, иногда с возможностью эксплуатации
  • Компиляторы - Csmith и Yarpgen запускают дифференциальный fuzzing для GCC/Clang/MSVC
  • SQL-движки - SQLite как эталон (oracle) против Postgres/MySQL для одного и того же запроса
  • Парсеры протоколов - исследования атак HTTP request smuggling использовали дифференциальный парсинг между фронтенд-прокси и бэкенд-серверами

Декодер формата с эталонной реализацией - каноническая цель, и по состоянию на 2026 год уже не единственный вариант: zstd-lean-proof-automation доказывает отсутствие контрпримеров, за которыми охотится этот метод, на том же классе кода.

Сочетание с grammar-based fuzzing'ом

grammar-based-fuzzing делает дифференциальный fuzzing практичным в масштабе: обе реализации должны распарсить вход достаточно глубоко, чтобы выдать результат, поэтому fuzzer не должен тратить ресурсы на входы, которые обе стороны отклоняют на нулевом байте. Грамматика, генерирующая "нечто, похожее на валидную транзакцию", проверяет семантические расхождения после парсинга - именно там и живут баги консенсуса.

Примеры из ранних запусков gosentry

В посте блога gosentry перечислены четыре ранние находки, и все они связаны с консенсусом:

  • Optimism / Kona и op-node разошлись в обработке каналов Brotli
  • Парсинг фреймов разошёлся со спецификацией Optimism
  • Обработчик неудавшихся депозитов в Revm не увеличивал nonce - несовпадение state-root с другими клиентами Ethereum
  • Optimism / Kona падал в panic на неизвестных типах батчей вместо их отклонения

Каждая из них - расхождение в интерпретации спецификации, а не падение реализации.