Fuzzing101

CVE-2019-13288 in XPDF 3.02

build:

build.sh:

#!/bin/sh
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --prefix=$PWD/bd
make

fuzzing:

start.sh:

#!/bin/sh
afl-fuzz -i $PWD/ipt -o $PWD/opt -s 123 -m none -- $PWD/bd/bin/pdftotext @@ $PWD/output

we get crash below :


 american fuzzy lop ++4.09a {default} (.../xpdf-3.02/bd/bin/pdftotext) [fast]
┌─ process timing ────────────────────────────────────┬─ overall results ────┐
│        run time : 0 days, 0 hrs, 48 min, 47 sec     │  cycles done : 0     │
│   last new find : 0 days, 0 hrs, 0 min, 4 sec       │ corpus count : 782   │
│last saved crash : 0 days, 0 hrs, 7 min, 51 sec      │saved crashes : 5     │
│ last saved hang : 0 days, 0 hrs, 4 min, 29 sec      │  saved hangs : 2     │
├─ cycle progress ─────────────────────┬─ map coverage┴──────────────────────┤
│  now processing : 781.0 (99.9%)      │    map density : 2.81% / 4.58%      │
│  runs timed out : 0 (0.00%)          │ count coverage : 4.10 bits/tuple    │
├─ stage progress ─────────────────────┼─ findings in depth ─────────────────┤
│  now trying : trim 64/64             │ favored items : 63 (8.06%)          │
│ stage execs : 47/384 (12.24%)        │  new edges on : 138 (17.65%)        │
│ total execs : 1.10M                  │ total crashes : 5 (5 saved)         │
│  exec speed : 321.8/sec              │  total tmouts : 37 (0 saved)        │
├─ fuzzing strategy yields ────────────┴─────────────┬─ item geometry ───────┤
│   bit flips : disabled (default, enable with -D)   │    levels : 21        │
│  byte flips : disabled (default, enable with -D)   │   pending : 557       │
│ arithmetics : disabled (default, enable with -D)   │  pend fav : 2         │
│  known ints : disabled (default, enable with -D)   │ own finds : 780       │
│  dictionary : n/a                                  │  imported : 0         │
│havoc/splice : 572/451k, 213/333k                   │ stability : 100.00%   │
│py/custom/rq : unused, unused, unused, unused       ├───────────────────────┘
│    trim/eff : 3.39%/310k, disabled                 │          [cpu000:  6%]
└─ strategy: explore ────────── state: in progress ──┘

analyze:

use tmin to minimize the crashes

#!/bin/sh
mkdir -p $PWD/opt/default/minimized
for i in $PWD/opt/default/crashes/id* ; do afl-tmin -i $i -o $PWD/opt/default/minimized/`basename $i` -- $PWD/bd/bin/pdftotext @@ $PWD/output ; done

rebuild with dbg symbols and feed the crash sample
gdb dbg:

 gdb --args ./pdftotext id:000000,sig:11,src:000499,time:429922,execs:198634,op:havoc,rep:4 ./1
 start

step to the crash point and look up backtrace , we entered a infinete loop at src Parser.cc:94

[#0] Id 1, Name: "pdftotext", stopped 0x7ffff7af1e57 in _int_malloc (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7af1e57 → _int_malloc(av=0x7ffff7c68c80 <main_arena>, bytes=0x158)
[#1] 0x7ffff7af3262 → __GI___libc_malloc(bytes=0x158)
[#2] 0x7ffff7e2c98c → operator new(unsigned long)()
[#3] 0x5555555e2ca3 → FileStream::makeSubStream(this=0x555555693c00, startA=0xa, limitedA=0x0, lengthA=0x0, dictA=0x7fffff7ff130)
[#4] 0x5555555f7a7c → XRef::fetch(this=0x555555695230, num=0x4, gen=0x0, obj=0x7fffff7ff1e0)
[#5] 0x5555555e016f → Object::dictLookup(obj=0x7fffff7ff1e0, key=0x55555560c1c6 "Length", this=0x7fffff7ff3a0)
[#6] 0x5555555e016f → Parser::makeStream(this=0x555556bc5a60, dict=0x7fffff7ff3a0, fileKey=0x0, encAlgorithm=cryptRC4, keyLength=0x0, objNum=0x4, objGen=0x0)
[#7] 0x5555555e071c → Parser::getObj(this=0x555556bc5a60, obj=0x7fffff7ff3a0, fileKey=0x0, encAlgorithm=cryptRC4, keyLength=0x0, objNum=0x4, objGen=0x0)
[#8] 0x5555555f7bbd → XRef::fetch(this=0x555555695230, num=0x4, gen=0x0, obj=0x7fffff7ff3a0)
[#9] 0x5555555e016f → Object::dictLookup(obj=0x7fffff7ff3a0, key=0x55555560c1c6 "Length", this=0x7fffff7ff560)

here causes a recursion, will finally run out of stack memory

mitigation:

#define recursionLimit 500 and exit after reaching the limit .

CVE-2009-3895 CVE-2012-2836 in libexif 0.6.14