Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!


TUCoPS :: Linux :: Apps A-M :: b06-3382.htm

Libwmf integer/heap overflow



libwmf integer/heap overflow
libwmf integer/heap overflow



Sorry I don't have time to chase down multiple email addresses of alleged
developers; so here this is after weeks of no response.  POC is not attached
unlike advisory says.  It's not very difficult to exploit.

++++++++++++++++++++++++++++++++++++++++++++

Subject:

libwmf integer/heap overflow

++++++++++++++++++++++++++++++++++++++++++++

Product:

libwmf is a library for reading vector images in Micros=F8ft's native Wind=F8ws
Metafile Format (WMF) and for either (a) displaying them in, e.g., an X window;
or (b) converting them to more standard/open file formats such as, e.g., the
W3C's XML-based Scaleable Vector Graphic (SVG) format.

http://wvware.sourceforge.net/libwmf.html 

++++++++++++++++++++++++++++++++++++++++++++

Vulnerable:

I tested the most recent release, 0.2.8.4

++++++++++++++++++++++++++++++++++++++++++++

Summary:

An integer overflow in memory allocation leads to a heap overflow.

++++++++++++++++++++++++++++++++++++++++++++

Details:


-------------------------------------------------------------------------------
file: src/meta.c +117
-------------------------------------------------------------------------------


wmf_error_t wmf_header_read (wmfAPI* API)
{	U16 u16a;
	U16 u16b;

    ...snip...


	if (API->File->wmfheader->HeaderSize == 9)
	{	API->File->wmfheader->Version       = wmf_read_16 (API);
		API->File->wmfheader->FileSize      = wmf_read_32 (API,0,0);
		API->File->wmfheader->NumOfObjects  = wmf_read_16 (API);
1]		API->File->wmfheader->MaxRecordSize = wmf_read_32 (API,0,0);
		API->File->wmfheader->NumOfParams   = wmf_read_16 (API);


        1) This value is taken directly from the wmf file, later it will be used
        to allocate memory.  It is not sanitized at any point.


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

-------------------------------------------------------------------------------
file: src/player.c +86
-------------------------------------------------------------------------------


wmf_error_t wmf_scan (wmfAPI* API,unsigned long flags,wmfD_Rect* d_r)
{	wmfPlayer_t* P  = (wmfPlayer_t*) API->player_data;


    ...snip...

	wmf_header_read (API);

    ...snip...

1]

/*	P->Parameters = (unsigned char*) wmf_malloc (API,(MAX_REC_SIZE
(API)-3) * 2 * sizeof (unsigned char)); */	P->Parameters = (unsigned
char*) wmf_malloc (API,(MAX_REC_SIZE(API)  ) * 2 * sizeof (unsigned
char));   /* HOLE */


	WmfPlayMetaFile (API);



        1) Overflow the calculation.


    **************************

 
static wmf_error_t WmfPlayMetaFile (wmfAPI* API)
{	int i;
	int byte;
	int changed;

	unsigned char* Par;


    ...snip...


1]	Par = P->Parameters;


    ...snip...

	number = 0;
	do
	{	if (++number < API->store.count)
		{	atts = API->store.attrlist + number;
		}
		else
		{	atts = &attrlist;
			wmf_attr_clear (API, atts);
		}

2]		Size     = wmf_read_32 (API,0,0);
		Function = wmf_read_16 (API);

		if ((Size == 3) && (Function == 0))
		{	if (SCAN (API)) wmf_write (API, Size, Function,
"empty", atts->atts, 0, 0);
			break; /* Probably final record ?? */
		}

/*		if ((Size > MAX_REC_SIZE (API)) || (Size < 3))
 */		if (((Size - 3) > MAX_REC_SIZE (API)) || (Size < 3))
		{	WMF_ERROR (API,"libwmf: wmf with bizarre record size;
bailing..."); WMF_ERROR (API,"        please send it to us at
http://www.wvware.com/"); wmf_printf (API,"maximum record size = %u\n", 
(unsigned) MAX_REC_SIZE (API)); wmf_printf (API,"record size = %u\n",(unsigned)
Size); API->err = wmf_E_BadFormat;
			break;
		}

		pos_params = WMF_TELL (API);

		if (pos_params < 0)
		{	WMF_ERROR (API,"API's tell() failed on input stream!");
			API->err = wmf_E_BadFile;
			break;
		}

3]		for (i = 0; i < ((Size - 3) * 2); i++)
		{	byte = WMF_READ (API);
			if (byte == (-1))
			{	WMF_ERROR (API,"Unexpected EOF!");
				API->err = wmf_E_EOF;
				break;
			}
			Par[i] = (unsigned char) byte;  /* VECTOR */
		}


    1) Points to the memory we allocated above.

    2) Controls the number of bytes we write into the buffer.

    3) Overflow the buffer by arbitrarily huge amounts.

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

++++++++++++++++++++++++++++++++++++++++++++

Mitigating factors:

None.

++++++++++++++++++++++++++++++++++++++++++++

Workaround:

Do not open up untrusted wmf files.

++++++++++++++++++++++++++++++++++++++++++++

Notes:

libwmf is used by:

wv
abiword
freetype
gimp
libgsf
imagemagick

++++++++++++++++++++++++++++++++++++++++++++


Exploits:

POC is provided that crashes in free().  The easiest way to test is to use the
example conversion programs that come with libwmf, they are found in the
src/convert/.libs directory:


sean@hydra:~/libwmf-0.2.8.4/src/convert/.libs$ gcc -Wall exwmf.c 
sean@hydra:~/libwmf-0.2.8.4/src/convert/.libs$ ./a.out > evil.wmf 
sean@hydra:~/libwmf-0.2.8.4/src/convert/.libs$ gdb wmf2x 
GNU gdb 6.3-debian

(gdb) r evil.wmf
Starting program: /home/sean/libwmf-0.2.8.4/src/convert/.libs/wmf2x evil.wmf
ERROR: player.c (482): Unexpected EOF!

Program received signal SIGSEGV, Segmentation fault.
0x402d5354 in mallopt () from /lib/libc.so.6
(gdb) bt
#0  0x402d5354 in mallopt () from /lib/libc.so.6
#1  0x402d415f in free () from /lib/libc.so.6
#2  0x402c283b in fclose () from /lib/libc.so.6
#3  0x4006e10e in wmf_file_close (API=0x804ad38) at bbuf.c:137
#4  0x4006d7d8 in wmf_lite_destroy (API=0x804ad38) at api.c:336
#5  0x40021e6f in wmf_api_destroy (API=0x804ad38) at wmf.c:167
#6  0x08048aec in wmf2x_draw (pdata=0xbffff8a0) at wmf2x.c:279
#7  0x08049518 in main (argc=1229353872, argv=0x49467390) at wmf2x.c:401

(gdb) up 1
#1  0x402d415f in free () from /lib/libc.so.6

(gdb) x/4x $ebp
0xbffff654:     0xbffff688      0x402c283b      0x08053258      0x00000000
                                                ^^^
                                                chunk being free()'d


(gdb) x/30x 0x08053258-16
0x8053248:      0x41414141      0x41414141      0x41414141      0x41414141
                                                ^^^^^
                                                chunk header


0x8053258:      0x00000000      0x40087000      0x40087000      0x40087000
0x8053268:      0x40087000      0x40087000      0x40087000      0x40087000
0x8053278:      0x40088000      0x00000000      0x00000000      0x00000000
0x8053288:      0x00000000      0x4038c440      0x00000006      0x00000000
0x8053298:      0x0804bb70      0x08000000      0x080532f0      0x00001018
0x80532a8:      0x00000000      0x0804bbe8      0x08053308      0xffffffff
0x80532b8:      0x0804bc30      0x0804bc40
(gdb)

++++++++++++++++++++++++++++++++++++++++++++


-- 
[ sean ]
[ pgp key id: 0x421C8CD9 ]
[ The advantage of a bad memory is that one enjoys several ]
[ times the same good things for the first time. ]



TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH