Fuzzilli – A JavaScript Engine Fuzzer

Fuzzilli - A JavaScript Engine Fuzzer

A (protection-)guided fuzzer for dynamic language interpreters centered on a custom intermediate language (“FuzzIL”) which can be mutated and translated to JavaScript.

Utilization

The simple methods to use this fuzzer are:

  1. Down load the supply code for one particular of the supported JavaScript engines. See the Targets/ listing for the record of supported JavaScript engines.
  2. Implement the corresponding patches from the target’s listing. Also see the README.md in that listing.
  3. Compile the engine with protection instrumentation (requires clang >= 4.) as explained in the README.
  4. Compile the fuzzer: swift develop [-c release].
  5. Run the fuzzer: swift operate [-c release] FuzzilliCli --profile= [other cli options] /route/to/jsshell. See also swift operate FuzzilliCli --enable.

Developing and functioning Fuzzilli and the supported JavaScript engines inside Docker and on Google Compute Engine is also supported.

Hacking

Examine out most important.swift to see a utilization case in point of the Fuzzilli library and enjoy with the a variety of configuration selections. Following, choose a look at Fuzzer.swift for the highlevel fuzzing logic. From there dive into any component that seems appealing.

Patches, additions, other contributions etcetera. to this project are incredibly welcome! Having said that, do speedily test the notes for contributors. Fuzzilli roughly follows Google’s code type tutorial for swift.

It would be a great deal appreciated if you could send a quick take note (quite possibly which include a CVE range) to saelo@google.com or open a pull ask for for any vulnerability located with the assist of this project so it can be included in the bug showcase segment. Other than that you can of course assert any bug bounty, CVE credits, and many others. for the vulnerabilities 🙂

Concept

When fuzzing for main interpreter bugs, e.g. in JIT compilers, semantic correctness of generated courses gets a worry. This is in contrast to most other eventualities, e.g. fuzzing of runtime APIs, in which case semantic correctness can simply be worked all-around by wrapping the produced code in try-capture constructs. There are various prospects to accomplish an acceptable charge of semantically suitable samples, one particular of them currently being a mutational solution in which all samples in the corpus are also semantically legitimate. In that situation, each individual mutation only has a modest likelihood of turning a legitimate sample into an invalid a person.

To put into action a mutation-based JavaScript fuzzer, mutations to JavaScript code have to be defined. Instead of mutating the AST, or other syntactic components of a plan, a custom intermediate language (IL) is outlined on which mutations to the handle and facts flow of a program can much more immediately be executed. This IL is afterwards translated to JavaScript for execution. The intermediate language seems to be roughly as follows:

v0 <− LoadInteger '0'
v1 <− LoadInteger '10'
v2 <− LoadInteger '1'
v3 <− LoadInteger '0'
BeginFor v0, ' v4
v6 <− BinaryOperation v3, '+', v4
Reassign v3, v6
EndFor
v7 <− LoadString 'Result: '
v8 <− BinaryOperation v7, '+', v3
v9 <− LoadGlobal 'console'
v10 <− CallMethod v9, 'log', [v8]

Which can e.g. be trivially translated to the following JavaScript code:

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)

Or to the following JavaScript code by inlining intermediate expressions:

let v3 = 0
for (let v4 = 0 v4 < 10 v4++)
v3 = v3 + v4

console.log("Result: " + v3)

FuzzIL has a number of properties:

  • A FuzzIL program is simply a list of instructions.
  • A FuzzIL instruction is an operation together with input and output variables and potentially one or more parameters (enclosed in single quotes in the notation above).
  • Inputs to instructions are always variables, there are no immediate values.
  • Every output of an instruction is a new variable, and existing variables can only be reassigned through dedicated operations such as the Reassign instruction.
  • Every variable is defined before it is used.

A number of mutations can then be performed on these programs:

  • InputMutator: replaces input variables of instructions with different ones to mutate the dataflow of the program.
  • CodeGenMutator: generates code and inserts it somewhere in the mutated program. Code is generated either by running a code generator or by copying some instructions from another program in the corpus (splicing).
  • CombineMutator: inserts a program from the corpus into a random position in the mutated program.
  • OperationMutator: mutates the parameters of operations, for example replacing an integer constant with a different one.
  • and more…

Implementation

The fuzzer is implemented in Swift, with some parts (e.g. coverage measurements, socket interactions, etc.) implemented in C.

Architecture

A fuzzer instance (implemented in Fuzzer.swift) is made up of the following central components:

  • MutationFuzzer: produces new programs from existing ones by applying mutations. Afterwards executes the produced samples and evaluates them.
  • ScriptRunner: executes programs of the target language.
  • Corpus: stores interesting samples and supplies them to the core fuzzer.
  • Environment: has knowledge of the runtime environment, e.g. the available builtins, property names, and methods.
  • Minimizer: minimizes crashing and interesting programs.
  • Evaluator: evaluates whether a sample is interesting according to some metric, e.g. code coverage.
  • Lifter: translates a FuzzIL program to the target language (JavaScript).

Furthermore, a number of modules are optionally available:

The fuzzer is event-driven, with most of the interactions between different classes happening through events. Events are dispatched e.g. as a result of a crash or an interesting program being found, a new program being executed, a log message being generated and so on. See Events.swift for the full list of events. The event mechanism effectively decouples the various components of the fuzzer and makes it easy to implement additional modules.

A FuzzIL program can be built up using a ProgramBuilder instance. A ProgramBuilder provides methods to create and append new instructions, append instructions from another program, retrieve existing variables, query the execution context at the current position (e.g. whether it is inside a loop), and more.

Execution

Fuzzilli uses a custom execution mode called REPRL (read-eval-print-reset-loop). For that, the target engine is modified to accept a script input over pipes and/or shared memory, execute it, then reset its internal state and wait for the next script. This removes the overhead from process creation and to a large part from the engine ininitializaiton.

Scalability

There is one Fuzzer instance per target process. This enables synchronous execution of programs and thereby simplifies the implementation of various algorithms such as consecutive mutations and minimization. Moreover, it avoids the need to implement thread-safe access to internal state, e.g. the corpus. Each fuzzer instance has its own DispatchQueue, conceptually corresponding to a single thread. As a rule of thumb, every interaction with a Fuzzer instance must happen on that instance’s dispatch queue. This guarantees thread-safety as the queue is serial. For more details see the docs.

To scale, fuzzer instances can become workers, in which case they report newly found interesting samples and crashes to a master instance. In turn, the master instances also synchronize their corpus with the workers. Communication between masters and workers can happen in different ways, each implemented as a module:

  • Inter-thread communication: synchronize instances in the same process by enqueuing tasks to the other fuzzer’s DispatchQueue.
  • Inter-process communication (TODO): synchronize instances over an IPC channel.
  • Inter-machine communication: synchronize instances over a simple TCP-based protocol.

This design allows the fuzzer to scale to many cores on a single machine as well as to many different machines. As one master instance can quickly become overloaded if too many workers send programs to it, it is also possible to configure multiple tiers of master instances, e.g. one master instance, 16 intermediate masters connected to the master, and 256 workers connected to the intermediate masters.

Resources

Further resources about this fuzzer:

  • A presentation about Fuzzilli given at Offensive Con 2019.
  • The master’s thesis for which the initial implementation was done.
  • A blogpost by Sensepost about using Fuzzilli to find a bug in v8
  • A blogpost by Doyensec about fuzzing the JerryScript engine with Fuzzilli

Bug Showcase

The following is a list of some of the bugs found with the help of Fuzzilli. Only bugs with security impact are included in the list. Special thanks to all users of Fuzzilli who have reported bugs found by it!

WebKit/JavaScriptCore

  • Issue 185328: DFG Compiler uses incorrect output register for NumberIsInteger operation
  • CVE-2018-4299: performProxyCall leaks internal object to script
  • CVE-2018-4359: compileMathIC produces incorrect machine code
  • CVE-2019-8518: OOB access in FTL JIT due to LICM moving array access before the bounds check
  • CVE-2019-8558: CodeBlock UaF due to dangling Watchpoints
  • CVE-2019-8611: AIR optimization incorrectly removes assignment to register
  • CVE-2019-8623: Loop-invariant code motion (LICM) in DFG JIT leaves stack variable uninitialized
  • CVE-2019-8622: DFG’s doesGC() is incorrect about the HasIndexedProperty operation’s behaviour on StringObjects
  • CVE-2019-8671: DFG: Loop-invariant code motion (LICM) leaves object property access unguarded
  • CVE-2019-8672: JSValue use-after-free in ValueProfiles
  • CVE-2019-8678: JSC fails to run haveABadTime() when some prototypes are modified, leading to type confusions
  • CVE-2019-8685: JSPropertyNameEnumerator uses wrong structure IDs
  • CVE-2019-8765: GetterSetter type confusion during DFG compilation
  • CVE-2019-8820: Type confusion during bailout when reconstructing arguments objects
  • CVE-2020-3901: GetterSetter type confusion in FTL JIT code (due to not always safe LICM)

Gecko/Spidermonkey

  • CVE-2018-12386: IonMonkey register allocation bug leads to type confusions
  • CVE-2019-9791: IonMonkey’s type inference is incorrect for constructors entered via OSR
  • CVE-2019-9792: IonMonkey leaks JS_OPTIMIZED_OUT magic value to script
  • CVE-2019-9816: unexpected ObjectGroup in ObjectGroupDispatch operation
  • CVE-2019-9813: IonMonkey compiled code fails to update inferred property types, leading to type confusions
  • CVE-2019-11707: IonMonkey incorrectly predicts return type of Array.prototype.pop, leading to type confusions
  • CVE-2020-15656: Type confusion for special arguments in IonMonkey

Chromium/v8

Duktape

  • Issue 2323: Unstable valstack pointer in putprop
  • Issue 2320: Memcmp pointer overflow in string builtin

JerryScript

  • CVE-2020-13991: Incorrect release of spread arguments
  • Issue 3784: Memory corruption due to incorrect property enumeration
  • CVE-2020-13623: Stack overflow via property keys for Proxy objects
  • CVE-2020-13649 (1): Memory corruption due to error handling in case of OOM
  • CVE-2020-13649 (2): Memory corruption due to error handling in case of OOM
  • CVE-2020-13622: Memory corruption due to incorrect handling of property keys for Proxy objects
  • CVE-2020-14163: Memory corruption due to race condition triggered by garbage collection when adding key/value pairs
  • Issue 3813: Incorrect error handling in SerializeJSONProperty function
  • Issue 3814: Unexpected Proxy object in ecma_op_function_has_instance assertion
  • Issue 3836: Memory corruption due to incorrect TypedArray initialization
  • Issue 3837: Memory corruption due to incorrect memory handling in getOwnPropertyDescriptor

Disclaimer

This is not an officially supported Google product.

SwcA8mqskXY

Image and Article Source link

Read More on Pentesting Tools

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: