[ advisories | exploits | discussions | news | conventions | security tools | texts & papers ]
 main menu
- feedback
- advertising
- privacy
- FightAIDS
- newsletter
- news
 
 discussions
- read forum
- new topic
- search
 

 meetings
- meetings list
- recent additions
- add your info
 
 top 100 sites
- visit top sites
- sign up now
- members
 
 webmasters

- add your url
- add domain
- search box
- link to us

 
 projects
- our projects
- free email
 
 m4d network
- security software
- secureroot
- m4d.com
Home : Advisories : JPEG COM Marker Processing Vulnerability in Netscape Browsers

Title: JPEG COM Marker Processing Vulnerability in Netscape Browsers
Released by: Openwall
Date: 25th July 2000
Printable version: Click here
-----BEGIN PGP SIGNED MESSAGE-----



OW-002-netscape-jpeg, revision 1

July 25, 2000



 JPEG COM Marker Processing Vulnerability in Netscape Browsers

 -------------------------------------------------------------



This advisory explains a vulnerability in Netscape browsers present

since at least version 3.0 and up to Netscape 4.73 and Mozilla M15.

The vulnerability is fixed in Netscape 4.74 and Mozilla M16.





 Impact

 ------



It may be possible, although hard to do reliably in a real-world

attack, for a malicious web site to execute arbitrary assembly code

in the context of the web browser.  In the case of Netscape Mail or

News, the attack may be performed via a mail message or a news

article, as well.





 Vulnerability details

 ---------------------



JPEG interchange format streams consist of an ordered collection of

markers, parameters, and entropy-coded data segments.  Many markers

start marker segments, which consist of the marker followed by a

sequence of related parameters.  Marker segments are of a variable

length, with the first parameter being the two-byte length.  The

encoded length includes the size of the length parameter itself.

Thus, lengths smaller than 2 are always invalid.



Netscape browsers use the Independent JPEG Group's decoder library

for JPEG File Interchange Format (JFIF) files.  However, they install

a custom handler for processing the COM (comment) marker that stores

the comment in memory rather than just skip it like the library would

do.  Unfortunately, the new handler doesn't check whether the length

field is valid, and subtracts 2 from the encoded length to calculate

the length of the comment itself.  It then allocates memory for the

comment (with one additional byte for its NUL termination) and goes

into a loop to read the comment into that memory.



By setting the length field to 1, it is possible to ensure the memory

allocation call (of 0 bytes) will succeed.  As the calculated comment

length is declared unsigned, it will be a huge positive value rather

than a small negative one, so the loop won't terminate until the end

of JPEG stream.  It will read the JPEG stream onto the heap, possibly

overwriting other dynamically allocated buffers of Netscape, as well

as structures internal to the malloc(3) implementation.  Exploiting

this vulnerability into executing arbitrary code is non-trivial, but

possible on some platforms.





 The real problem

 ----------------



Is this problem in the lack of error checking in the code?  Indeed.

A programmer's fault.  Is this a problem because of the choice of a

programming language that doesn't offer overflow checking and with

compilers that traditionally don't offer bound checking?  Partially.



However, let's see how many different file formats, languages, and

protocols a modern web browser has to support.  Have all of the file

parsers been initially implemented with intent to be robust against

untrusted and possibly malicious data?  If not, have all possible

cases been covered with additional checks now?  Do we have a reason

to believe there're no bugs in the implementation of any of those, or

do we have reasons to suspect the opposite?



Solutions?  There's little an end user can do, but you can take this

advisory as yet another reminder to run the web browser you use to

access untrusted content in a restricted environment, without access

to your most critical data.  Unfortunately, this isn't easy to do in

the Win32 world, yet.





 Fixes

 -----



Upgrade to Netscape 4.74 or Mozilla M16, or newer.



Alternatively, Mozilla users can apply the following patch (against

Milestone 15) and rebuild the sources:



- --- mozilla/modules/libimg/jpgcom/jpeg.cpp.orig Tue Mar 28 02:08:15 2000

+++ mozilla/modules/libimg/jpgcom/jpeg.cpp Wed May 24 17:24:03 2000

@@ -469,6 +469,10 @@



     /* Get 16-bit comment length word. */

     INPUT_2BYTES(cinfo, length, return FALSE);

+    if (length < 2) {

+ cinfo->err->msg_code = JERR_BAD_LENGTH;

+ il_error_exit((j_common_ptr)cinfo);

+    }

     length -= 2;            /* discount the length word itself */



     PR_FREEIF(ic->comment);





 Workaround

 ----------



Included in the archive accompanying this advisory (see below) is an

unofficial binary patch for older versions of Netscape browsers on

some platforms.  Source code and a Win32 binary of the patch program

are provided.  You should only use the patch if you can't upgrade to

a fixed version.  There's absolutely no warranty.



This patch prevents the browser from installing its own COM marker

handler rather than fix the handler itself.  The latter would require

extra code and result in much larger search patterns that wouldn't

apply to as many versions of Netscape.



Please note that this may refuse to apply to your version of Netscape,

or this may not work for you.  Be sure to check that the patch has

worked as intended by trying to display the demonstration JFIF file

(crash.jpg).  Your browser should no longer crash, and you should see

an image identical to that in valid.jpg (even though crash.jpg is in

fact an invalid JFIF file, but that isn't a security issue any longer

and is just the way the Independent JPEG Group's library works).





 Exploiting the vulnerability

 ----------------------------



The vulnerability lets us overwrite heap locations beyond the end of

allocated area.  We're limited to printable characters, NUL, and LF.

Thus, the ability to exploit this into doing more than a crash will

depend on locale settings on some platforms.



First, we need to decide on what we overwrite.  Structures internal

to the dynamic memory implementation are the most promising target:

they're always there and they typically contain pointers.



For the example below, we'll assume Doug Lea's malloc (which is used

by most Linux systems, both libc 5 and glibc) and locale for an 8-bit

character set (such as most locales that come with glibc, including

en_US, or ru_RU.KOI8-R).



The following fields are kept for every free chunk on the list: size

of the previous chunk (if free), this chunk's size, and pointers to

next and previous chunks.  Additionally, bit 0 of the chunk size is

used to indicate whether the previous chunk is in use (LSB of actual

chunk size is always zero due to the structure size and alignment).



By playing with these fields carefully, it is possible to trick calls

to free(3) into overwriting arbitrary memory locations with our data.

free(3) checks if a chunk adjacent to the one being freed is in use

and, if not, consolidates the two chunks by unlinking the adjacent

chunk from the list.  Unlinking a chunk involves setting the previous

chunk's "next" pointer and the next chunk's "previous" pointer, where

both of these chunks are addressed via pointers from the chunk being

unlinked.  Thus, in order to get control over these memory writes, we

need to overwrite the two pointers within a chunk (or maybe allocated

memory at the time) and preferably reset the PREV_INUSE flag of the

next chunk.  This takes 13 bytes on a 32-bit little endian, such as

Linux/x86 (8 bytes for the two pointers, four bytes placeholder for

the previous size field, and 1 byte to reset the flag).  In practice,

we would want to repeat the desired 16-byte pattern (of which only 9

bytes matter) at least several times to increase our chances in case

of larger allocated chunks.



The overwritten pointers each serve as both the address and the data

being stored, which limits our choice of data: it has to be a valid

address as well, and memory at that address should be writable.



Now we need to decide what pointer we want to overwrite (there's not

that much use in overwriting a non-pointer with an address).  A good

candidate would be any return address on the stack.  That would work,

but not be very reliable as the location of a return address depends

on how much other data is on the stack, including program arguments,

and that is generally not known for a remote attack.  A better target

would be a function pointer.  We don't want to guess exact locations

on the stack and we can't get to the ELF sections on x86 (BS isn't a

printable character), so we're effectively limited to pointers within

shared libraries.  A nice one we can use is __free_hook, so that the

second call to free(3) will give us the control.  The debugging hooks

are always compiled in when Doug Lea's code is a part of GNU libc.



Our next decision is about where we want the control transferred.  We

would definitely prefer to have our "shellcode" within the JFIF file

itself.  However, the character set restriction might prevent us from

passing heap addresses.  We have to settle on the stack and place our

code in there via other parts of the browser prior to the overflow.

We can use a bunch of NOP's or equivalent to avoid having to provide

an exact stack location.



A compiler to produce JFIF files implementing the above approach is

included in the accompanying archive.



Please note that this is by no means limited to Linux/x86.  It's just

that one platform had to be chosen for the example.  So far, this is

known to be exploitable on at least one Win32 installation in a very

similar way (via ntdll!RtlFreeHeap).





 References

 ----------



Additional programs and example JFIF files mentioned in this advisory

are provided in the accompanying archive, which can be downloaded via

one of these links:



http://www.openwall.com/advisories/OW-002-netscape-jpeg-r1.tar.gz

http://www.openwall.com/advisories/OW-002-1.zip



MD5 (OW-002-netscape-jpeg-r1.tar.gz) = 05b9879474e6b8988cd3141760e07826

MD5 (OW-002-1.zip) = ea3a7febd3d8410382bcbf7463cf32a3



JPEG interchange format is documented in ISO International Standard

10918-1 and CCITT (now ITU-T) Recommendation T.81.



JFIF specification and the IJG library are available at:



http://ftp.uu.net/graphics/jpeg/





 Credits and contact information

 -------------------------------



This vulnerability was found and advisory written by Solar Designer

.  I would like to thank Kevin Murray of Netscape

Communications and many others from both the Mozilla community and

Netscape for their support in handling of this vulnerability.



Updated versions of this and other Openwall advisories will be made

available at:



http://www.openwall.com/advisories/



-----BEGIN PGP SIGNATURE-----

Version: 2.6.3ia

Comment: http://www.openwall.com/signatures/

Charset: noconv



iQCVAwUBOXzENXK5fbEpUCnxAQFNKgP/cdKHIjRSn8mNeKmS1UrBPjsAcZ8Q8a3q

YM/uPhSkccuCVI3t3zibIt1RxLaQtkCcFHJ8TQfFa0s420IT5LabRGM4xz77LNUs

EF9/86UP3KprycHwh953ETEOZlHZCrhkBvr0/W3LZp4qr4IzfXMDtm3uEORZR0U2

RxSc8Fe8Clc=

=0Sob

-----END PGP SIGNATURE-----








(C) 1999-2000 All rights reserved.