another round of proof reading
This commit is contained in:
parent
d8a71ff8d4
commit
ccee218d26
@ -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
|
||||
fun things this week. So let's have some fun.
|
||||
|
||||
Step two: FreeBSD had a problem in =pr_pack()= because that function
|
||||
handles data from the network. The data is untrusted and needs to be
|
||||
validated. Now is a good time as any to check OpenBSD's implementation
|
||||
of =pr_pack()=. I wanted to try fuzzing something, anything, with [[https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)][afl]]
|
||||
for a few years, but never got around to it. I thought I might as well
|
||||
do it now, might be fun.
|
||||
Step two: Did we mess something else up? FreeBSD had a problem in
|
||||
=pr_pack()= because that function handles data from the network. The
|
||||
data is untrusted and needs to be validated. Now is a good a time as
|
||||
any to check OpenBSD's implementation of =pr_pack()=. I wanted to try
|
||||
fuzzing something, anything, with [[https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)][afl]] for a few years, but never got
|
||||
around to it. I thought I might as well do it now, might be fun.
|
||||
|
||||
* 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
|
||||
AFL++]]".
|
||||
Here is what we need:
|
||||
I installed =afl++= from packages and glanced at
|
||||
"[[https://aflplus.plus/docs/tutorials/libxml2_tutorial/][Fuzzing libxml2 with AFL++]]". Here is what we need:
|
||||
+ A program to test. Something with a know bug so that we can tell the
|
||||
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=.
|
||||
+ Run =afl-fuzz=.
|
||||
|
||||
@ -85,12 +84,12 @@ Here is what we need:
|
||||
}
|
||||
#+end_src
|
||||
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
|
||||
reads the whole file into a buffer. It interprets the first byte as
|
||||
the length of data (=len=) and allocates a new buffer (=dbuf=) of this
|
||||
size. It skips the length byte and copies =fsize - 1= bytes into the
|
||||
new buffer. So it trusts that the amount of data it read from disk is
|
||||
the same as indicated by the length byte.
|
||||
file is on disk and stores this in =fsize=. It allocates a buffer of
|
||||
this size and then reads the whole file into it. It interprets the
|
||||
first byte as the length of the data (=len=) and allocates a new
|
||||
buffer (=dbuf=) of this size. It skips the length byte and copies
|
||||
=fsize - 1= bytes into the new buffer. So it trusts that the amount of
|
||||
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
|
||||
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
|
||||
it to =ping(8)=.
|
||||
|
||||
From a high level point of view =ping(8)= parses arguments, initializes
|
||||
a bunch of stuff and then enters an infinite loop sending ICMP echo
|
||||
packets and waiting for a reply. It then parses and prints the reply.
|
||||
From a high level point of view =ping(8)= parses arguments,
|
||||
initializes a bunch of stuff and then enters an infinite loop sending
|
||||
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
|
||||
network and is untrusted. This is where things go wrong. The parsing
|
||||
is handled by =pr_pack()=, so that's what we should fuzz.
|
||||
network and is untrusted. This is where things can go wrong. The
|
||||
parsing is handled by =pr_pack()=, so that's what we should fuzz.
|
||||
|
||||
** =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)=
|
||||
to dump the packet to disk.
|
||||
#+begin_src diff
|
||||
@ -280,7 +280,7 @@ single ping and wait for one second. The ICMP reply is written to
|
||||
|
||||
** Fuzzing =pr_pack()=
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
So [[file:fuzzing-ping/afl_ping.c][here (=afl_ping.c=)]] it is, it is quite terrible. It would probably make more sense
|
||||
to copy all of =ping(8)= and slap on a new =main()= function. Maybe.
|
||||
So [[file:fuzzing-ping/afl_ping.c][here (=afl_ping.c=)]] it is, it is quite terrible. It would probably
|
||||
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
|
||||
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
|
||||
thing running.
|
||||
=pr_pack()=. Not too bad. It was time for dinner and I left the thing
|
||||
running.
|
||||
|
||||
** The promised bug
|
||||
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
|
||||
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:
|
||||
#+begin_src C
|
||||
|
Loading…
Reference in New Issue
Block a user