[UNIX] chmlib Buffer Overflow (Technical Details)
From: SecuriTeam (support_at_securiteam.com)
Date: 10/31/05
- Previous message: SecuriTeam: "[UNIX] SCO Multiple Local Buffer Overflow"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 31 Oct 2005 08:59:31 +0200
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
chmlib Buffer Overflow (Technical Details)
------------------------------------------------------------------------
SUMMARY
CHMLIB is "a library for dealing with Microsoft ITSS/CHM format files.
Right now, it is a very simple library, but sufficient for dealing with
all of the .chm files I've come across. Due to the fairly well-designed
indexing built into this particular file format, even a small library is
able to gain reasonably good performance indexing into ITSS archives".
chmlib has been found to be vulnerable to a buffer overflow, allowing
attacker to execute arbitrary code.
DETAILS
Vulnerable Systems:
* chmlib version 0.36 and prior.
Immune Systems:
* CHM lib version 0.37 (download
<http://morte.jedrea.com/%7Ejedwin/projects/chmlib/chmlib-0.37.2.tgz>
here)
* CHM lib version 0.37.2 (download
<http://morte.jedrea.com/%7Ejedwin/projects/chmlib/chmlib-0.37.tgz> here)
0. chm_lib.c: _chm_decompress_block(struct chmFile *h, UInt64 block,UChar
**ubuffer)
1. see cmpLen and cbuffer declaration
2. call to _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) to set
cmpLen
3. cmpLen is used to offset write operations in cbuffer
(_chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen))
4. if cmpLen > h->reset_table.block_len + 6144 the buffer overflows
5. as we can supply the fd data, exploitation is possible and an attacker
can execute arbitrary code.
Vulnerable code:
/* decompress the block. must have lzx_mutex. */
static Int64 _chm_decompress_block(struct chmFile *h,
UInt64 block,
UChar **ubuffer)
{
..
UChar cbuffer[h->reset_table.block_len + 6144]; /* compressed
buffer */
Int64 cmpLen; /* compressed
len */
..
..
..
..
if (! _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen)
||
_chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen
||
LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen,
(int)h->reset_table.block_len) != DECR_OK)
{
..
-----------------------------
/* get the bounds of a compressed block. return 0 on failure */
static int _chm_get_cmpblock_bounds(struct chmFile *h,
UInt64 block,
UInt64 *start,
Int64 *len)
{
UChar buffer[8], *dummy;
unsigned int remain;
/* for all but the last block, use the reset table */
if (block < h->reset_table.block_count-1)
{
...
...
/* unpack the end address */
dummy = buffer;
remain = 8;
if (_chm_fetch_bytes(h, buffer,
(UInt64)h->data_offset
+ (UInt64)h->rt_unit.start
+ (UInt64)h->reset_table.table_offset
+ (UInt64)block*8 + 8,
remain) != remain
||
!_unmarshal_int64(&dummy, &remain, len))
return 0;
}
/* for the last block, use the span in addition to the reset table */
else
{
...
}
/* compute the length and absolute start address */
*len -= *start;
*start += h->data_offset + h->cn_unit.start;
return 1;
}
--------------
/*
* dest(len) is read out of the fd
*/
static int _unmarshal_int64(unsigned char **pData,
unsigned int *pLenRemain,
Int64 *dest)
{
Int64 temp;
int i;
if (8 > *pLenRemain)
return 0;
temp=0;
for(i=8; i>0; i--)
{
temp <<= 8;
temp |= (*pData)[i-1];
}
*dest = temp;
*pData += 8;
*pLenRemain -= 8;
return 1;
}
---------------
/* utility function to handle differences between {pread,read}(64)? */
static Int64 _chm_fetch_bytes(struct chmFile *h,
UChar *buf,
UInt64 os,
Int64 len)
{
Int64 readLen=0, oldOs=0;
if (h->fd == CHM_NULL_FD)
return readLen;
CHM_ACQUIRE_LOCK(h->mutex);
..
readLen = pread(h->fd, buf, (long)len, (unsigned int)os);
..
CHM_RELEASE_LOCK(h->mutex);
return readLen;
}
Disclosure Timeline:
24.10.05 - Issue found by Sven Tantau
25.10.05 - Contacted chmlib maintainer
25.10.05 - Quick reaction with confirmation
26.10.05 - New release of chmlib and public disclosure
Vendor Status:
chmlib maintainer Jed Wing released a new version 0.37
ADDITIONAL INFORMATION
The information has been provided by <mailto:sven@sven-tantau.de> Sven
Tantau.
The original article can be found at:
<http://www.sven-tantau.de/public_files/chmlib/chmlib_20051126.txt>
http://www.sven-tantau.de/public_files/chmlib/chmlib_20051126.txt
========================================
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com
====================
====================
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.
- Previous message: SecuriTeam: "[UNIX] SCO Multiple Local Buffer Overflow"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|