Let's Fuzz: IrfanView

When it comes to software security testing, fuzzing is both an effective and efficient way to exercise a program's inputs and outputs.  An introduction on fuzzing techniques and methodologies extends well beyond the scope of this post, so if you're new to the subject, I highly recommend picking up Fuzzing: Brute Force Vulnerability Discovery and familiarizing yourself with the concepts.  In the event that you don't feel like buying a book, there's a tremendous amount of information out there, freely available in the form of whitepapers and slide decks.

In this post, we'll be using the tool Failure Observation Engine (FOE) created by CERT against our target application, IrfanView, but first, let's talk about FOE.

FOE

From the FOE homepage:

The CERT Failure Observation Engine (FOE) is a software testing tool that finds defects in applications that run on the Windows platform. FOE performs mutational fuzzing on software that consumes file input.

This means that FOE operates as a blackbox fuzzer, because it has no understanding of the files/inputs that it's fuzzing.  To clarify, there are two types of fuzzing: generational and mutational.  A generational fuzzer generates files based on a known and/or defined file format/structure.  For example, the popular fuzzer Peach is a smartfuzzer that can generate files based on an XML representation of the file format.  In the case of FOE, it's a mutational fuzzer, which means that it consumes a valid file format without grammatically understanding its structure, mutates it, and sees what the program does with the malformed data.  This can be considered dumb fuzzing but that seems a bit harsh for such a useful tool.  And while we're talking about fuzzin' stuff, we need to keep in mind the concept of code coverage as it applies to security testing.  In an oversimplified sense, fuzzing and code coverage has to do with how much of a program's functionality can be exercised and observed in an automated fashion.  More coverage means better results, and smartfuzzers generally have better code coverage than dumb/blackbox fuzzers.

Another crucial component of any fuzzer, which FOE does very well, is the monitoring of the target process for crashes, exceptions, and other "interesting" behavior.  In the case of FOE, which we'll cover a little later, FOE uses Windbg and !exploitable (bang exploitable) to provide a superficial, albeit very useful, automated postmortem analysis when a crash is detected.  When an exception is detected, FOE will verify that the test case is reproducible, generate a minimum test case (more on this later), and triage the crash data into folders linked with the fuzzing campaign such as EXPLOITABLE, PROBABLY_EXPLOITABLE, UKNOWN, etc.

So what are we going to do with all of this?  Fuzz IrfanView (well its plugins, but still...)

IrfanView

From the IrfanView homepage:

IrfanView is a very fast, small, compact and innovative FREEWARE (for non-commercial use) graphic viewer for Windows 9x, ME, NT, 2000, XP, 2003 , 2008, Vista, Windows 7, Windows 8.

While IrfanView is a pretty great program, there isn't much to say about it that's relevant to this post other than the fact that it was chosen at random, well kind of.  IrfanView was chosen because of its plugins, which allows the program to open and manipulate a very wide variety of file formats.  In a world where file parsing bugs run rampant, this often makes for a very large attack surface as we'll see shortly.

FOE Quick and Dirty Config

CERT provides a fully documented sample configuration file that you can modify to suit your needs, but for the sake of getting up and running, we'll run through the key things to change.

id: irfanView    #This is the name of the campaign, change it to reflect the program you're fuzzing
keep_heisenbugs: False    #Heisenbug you may or may not want to keep these, I often don't

Further down...

target:
program: C:\IrfanView\i_view32.exe    #This is the path to your target executable
cmdline_template: $PROGRAM $SEEDFILE    #Template for command line execution.*

And more...

directories:
    seedfile_dir: seedfiles    #This is the directory that FOE will use to find good files to mutate
    working_dir:  C:\FOE2\fuzzdir    #leave this
    results_dir:  results    #leave this too

Finally, there's three other sections: runner, fuzzer, and runoptions.  Unless you have a specific need to change these, don't.  If you're just setting up FOE to work through this post, leave the values in those sections unchanged.

*By default, the config will append NUL to the end of the cmdline_template string.  For reasons I haven't investigated, this can result in improperly launching the target application, so if it doesn't look like it's doing what it says on the box, remove NUL from that line in the config.

So, at this point we have our working and configured fuzzer, and our target application, but we need files to fuzz to get us good (or better) code coverage.  Because we're using a mutational fuzzer, the more files we have to mutate, the better, and if you look at all of the file types supported by IrfanView, you're going to be pretty busy gathering seed files.  On a related note, because the plugins provided by IrfanView let you access so many file formats, I would chose breadth over depth on your first campaign, which is to say, test as many formats (seed files) as possible and worry about robustness for testing a specific format/parser later.

Execution

Fuzzing isn't like running a vulnerability scanner or other security tools; fuzzers can run for a very very long time, like weeks and months depending on how determined you are and how good your fuzzer is.  In this example fuzzing scenario, I started with 16 seed files covering 16 different formats, let the fuzzer run for approximately 5 days, and left with 37 unique crashes and 3 exploitable file parsing vulnerabilities.  At the time of writing, the AWD and SVG parsing flaws have been remediated by the lead developer, Irfan Skiljan, in conjunction with the unnamed plugin developer, and the turnaround time on this was awesome.  Any users impacted should update their plugins from IrfanView's official site.  Nice work Irfan & team!

So, moving on, as the fuzzer runs, interesting data will be stored in C:\FOE2\results\%campaignID% and categorized based the initial automated analysis of Windbg and !exploitable as seen below.

iview

Within these directories, you will have several files.  The files of immediate interest will be suffixed with .minimized .msec, and the initial file that caused the crash, something long and ugly like sf_dbf01ee90624694f3108c5f58c772036-53467-0x5ad70000.awd.  The .msec file is the text output of the Windbg crash analysis.  The .minimized file is a minimized test case that is the least significantly different from the original seed file that triggered the crash, and the original file that caused the crash which is pretty self explanatory.  As a rule of thumb, when you first start digging into the crash, load both the unmangled seed filet and the minimized file in a hex editor and do a byte-by-byte diff on the two files to see what mutated value caused the crash as seen in the next image.

ifmutate

For more in depth analysis of the crash and related events, review the Windbg output in the .msec file.  Pasted below is a trimmed portion of the .msec output related to the AWD parsing flaw.

Opened log file 'C:\FOE2\fuzzdir\campaign_djf435\iteration_ei3yur\foe-crash-up2nbd\sf_dbf01ee90624694f3108c5f58c772036-53467.awd.e1.msec'
...
(f4.ac4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=153faa91 ecx=3fffe160 edx=48c0215c esi=323fa19c edi=5ad70000
eip=00d76113 esp=0012edd8 ebp=0012ee04 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
AWD+0x56113:
00d76113 f3ab            rep stos dword ptr es:[edi]
0:000> g;r;!exploitable -v;q
(f4.ac4): Unknown exception - code 0eedfade (first chance)
(f4.ac4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=7ffde000 ebx=00000000 ecx=00ff0fa6 edx=00000022 esi=00ff0fa1 edi=0012f22c
eip=00d3b398 esp=0012f1c8 ebp=0012f1f0 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
<Unloaded_DLL>+0xd3b397:
00d3b398 ??              ???
Event Type: Exception
Exception Faulting Address: 0xd3b398
First Chance Exception Type: STATUS_ACCESS_VIOLATION (0xC0000005)
Exception Sub-Type: Read Access Violation
...
Description: Read Access Violation at the Instruction Pointer
Short Description: ReadAVonIP
Exploitability Classification: EXPLOITABLE
Recommended Bug Title: Exploitable - Read Access Violation at the Instruction Pointer starting at <Unloaded_DLL>+0x0000000000d3b397 (Hash=0x0243412e.0x60134464)

Access violations at the instruction pointer are exploitable if not near NULL.

Additional investigation of the crash and exploitability is left as an exercise to the reader, if you're so inclined.

And that's where we wrap up!  We've taken a quick look at FOE, fuzzed a real world application, found some bugs, got them fixed and now we can go back to relaxing, or continue fuzzing for more bugs.  Between now and the next post, if you want more information on things such as protocol and browser fuzzers, check out the additional resources such as PacketStorm and fuzzinginfo.org!