another round of proof reading

This commit is contained in:
Florian Obser 2022-12-02 16:58:09 +01:00
parent d8a71ff8d4
commit ccee218d26

View File

@ -29,20 +29,19 @@ that's just rude, uncalled for, and generally boring and
pointless. Technically I'm on vacation and I had resolved to only do pointless. Technically I'm on vacation and I had resolved to only do
fun things this week. So let's have some fun. fun things this week. So let's have some fun.
Step two: FreeBSD had a problem in =pr_pack()= because that function Step two: Did we mess something else up? FreeBSD had a problem in
handles data from the network. The data is untrusted and needs to be =pr_pack()= because that function handles data from the network. The
validated. Now is a good time as any to check OpenBSD's implementation data is untrusted and needs to be validated. Now is a good a time as
of =pr_pack()=. I wanted to try fuzzing something, anything, with [[https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)][afl]] any to check OpenBSD's implementation of =pr_pack()=. I wanted to try
for a few years, but never got around to it. I thought I might as well fuzzing something, anything, with [[https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)][afl]] for a few years, but never got
do it now, might be fun. around to it. I thought I might as well do it now, might be fun.
* Make sure you are not holding it wrong. * Make sure you are not holding it wrong.
I installed =afl++= from packages and glanced at "[[https://aflplus.plus/docs/tutorials/libxml2_tutorial/][Fuzzing libxml2 with I installed =afl++= from packages and glanced at
AFL++]]". "[[https://aflplus.plus/docs/tutorials/libxml2_tutorial/][Fuzzing libxml2 with AFL++]]". Here is what we need:
Here is what we need:
+ A program to test. Something with a know bug so that we can tell the + A program to test. Something with a know bug so that we can tell the
fuzzing works. fuzzing works.
+ A file as input, that does not trigger the bug. + An input file, that does not trigger the bug.
+ Compile the program with =afl-clang-fast=. + Compile the program with =afl-clang-fast=.
+ Run =afl-fuzz=. + Run =afl-fuzz=.
@ -85,12 +84,12 @@ Here is what we need:
} }
#+end_src #+end_src
This program has a trivial buffer overflow. It figures out how big a This program has a trivial buffer overflow. It figures out how big a
file is on disk and stores this in =fsize=. Then it goes ahead and file is on disk and stores this in =fsize=. It allocates a buffer of
reads the whole file into a buffer. It interprets the first byte as this size and then reads the whole file into it. It interprets the
the length of data (=len=) and allocates a new buffer (=dbuf=) of this first byte as the length of the data (=len=) and allocates a new
size. It skips the length byte and copies =fsize - 1= bytes into the buffer (=dbuf=) of this size. It skips the length byte and copies
new buffer. So it trusts that the amount of data it read from disk is =fsize - 1= bytes into the new buffer. So it trusts that the amount of
the same as indicated by the length byte. data it read from disk is the same as indicated by the length byte.
While this might seem silly, this is how real world buffer overflows While this might seem silly, this is how real world buffer overflows
look like. look like.
@ -120,16 +119,17 @@ At this point we are facing a few problems. What does it mean to fuzz
=ping(8)=, where are we getting the sample input from and how do we feed =ping(8)=, where are we getting the sample input from and how do we feed
it to =ping(8)=. it to =ping(8)=.
From a high level point of view =ping(8)= parses arguments, initializes From a high level point of view =ping(8)= parses arguments,
a bunch of stuff and then enters an infinite loop sending ICMP echo initializes a bunch of stuff and then enters an infinite loop sending
packets and waiting for a reply. It then parses and prints the reply. ICMP echo request packets and waiting for a reply. It parses and
prints each reply.
Parsing the reply is the interesting thing. The reply comes from the Parsing the reply is the interesting thing. The reply comes from the
network and is untrusted. This is where things go wrong. The parsing network and is untrusted. This is where things can go wrong. The
is handled by =pr_pack()=, so that's what we should fuzz. parsing is handled by =pr_pack()=, so that's what we should fuzz.
** =in/= for =ping(8)= ** =in/= for =ping(8)=
Now we need sample data. An ICMP package is binary data We need some sample data. An ICMP package is binary data
on-wire. Crafting it by hand is annoying. So let's just hack =ping(8)= on-wire. Crafting it by hand is annoying. So let's just hack =ping(8)=
to dump the packet to disk. to dump the packet to disk.
#+begin_src diff #+begin_src diff
@ -280,7 +280,7 @@ single ping and wait for one second. The ICMP reply is written to
** Fuzzing =pr_pack()= ** Fuzzing =pr_pack()=
At this point I wrote a =main()= function that accepts a file name as At this point I wrote a =main()= function that accepts a file name as
argument, and reads it into a buffer. I then ripped =pr_pack()= out of argument and reads it into a buffer. I then ripped =pr_pack()= out of
=ping(8)= and fed it the file contents. =ping(8)= and fed it the file contents.
Of course compiling fails quite spectacularly at this point. So I Of course compiling fails quite spectacularly at this point. So I
@ -292,19 +292,20 @@ is that the data does not validate and =SipHash= would short circuit.
Oh yeah, and the thing is legacy IP only at this point. Oh yeah, and the thing is legacy IP only at this point.
So [[file:fuzzing-ping/afl_ping.c][here (=afl_ping.c=)]] it is, it is quite terrible. It would probably make more sense So [[file:fuzzing-ping/afl_ping.c][here (=afl_ping.c=)]] it is, it is quite terrible. It would probably
to copy all of =ping(8)= and slap on a new =main()= function. Maybe. make more sense to copy all of =ping(8)= and slap on a new =main()=
function. Maybe.
Anyway, at this point I was 30 minutes in, from reading about afl for Anyway, at this point I was 30 minutes in, from reading about afl for
the first time until firing up =afl-fuzz= on my hacked the first time until firing up =afl-fuzz= on my hacked
=pr_pack()=. Not too bad. It was now time for dinner and I left the =pr_pack()=. Not too bad. It was time for dinner and I left the thing
thing running. running.
** The promised bug ** The promised bug
I came back after dinner and afl found zero crashes. That's I came back after dinner and afl found zero crashes. That's
disappointing. Or good. Depending on how you look at it. But it found disappointing. Or good. Depending on how you look at it. But it found
hangs. Running =afl_ping= on one of the reproducers, it printed hangs. Running =afl_ping= on one of the reproducers, it printed
=unknown option 20= forever. "=unknown option 20=" forever.
The problem is in this part of the code: The problem is in this part of the code:
#+begin_src C #+begin_src C