#fuzzing #constant-time #wasm-interpreter #wasm #numbers

sidefuzz

自动查找侧信道(时间)漏洞的模糊测试工具

3个版本

0.1.2 2019年5月2日
0.1.1 2019年4月30日
0.1.0 2019年4月30日

测试类别中排名第598

每月下载量24

MIT/Apache

13KB

SideFuzz:针对侧信道漏洞的模糊测试

SideFuzz是一个自适应的模糊测试工具,它结合了遗传算法优化器与t统计量,以寻找编译为wasm的加密学中的侧信道(时间)漏洞。

模糊测试目标可以在以下位置找到: https://github.com/phayes/sidefuzz-targets

工作原理

SideFuzz通过计数在wasmi wasm解释器中执行的指令来工作。它分为两个阶段

第一阶段。 使用遗传算法优化器尝试最大化两个不同输入之间执行的指令差异。它将继续优化,直到后续几代的输入对不再产生任何有意义的指令数量差异。这意味着它将优化,直到找到输入对适应度的局部最优。

第二阶段。 一旦找到局部最优,就会从领先输入对中进行抽样,直到以下任一条件成立:

  • 找到一个大的t统计量(p = 0.001),表明两个输入之间运行时间存在统计学上的显著差异。这表明存在时间侧信道漏洞;或者

  • t统计量保持较低,即使经过大量抽样。在这种情况下,候选输入对将被拒绝,SideFuzz将返回第一阶段,恢复遗传算法优化器以找到另一个局部最优。

它能给您带来什么

使用SideFuzz进行模糊测试表明,您的Rust代码可以具有常数时间复杂度,但它并不表明它在所有架构上都具有常数时间复杂度。这是因为LLVM后端在编译成机器码时,可能会破坏常数时间的Rust/LLVM-IR。因此,SideFuzz应被视为一个“良好的第一步”,随后可以跟进dudect-bencherctgrind。还应注意的是,在Rust生态系统中对常数时间代码生成进行适当编译器支持是一个未解决的问题。关于使用cranelift进行常数时间代码生成已经有一些想法,但这些仍然处于头脑风暴阶段。

安装

rustup target add wasm32-unknown-unknown
git clone [email protected]:phayes/sidefuzz.git
cd sidefuzz && cargo install --path .

(由于这个问题,目前无法使用cargo install sidefuzz进行安装)

创建Rust模糊测试目标

在Rust中创建目标非常简单。

// lib.rs
#[no_mangle]
pub extern "C" fn fuzz() {
  let input = sidefuzz::fetch_input(32); // 32 bytes of of fuzzing input as a &[u8]
  sidefuzz::black_box(my_hopefully_constant_fn(input));
}
# Cargo.toml
[lib]
crate-type = ["cdylib"]

[dependencies]
sidefuzz = "0.1.1"

按照以下方式编译和模糊测试目标

cargo build --release --target wasm32-unknown-unknown                # Always build in release mode
sidefuzz fuzz ./target/wasm32-unknown-unknown/release/my_target.wasm # Fuzzing!

可以按照以下方式检查结果

sidefuzz check my_target.wasm 01250bf9 ff81f7b3

在修复可变时间代码时,SideFuzz还可以使用sidefuzz count来快速统计目标执行的指令数。

cargo build --release && sidefuzz count my_target.wasm 01250bf9

在其他语言中创建模糊测试目标

SideFuzz可以与Go、C、C++和其他编译成wasm的语言一起使用。

wasm模块应提供四个导出项

  1. 导出至"memory"的内存

  2. 一个名为"fuzz"的函数。在模糊测试过程中,这个函数将被反复调用。

  3. 一个名为"input_pointer"的函数,它返回一个指向线性内存中位置的i32指针,我们可以在此处写入一个输入字节数组。该"fuzz"函数应读取这个字节数组作为它的模糊测试输入。

  4. 一个名为"input_len"的函数,它返回一个i32,表示所需的输入字节数。

常见问题解答

1. 为什么使用wasm?

Web Assembly允许我们精确跟踪执行的指令数、执行的指令类型以及使用的内存量。这比其他方法(如跟踪墙时间或计算CPU周期)要精确得多。

2. 为什么我总是需要以发布模式构建?

许多常数时间函数包含对可变时间的debug_assert!()函数的调用,这些调用在发布构建中被删除。Rust和LLVM优化器也可能为了优化而破坏所谓的常数时间代码,从而引入微妙的时序漏洞。在发布模式下运行可以让我们暴露这些问题。

3. 我需要一个随机数生成器(RNG)。怎么办?

您应该使用具有静态种子的PRNG。虽然这对于生产代码来说是一个坏主意,但对于模糊测试来说却很好。请参阅rsa_encrypt_pkcs1v15_message目标以了解如何操作的示例。

4. 关于black_box是什么意思?

sidefuzz::black_box用于避免死代码消除。因为我们感兴趣的是锻炼模糊测试代码,而不是从它那里得到结果,所以导出的fuzz函数不返回任何内容。Rust优化器将所有不返回的函数视为死代码,并试图在优化过程中将其删除。《code>black_box是一个对优化器来说是透明的函数,允许我们在函数被优化删除之前锻炼它。它应该在调用不返回任何内容或忽略返回结果的函数时使用。

5. 模糊测试器给了我无效的输入,接下来怎么办?

你应该感到恐慌(这会导致wasm陷阱)。这将向fuzzer发出信号,表明输入无效。

6. 我需要做一些变量时间的设置。我该如何操作?

你应该使用lazy_static来完成任何设置工作(如生成密钥等)。目标总是运行一次,以初始化懒静态变量,然后在真正的模糊测试开始之前。

  1. dudect-bencher。DudeCT常时函数测试器的实现。与SideFuzz相比,这个工具更接近原始的dudect设计。 https://crates.io/crates/dudect-bencher

  2. ctgrind。使用Valgrind检查函数是否为常时的工具。 https://github.com/RustCrypto/utils/tree/master/ctgrind

进一步阅读

  1. "DifFuzz: 用于侧信道分析的差异模糊测试",Nilizadeh等人。 https://arxiv.org/abs/1811.07005

  2. "Dude, is my code constant time?",Reparaz等人。 https://eprint.iacr.org/2016/1123.pdf

  3. "Rust, dudect和调试模式的常时加密",brycx。 https://brycx.github.io/2019/04/21/rust-dudect-constant-time-crypto.html

依赖关系

~11KB