Advertisement






libwmf integer/heap overflow

CVE Category Price Severity
CVE-2003-0201 CWE-119 Not available High
Author Risk Exploitation Type Date
Unknown High Local 2006-07-13
CPE
cpe:cpe:/a:wvware:libwmf:0.2.8
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H 0.105155 0.77784

CVSS vector description

Our sensors found this exploit at: http://cxsecurity.com/ascii/WLB-2006070039

Below is a copy:

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øft's native Windøws
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 = %un",
(unsigned) MAX_REC_SIZE (API)); wmf_printf (API,"record size = %un",(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. ]

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum