
Фаззер JavaScript-движка
(Покрытие-)направляемый фаззер для интерпретаторов динамических языков, основанный на пользовательском промежуточном языке («FuzzIL»), который можно мутировать и транслировать в JavaScript.
Основные шаги для использования этого фаззера:
swift build [-c release].swift run [-c release] FuzzilliCli --profile=<profile> [other cli options] /path/to/jsshell. См. также swift run FuzzilliCli --help.Сборка и запуск Fuzzilli и поддерживаемых движков JavaScript внутри Docker и на Google Compute Engine также поддерживаются.
Посмотрите main.swift, чтобы увидеть пример использования библиотеки Fuzzilli и поиграть с различными параметрами конфигурации. Затем ознакомьтесь с Fuzzer.swift для высокоуровневой логики фаззинга. Оттуда погружайтесь в любую интересную часть.
Патчи, дополнения и другие вклады в этот проект приветствуются! Однако предварительно ознакомьтесь с заметками для контрибьюторов. Fuzzilli в целом следует стилю кода Google для Swift.
Будет очень признательно, если вы отправите короткое уведомление (возможно, с номером CVE) на [email protected] или откроете pull request для любой уязвимости, найденной с помощью этого проекта, чтобы она могла быть включена в раздел галерея багов. В остальном вы, конечно, можете претендовать на любые вознаграждения за баги, кредиты CVE и т.д. за эти уязвимости :)
При фаззинге на предмет основных ошибок интерпретатора, например в JIT-компиляторах, семантическая корректность генерируемых программ становится проблемой. Это отличается от большинства других сценариев, например фаззинга API времени выполнения, где семантическую некорректность можно легко обойти, обернув сгенерированный код в конструкции try-catch. Существуют разные способы достижения приемлемого уровня семантически корректных образцов, один из них — мутационный подход, при котором все образцы в корпусе также семантически валидны. В этом случае каждая мутация имеет лишь небольшой шанс превратить валидный образец в невалидный.
Для реализации мутационного JavaScript-фаззера необходимо определить мутации кода JavaScript. Вместо мутации AST или других синтаксических элементов программы определяется пользовательский промежуточный язык (IL), на котором мутации потока управления и данных программы могут выполняться более непосредственно. Затем этот IL транслируется в JavaScript для выполнения. Промежуточный язык выглядит примерно так:
v0 <− LoadInteger '0'
v1 <− LoadInteger '10'
v2 <− LoadInteger '1'
v3 <− LoadInteger '0'
BeginFor v0, '<', v1, '+', v2 −> v4
v6 <− BinaryOperation v3, '+', v4
Reassign v3, v6
EndFor
v7 <− LoadString 'Result: '
v8 <− BinaryOperation v7, '+', v3
v9 <− LoadGlobal 'console'
v10 <− CallMethod v9, 'log', [v8]
Который, например, может быть тривиально транслирован в следующий JavaScript-код:
const v0 = 0;
const v1 = 10;
const v2 = 1;
let v3 = 0;
for (let v4 = v0; v4 < v1; v4 = v4 + v2) {
const v6 = v3 + v4;
v3 = v6;
}
const v7 = "Result: ";
const v8 = v7 + v3;
const v9 = console;
const v10 = v9.log(v8);
Или в следующий JavaScript-код путём встраивания промежуточных выражений:
let v3 = 0;
for (let v4 = 0; v4 < 10; v4++) {
v3 = v3 + v4;
}
console.log("Result: " + v3);
FuzzIL обладает рядом свойств:
Reassign.Над этими программами могут выполняться различные мутации:
Более подробное обсуждение того, как работает Fuzzilli, можно найти здесь.
Фаззер реализован на Swift, некоторые части (например, измерение покрытия, сокетные взаимодействия и т.д.) реализованы на C.
Экземпляр фаззера (реализован в Fuzzer.swift) состоит из следующих центральных компонентов:
Кроме того, опционально доступны несколько модулей: