Quick Start
Goal
We will fuzz a very minimal Tauri application.
The repository features a minimal example called mini-app
.
This example app will be used to showcase how to setup fuzzing with tauri-fuzz
.
Fuzzing a Tauri application
We are using mini-app
that implements a simple Tauri command, that will later be fuzzed.
Tauri app structure
mini-app
- ...
- src/
- src-tauri/
- src/
- lib.rs
- main.rs
- tauri_commands/
- file_access.rs
- read_foo_file
- ...
- Cargo.toml
Make the Tauri Application Accessible to the Fuzzer
The Tauri app backend must be compiled as a crate such that the Tauri commands are exposed to the fuzzer.
For example we want to fuzz the Tauri commands called read_foo_file
:
`mini-app/src-tauri/Cargo.toml`
[package]
name = "mini-app"
version = "0.0.0"
description = "A Tauri App"
# This section is automatic in Tauri v2
[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
`mini-app/src-tauri/lib.rs`
/// define the module
pub mod tauri_commands;
/// publicly re-export the Taur command `read_foo_file`
pub use tauri_commands::file_access::read_foo_file
`mini-app/src-tauri/src-tauri/tauri_commands/file_access.rs`
#[tauri::command]
/// Mark the function as public
pub fn read_foo_file() -> String {
let path = get_foo_path();
let mut content = String::new();
let mut file = File::open(path).unwrap();
file.read_to_string(&mut content).unwrap();
content
}
Fuzzing our Tauri app, quick guide
[Note] This section requires the CLI utility
cargo-tauri-fuzz
The project contains the cratecrates/tauri-fuzz-cli
that builds the binarycargo-tauri-fuzz
. If any issue arises from using the CLI we recommend you follow the manual steps guide
1. Create fuzz directory
Execute cargo-tauri-fuzz init
in mini-app/src-tauri
.
Tauri app structure with fuzz directory
Project
- ...
- src/
- ...
- src-tauri/
- src/
- lib.rs
- main.rs
- tauri_commands/
- file_access.rs
- read_foo_file
- ...
- fuzz/
- build.rs
- Cargo.toml
- fuzz_targets/
- _template_.rs
- _template_full_.rs
- fuzzer_config.toml
- README.md
- tauri.conf.json
- Cargo.toml
2. Write your fuzz target
- Copy
mini-app/src-tauri/fuzz/fuzz_targets/_template_.rs
asmini-app/src-tauri/fuzz/fuzz_targets/fuzz_read_foo.rs
- Fill
mini-app/src-tauri/fuzz/fuzz_targets/fuzz_read_foo.rs
with relevant information
`mini-app/src-tauri/fuzz/fuzz_targets/fuzz_read_foo.rs`
Here we will fuzz the Tauri command read_foo
against a policy that does not allow any file access.
// Copyright 2023-2024 CrabNebula Ltd., Alexandre Dang
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// This is a template to create a fuzz target
//
// Steps:
// 1. Copy this file and rename it
// 2. Change the target details below
// 3. Add the new fuzz target in [[bin]] table in Cargo.toml of your project
//
// Note: you may need to implement [FromRandomBytes] for your command argument types.
tauri_fuzz::fuzz_tauri_command! {
// Name of the tauri command you want to fuzz
command: "read_foo_file",
// Pointer to the tauri command you want to fuzz
path: {{crate_name_underscored}}::file_access::read_foo_file,
// Parameters names and types to the tauri command
parameters: {
name: String,
},
// Policy chosen for the fuzzing
// Here the policy will not allow any access to the filesystem
policy: tauri_fuzz_policies::filesystem::no_file_access(),
}
3. Add the fuzz target as binary
Add fuzz_read_foo
as a binary in mini-app/src-tauri/fuzz/Cargo.toml
`mini-app/src-tauri/fuzz/Cargo.toml`
[package]
name = "{{ crate_name }}-fuzz"
version = "0.0.0"
publish = false
edition = "2021"
[workspace]
[build-dependencies]
tauri-build = "2.0"
[dependencies]
{{ crate_name }} = { path = ".." }
tauri-fuzz-policies = { git = "ssh://git@github.com/crabnebula-dev/tauri-fuzz.git" }
tauri-fuzz = { git = "ssh://git@github.com/crabnebula-dev/tauri-fuzz.git", features = ["tauri"] }
tauri = { version = "2.0", features = ["test"]}
libafl = "0.13"
# Uncomment this block to add `fuzz_read_foo` as a fuzz target
# [[bin]]
# name = "fuzz_read_foo"
# path = "fuzz_targets/fuzz_read_foo.rs"
# doc = false
4. Start fuzzing
Start fuzzing by executing one of these commands.
From mini-app/src-tauri/
directory:
cargo-tauri-fuzz fuzz fuzz_read_foo
Or from mini-app/src-tauri/fuzz/
directory:
cargo r --bin fuzz_read_foo
5. Check your solutions
You should see this result repeatedly on your terminal:
Fuzzing results
[ERROR policies::engine] Policy was broken at function [open].
Description: Access to [open] denied
Rule: Rule::OnEntry
Context: Function entry with parameters: [140736965046336, 524288]
The application panicked (crashed).
Message: Intercepting call to [open].
Policy was broken at function [open].
Description: Access to [open] denied
Rule: Rule::OnEntry
Context: Function entry with parameters: [140736965046336, 524288]
This is the expected result. The Tauri command we fuzz, read_foo_file
, tries to read foo.txt
but got intercepted since we are fuzzing with a policy that does not allow any access to the filesystem.
More precisely the message specifies Policy was broken at function [open]
.
Indeed read_foo_file
tried to use the libc function open
that is used to access files and got intercepted.
The inputs used by the fuzzer which provokes a policy breach are stored in mini-app/src-tauri/fuzz/fuzz_solutions
.
Those inputs can be then investigated to understand why the policy breach happened.