Advisory: chmlib exploitable buffer overflow Product: chmlib Affected Version: <=0.36 Immune Version: >0.36 OS: Tested on linux 2.4 probably other OS affected as well Date: 26.10.2005 Author: Sven Tantau - http://www.sven-tantau.de/ Vendor-URL: http://morte.jedrea.com/%7Ejedwin/projects/chmlib/ Vendor-Status: informed, vendor released a fixed version Advisory-URL: http://www.sven-tantau.de/public_files/chmlib/chmlib_20051126.txt Product ======= >> From chmlib/README chmlib is a small library designed for accessing MS ITSS files. The ITSS file format is used for Microsoft Html Help files (.chm), which have been the predominant medium for software documentation from Microsoft during the past several years, having superceded the previously used .hlp file format. ... You can download the source code releases from http://morte.jedrea.com/%7Ejedwin/projects/chmlib/ Details ======= 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. (I am not going to release an exploit for this vulnerability to the public.) /* 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; } Solution ======== Update! chmlib maintainer Jed Wing released a new version 0.37 You can download the source code releases from: http://morte.jedrea.com/%7Ejedwin/projects/chmlib/ No need for my quick and dirty patch. History ======= 2005-10-24 issue found by Sven Tantau 2005-10-25 contacted chmlib maintainer 2005-10-25 quick reaction with confirmation 2005-10-26 new release of chmlib and public disclosure -- Sven Tantau
svyatogor, please provide a fixed ebuild
fyi: app-doc/kchmplayer includes a copy of chmlib. Unstable and fixed with v.1.1. Does the security team keep a list of applications including third party libs?
Thx carlo, I guess you mean kchmviewer and we don't keep a list of .... apps that include other apps (at least not yet). kchmplayer all fixed now.
*** Bug 111052 has been marked as a duplicate of this bug. ***
Sent an email to the maintainer, hope he will pick it up.
Sergey is on it.
In fact there are three buffer overflows : CVE-2005-2659 (fixed in >=0.36) Palasik Sandor discoverd a buffer overflow in the LZX decompression method. CVE-2005-2930 (fixed in >=0.36) A buffer overflow has been discovered that could lead to the execution of arbitrary code. CVE-2005-3318 (fixed in >=0.37) Sven Tantau discoverd a buffer overflow that could lead to the execution of arbitrary code. Ccing carlo so that he checks that kchmviewer-1.1 fixes all of them.
(In reply to comment #3) > kchmplayer all fixed now. Sorry for the confusing misnaming. :) (In reply to comment #7) > Ccing carlo so that he checks that kchmviewer-1.1 fixes all of them. kchmviewer-1.1 includes chmlib-0.37 and is marked testing anyways, so it's all fine.
Sergey any news on this one?
Created attachment 72982 [details] Ebuild for =app-doc/chmlib-0.36 Sending ebuild per jaervosz's request. I'd have sent an ebuild for app-doc/chmlib-0.37 too, but 0.37 does not `make install` on amd64, I received the following build error during the install phase: >>> Install chmlib-0.37 into /var/tmp/portage/chmlib-0.37/image/ category app-doc chmod a+r src/libchm.la mkdir -p /usr install -m0755 src/libchm.la /var/tmp/portage/chmlib-0.37/image//usr/lib64/ install -m0644 ./src/chm_lib.h /var/tmp/portage/chmlib-0.37/image//usr/include/ install -m0755 src/.libs/libchm.so.0.0.0 /var/tmp/portage/chmlib-0.37/image//usr/lib64/ ln -s /var/tmp/portage/chmlib-0.37/image//usr/lib64/libchm.so.0.0.0 /var/tmp/portage/chmlib-0.37/image//usr/lib64/libchm.so ln -s /var/tmp/portage/chmlib-0.37/image//usr/lib64/libchm.so.0.0.0 /var/tmp/portage/chmlib-0.37/image//usr/lib64/libchm.so.0 x86_64-pc-linux-gnu-gcc -o extract_chmLib src/extract_chmLib.c -I/usr/include -L/usr/lib64 -lchm -march=k8 -O3 -pipe -DCHM_MT -DCHM_USE_PREAD -DCHM_USE_IO64 -DDMALLOC_DISABLE /usr/lib/gcc/x86_64-pc-linux-gnu/3.4.4/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lchm collect2: ld returned 1 exit status make: *** [extract_chmLib] Error 1 !!! ERROR: app-doc/chmlib-0.37 failed. !!! Function src_install, Line 54, Exitcode 2 !!! (no error message) !!! If you need support, post the topmost build error, NOT this status message. localhost chmlib # emerge --info Portage 2.0.53_rc7 (default-linux/amd64/2005.0, gcc-3.4.4, glibc-2.3.5-r3, 2.6.14-gentoo x86_64) ================================================================= System uname: 2.6.14-gentoo x86_64 AMD Opteron(tm) Processor 242 Gentoo Base System version 1.12.0_pre10 dev-lang/python: 2.3.5, 2.4.2 sys-apps/sandbox: 1.2.13 sys-devel/autoconf: 2.13, 2.59-r7 sys-devel/automake: 1.4_p6, 1.5, 1.6.3, 1.7.9-r1, 1.8.5-r3, 1.9.6-r1 sys-devel/binutils: 2.16.1 sys-devel/libtool: 1.5.20-r1 virtual/os-headers: 2.6.11-r2 ACCEPT_KEYWORDS="amd64 ~amd64" AUTOCLEAN="yes" CBUILD="x86_64-pc-linux-gnu" CFLAGS="-march=k8 -O3 -pipe" CHOST="x86_64-pc-linux-gnu" CONFIG_PROTECT="/etc /usr/kde/2/share/config /usr/kde/3.2/share/config /usr/kde/3.3/env /usr/kde/3.3/share/config /usr/kde/3.3/shutdown /usr/kde/3.4/env /usr/kde/3.4/share/config /usr/kde/3.4/shutdown /usr/kde/3/share/config /usr/lib/X11/xkb /usr/share/config /var/qmail/control" CONFIG_PROTECT_MASK="/etc/gconf /etc/terminfo /etc/env.d" CXXFLAGS="-march=k8 -O3 -pipe" DISTDIR="/usr/portage/distfiles" FEATURES="autoconfig distlocks sandbox sfperms strict" GENTOO_MIRRORS="ftp://ftp.gtlib.cc.gatech.edu/pub/gentoo" MAKEOPTS="-j3" PKGDIR="/usr/portage/packages" PORTAGE_TMPDIR="/var/tmp" PORTDIR="/usr/portage" PORTDIR_OVERLAY="/usr/local/portage" SYNC="rsync://rsync.gentoo.org/gentoo-portage" USE="X alsa amd64 apache2 apm arts audiofile avi bitmap-fonts bonobo bzip2 cgi cli crypt cups curl cvs dba dvdr dvdread eds emboss encode esd ethereal exif expat fam ffmpeg flac foomaticdb fortran ftp gcj gd gdbm gif glut gnome gpm gstreamer gtk gtk2 gtkhtml idn imagemagick imlib ipv6 java jpeg junit kde lcms libg++ libwww lirc lzw lzw-tiff mad mhash mikmod mng mod_php motif mozsvg mp3 mpeg mysql ncurses nls nptl ogg oggvorbis opengl pam pcre pdflib perl php png postgres python qt quicktime readline real sdl session slang socket sockets spell ssl tcltk tcpd tiff truetype truetype-fonts type1-fonts udev usb userlocales vcd visualization vorbis xine xinerama xml xml2 xmms xpm xv xvid zlib userland_GNU kernel_linux elibc_glibc" Unset: ASFLAGS, CTARGET, LANG, LC_ALL, LDFLAGS, LINGUAS
solar/vapier/taviso/tigger please advise.
Created attachment 73556 [details] chmlib-0.37.4.ebuild Ebuild for 0.37.4 version that fixes ebuild design errors (already fixed by taviso in 0.35-r1) but succeeds in compiling lib + tools.
InCVS thx to taviso. Arches: please test chmlib-0.37.4 and mark stable.
Stable on x86. For a test case (just in case the other arches need it), I download the file: http://www.pltw.org/OCHM/Digital.chm into ~/, made the directory ~/digital_out, then ran: cd ~ ; chmextract Digital.chm digital_out/ and verified the contents of the chm were successfully extracted to digital_out/
amd64 stable
Marked ppc stable.
GLSA 200511-23