1590
|
1 # Fuzzing Dropbear |
|
2 |
|
3 Dropbear is process-per-session so it assumes calling `dropbear_exit()` |
|
4 is fine at any point to clean up. This makes fuzzing a bit trickier. |
|
5 A few pieces of wrapping infrastructure are used to work around this. |
|
6 |
|
7 The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness |
|
8 expects a long running process to continually run a test function with |
|
9 a string of crafted input. That process should not leak resources or exit. |
|
10 |
|
11 ## longjmp |
|
12 |
|
13 When dropbear runs in fuzz mode it sets up a |
|
14 [`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior |
|
15 to launching the code to be fuzzed, and then [`dropbear_exit()`](dbutil.c#L125) |
|
16 calls `longjmp()` back there. This avoids exiting though it doesn't free |
|
17 memory or other resources. |
|
18 |
|
19 ## malloc Wrapper |
|
20 |
|
21 Dropbear normally uses a [`m_malloc()`](dbmalloc.c) function that is the same as `malloc()` but |
|
22 exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator |
|
23 that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target |
|
24 calls [`m_malloc_free_epoch(1, 1)`](dbmalloc.c) to clean up any unreleased memory. |
|
25 |
|
26 If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset |
|
27 the tracked allocations but will not free memory - that allows libfuzzer's leak checking |
|
28 to detect leaks in normal operation. |
|
29 |
|
30 ## File Descriptor Input |
|
31 |
|
32 As a network process Dropbear reads and writes from a socket. The wrappers for |
|
33 `read()`/`write()`/`select()` in [fuzz-wrapfd.c](fuzz-wrapfd.c) will read from the |
|
34 fuzzer input that has been set up with `wrapfd_add()`. `write()` output is |
|
35 currently discarded. |
|
36 These also test error paths such as EINTR and short reads with certain probabilities. |
|
37 |
|
38 This allows running the entire dropbear server process with network input provided by the |
|
39 fuzzer, without many modifications to the main code. At the time of writing this |
|
40 only runs the pre-authentication stages, though post-authentication could be run similarly. |
|
41 |
|
42 ## Encryption and Randomness |
|
43 |
|
44 When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185) |
|
45 every time so that failures can be reproduced. |
|
46 |
|
47 Since the fuzzer cannot generate valid encrypted input the packet decryption and |
|
48 message authentication calls are disabled, see (packet.c)[packet.c]. |
|
49 MAC failures are set to occur with a low probability to test that error path. |
|
50 |
|
51 ## Fuzzers |
|
52 |
|
53 Current fuzzers are |
|
54 |
|
55 - fuzzer-preauth - the fuzzer input is treated as a stream of session input. This will |
|
56 test key exchange, packet ordering, authentication attempts etc. |
|
57 |
|
58 - fuzzer-preauth_nomaths - the same as fuzzer-preauth but with asymmetric crypto |
|
59 routines replaced with dummies for faster runtime. corpora are shared |
|
60 between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this |
|
61 will help fuzzer-preauth too. |
|
62 |
|
63 - fuzzer-verify - read a key and signature from fuzzer input and verify that signature. |
|
64 It would not be expected to pass, though some keys with bad parameters are |
|
65 able to validate with a trivial signature - extra checks are added for that. |
|
66 |
|
67 - fuzzer-pubkey - test parsing of an `authorized_keys` line. |
|
68 |
|
69 - fuzzer-kexdh - test Diffie-Hellman key exchange where the fuzz input is the |
|
70 public key that would be received over the network. |
|
71 |
|
72 - fuzzer-kexecdh - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh |