diff -u clamav-0.92~dfsg/debian/changelog clamav-0.92~dfsg/debian/changelog --- clamav-0.92~dfsg/debian/changelog +++ clamav-0.92~dfsg/debian/changelog @@ -1,3 +1,11 @@ +clamav (0.92~dfsg-2~dapper1ubuntu0.2) dapper-security; urgency=low + + * SECURITY UPDATE: Remote Code Excecution + * Added : 30_pe.c-CVE-2008-1100.dpatch Fixes Remote Code Execution + * References CVE-2008-1100 ( LP: #217361 ) + + -- Leonel Nunez Mon, 14 Apr 2008 18:23:38 -0600 + clamav (0.92~dfsg-2~dapper1ubuntu0.1) dapper-security; urgency=low * SECURITY UPDATE: possible integer overflow and tempfile symlink diff -u clamav-0.92~dfsg/debian/patches/00list clamav-0.92~dfsg/debian/patches/00list --- clamav-0.92~dfsg/debian/patches/00list +++ clamav-0.92~dfsg/debian/patches/00list @@ -7,0 +8 @@ +30_pe.c-CVE-2008-1100.dpatch only in patch2: unchanged: --- clamav-0.92~dfsg.orig/debian/patches/30_pe.c-CVE-2008-1100.dpatch +++ clamav-0.92~dfsg/debian/patches/30_pe.c-CVE-2008-1100.dpatch @@ -0,0 +1,315 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 30_pe.c-CVE-2008-1100.dpatch by Leonel Nunez +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +@DPATCH@ +diff -urNad clamav-0.92~dfsg~/libclamav/pe.c clamav-0.92~dfsg/libclamav/pe.c +--- clamav-0.92~dfsg~/libclamav/pe.c 2007-12-10 07:13:16.000000000 -0700 ++++ clamav-0.92~dfsg/libclamav/pe.c 2008-04-14 18:20:37.000000000 -0600 +@@ -333,6 +333,7 @@ + uint32_t valign, falign, hdr_size, j; + struct cli_exe_section *exe_sections; + struct cli_matcher *md5_sect; ++ char timestr[32]; + + + if(!ctx) { +@@ -505,7 +506,7 @@ + cli_dbgmsg("NumberOfSections: %d\n", nsections); + + timestamp = (time_t) EC32(file_hdr.TimeDateStamp); +- cli_dbgmsg("TimeDateStamp: %s", ctime(×tamp)); ++ cli_dbgmsg("TimeDateStamp: %s", cli_ctime(×tamp, timestr, sizeof(timestr))); + + cli_dbgmsg("SizeOfOptionalHeader: %x\n", EC16(file_hdr.SizeOfOptionalHeader)); + +@@ -782,7 +783,7 @@ + + if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */ + if (exe_sections[i].raw >= fsize) { /* really broken */ +- cli_dbgmsg("Broken PE file - Section %d starts beyond the end of file (Offset@ %d, Total filesize %d)\n", i, exe_sections[i].raw, fsize); ++ cli_dbgmsg("Broken PE file - Section %d starts beyond the end of file (Offset@ %lu, Total filesize %lu)\n", i, (unsigned long)exe_sections[i].raw, (unsigned long)fsize); + free(section_hdr); + free(exe_sections); + if(DETECT_BROKEN) { +@@ -796,16 +797,25 @@ + if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !*sname && exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000 && exe_sections[i].chr == 0xe0000060) polipos = i; + + /* check MD5 section sigs */ +- md5_sect = ctx->engine->md5_sect; ++ md5_sect = ctx->engine->md5_mdb; + if((DCONF & PE_CONF_MD5SECT) && md5_sect) { + found = 0; + for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) { + if(md5_sect->soff[j] == exe_sections[i].rsz) { + unsigned char md5_dig[16]; +- if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_sect, 0, 0, -1) == CL_VIRUS) { ++ if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, 0, -1) == CL_VIRUS) { ++ /* Since .mdb sigs are not fp-prone, to save ++ * performance we don't call cli_checkfp() here, ++ * just give the possibility of whitelisting ++ * idividual .mdb entries via daily.fp ++ */ ++ if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS) { ++ + ++ + free(section_hdr); + free(exe_sections); + return CL_VIRUS; ++ } + } + break; + } +@@ -813,6 +823,19 @@ + } + } + ++ if (exe_sections[i].urva>>31 || exe_sections[i].uvsz>>31 || (exe_sections[i].rsz && exe_sections[i].uraw>>31) || exe_sections[i].ursz>>31) { ++ cli_dbgmsg("Found PE values with sign bit set\n"); ++ free(section_hdr); ++ free(exe_sections); ++ if(DETECT_BROKEN) { ++ if(ctx->virname) ++ *ctx->virname = "Broken.Executable"; ++ return CL_VIRUS; ++ } ++ return CL_CLEAN; ++ } ++ ++ + if(!i) { + if (DETECT_BROKEN && exe_sections[i].urva!=hdr_size) { /* Bad first section RVA */ + cli_dbgmsg("First section is in the wrong place\n"); +@@ -1094,7 +1117,7 @@ + } + + if((bytes = read(desc, buff, 0xb0)) != 0xb0) { +- cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes); ++ cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %lu\n", fileoffset, fileoffset, (unsigned long)bytes); + break; + } + +@@ -1132,12 +1155,12 @@ + } + + if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) { +- cli_dbgmsg("MEW: Can't read %d bytes [read: %d]\n", exe_sections[i + 1].rsz, bytes); ++ cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes); + free(exe_sections); + free(src); + return CL_EIO; + } +- cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes); ++ cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes); + + /* count offset to lzma proc, if lzma used, 0xe8 -> call */ + if (buff[0x7b] == '\xe8') { +@@ -1152,7 +1175,7 @@ + } + + CLI_UNPTEMP("MEW",(src,exe_sections,0)); +- CLI_UNPRESULTS("MEW",(unmew11(i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, NULL, NULL, ndesc)),1,(src,0)); ++ CLI_UNPRESULTS("MEW",(unmew11(src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, ndesc)),1,(src,0)); + break; + } + } +@@ -1233,7 +1256,7 @@ + + CLI_UNPSIZELIMITS("Upack", MAX(MAX(dsize, ssize), exe_sections[1].ursz)); + +- if (exe_sections[1].rva - off > dsize || exe_sections[1].rva - off > dsize - exe_sections[1].ursz || (upack && (exe_sections[2].rva - exe_sections[0].rva > dsize || exe_sections[2].rva - exe_sections[0].rva > dsize - ssize)) || ssize > dsize) { ++ if (!CLI_ISCONTAINED(0, dsize, exe_sections[1].rva - off, exe_sections[1].ursz) || (upack && !CLI_ISCONTAINED(0, dsize, exe_sections[2].rva - exe_sections[0].rva, ssize)) || ssize > dsize) { + cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n"); + break; + } +@@ -1246,9 +1269,8 @@ + lseek(desc, 0, SEEK_SET); + if(read(desc, dest, ssize) != ssize) { + cli_dbgmsg("Upack: Can't read raw data of section 0\n"); +- free(exe_sections); + free(dest); +- return CL_EIO; ++ break; + } + + if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize); +@@ -1257,9 +1279,8 @@ + + if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) { + cli_dbgmsg("Upack: Can't read raw data of section 1\n"); +- free(exe_sections); + free(dest); +- return CL_EIO; ++ break; + } + + CLI_UNPTEMP("Upack",(dest,exe_sections,0)); +@@ -1784,7 +1805,7 @@ + if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) { + free(exe_sections); + free(dest); +- return CL_EIO; ++ return CL_CLEAN; + } + } + } +@@ -1812,7 +1833,7 @@ + + lseek(desc, 0, SEEK_SET); + if((size_t) cli_readn(desc, spinned, fsize) != fsize) { +- cli_dbgmsg("PESpin: Can't read %d bytes\n", fsize); ++ cli_dbgmsg("PESpin: Can't read %lu bytes\n", (unsigned long)fsize); + free(spinned); + free(exe_sections); + return CL_EIO; +@@ -1838,7 +1859,7 @@ + + lseek(desc, 0, SEEK_SET); + if((size_t) cli_readn(desc, spinned, fsize) != fsize) { +- cli_dbgmsg("yC: Can't read %d bytes\n", fsize); ++ cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize); + free(spinned); + free(exe_sections); + return CL_EIO; +@@ -1851,103 +1872,65 @@ + + /* WWPack */ + +- if((DCONF & PE_CONF_WWPACK) && nsections > 1 && +- exe_sections[nsections-1].raw>0x2b1 && ++ while ((DCONF & PE_CONF_WWPACK) && nsections > 1 && + vep == exe_sections[nsections - 1].rva && +- exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz == max && + memcmp(epbuff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 && + memcmp(epbuff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0) { +- uint32_t headsize=exe_sections[nsections - 1].raw; +- char *dest, *wwp; ++ uint32_t head = exe_sections[nsections - 1].raw; ++ uint8_t *packer; + +- for(i = 0 ; i < (unsigned int)nsections-1; i++) +- if (exe_sections[i].rawssize) break; + +- CLI_UNPSIZELIMITS("WWPack", dsize); ++ CLI_UNPSIZELIMITS("WWPack", ssize); + +- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { +- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", dsize); ++ if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) { + free(exe_sections); + return CL_EMEM; + } +- + lseek(desc, 0, SEEK_SET); +- if((size_t) cli_readn(desc, dest, headsize) != headsize) { +- cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", headsize); +- free(dest); ++ if((size_t) cli_readn(desc, src, head) != head) { ++ cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head); ++ free(src); + free(exe_sections); + return CL_EIO; + } + +- for(i = 0 ; i < (unsigned int)nsections-1; i++) { +- if(exe_sections[i].rsz) { +- if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) { +- free(dest); +- free(exe_sections); +- return CL_EIO; +- } +- } +- } +- +- if((wwp = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { +- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", exe_sections[nsections - 1].rsz); +- free(dest); ++ for(i = 0 ; i < (unsigned int)nsections-1; i++) { ++ if(!exe_sections[i].rsz) continue; ++ if(!cli_seeksect(desc, &exe_sections[i])) break; ++ if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break; ++ if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break; ++ } ++ if(i!=nsections-1) { ++ cli_dbgmsg("WWpack: Probably hacked/damaged file.\n"); ++ free(src); ++ break; ++ } ++ if((packer = (uint8_t *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { ++ free(src); + free(exe_sections); + return CL_EMEM; + } + +- if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, wwp, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { ++ if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, packer, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { + cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz); +- free(dest); +- free(wwp); ++ free(src); ++ free(packer); + free(exe_sections); + return CL_EIO; + } + +- if (!wwunpack(dest, dsize, headsize, min, exe_sections[nsections-1].rva, e_lfanew, wwp, exe_sections[nsections - 1].rsz, nsections-1)) { +- +- free(wwp); +- +- CLI_UNPTEMP("WWPack",(dest,exe_sections,0)); +- +- if((unsigned int) write(ndesc, dest, dsize) != dsize) { +- cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize); +- close(ndesc); +- free(tempfile); +- free(dest); +- free(exe_sections); +- return CL_EIO; +- } +- +- free(dest); +- if (cli_leavetemps_flag) +- cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); +- else +- cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n"); +- +- fsync(ndesc); +- lseek(ndesc, 0, SEEK_SET); +- +- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { +- free(exe_sections); +- close(ndesc); +- if(!cli_leavetemps_flag) +- unlink(tempfile); +- free(tempfile); +- return CL_VIRUS; +- } +- +- close(ndesc); +- if(!cli_leavetemps_flag) +- unlink(tempfile); +- free(tempfile); +- } else { +- free(wwp); +- free(dest); +- cli_dbgmsg("WWPpack: Decompression failed\n"); +- } ++ CLI_UNPTEMP("WWPack",(src,packer,exe_sections,0)); ++ CLI_UNPRESULTS("WWPack",(wwunpack((uint8_t *)src, ssize, packer, exe_sections, nsections-1, e_lfanew, ndesc)),0,(src,packer,0)); ++ break; + } + +