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
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user