Hi,

Playing with sparse files I noticed it's easy to create a tiny 2
megabytes zip file that would unpack into a whopping 2 gigabytes file.

If your qmail-scanner is configured to unpack the zip files before
scanning (force_unzip=1), then unpacking these special zip files will
cause heavy disk I/O, CPU usage and might take up all your disk space.

Clamav has a builtin protection against these type of archive. So, if
you use qmail-scanner with Clamav as the virus scanner, you can disable
unzip support in qmail-scanner.

But, if you really need to unpack the zip files in qmail-scanner, then
here is a patch that allows you to check the compression ratio of the
zip files. Any zip file with a compression ratio greater than
`$max_zip_compression_ratio' will be placed in quarantine.

Regards,
Jérôme

-- 
<ESC>:r $HOME/.signature<CR>
--- qmail-scanner-queue.template.orig   2004-08-20 22:09:25.000000000 +0200
+++ qmail-scanner-queue.template        2004-08-21 13:06:13.000000000 +0200
@@ -243,6 +243,11 @@
 #McAfee's doesn't!
 my $force_unzip=FORCE_UNZIP;
 
+# Specify the maximum zip compression ratio (0 to 100).
+# This is to prevent potential Denial Of Service with specially crafted zip
+# Set it to 0 to disable oversized zip file checking.
+my $max_zip_compression_ratio=90
+
 #Descriptive string to use in generated Email
 my $destring="virus";
 
@@ -1994,6 +1999,7 @@
 sub unzip_file {
   my($zipfile)[EMAIL PROTECTED];
   my ($MAYBEZIP,$ztmp,$zfile,$zline,$zsize,$zip_status,$passwd_protected_zip);
+  my ($status_line,$zip_ratio);
   
   &debug("u_f: potential zip archive file found ($zipfile).");
   &debug ("u_f: it is possibly a zip file, run unzip $unzip_options -t 
$ENV{'TMPDIR'}/$zipfile");
@@ -2019,6 +2025,22 @@
       $description .= "\n---perlscanner results ---\n$destring 
'$quarantine_description' found in file $ENV{'TMPDIR'}/$zipfile";
     } else {
       if ($force_unzip) {
+       if ($max_zip_compression_ratio) {
+         &debug("u_f: run $unzip_binary $unzip_options -lv $ENV{'TMPDIR'}/$zipfile 
2>&1");
+         open(ZIPPED,"$unzip_binary $unzip_options -lv $ENV{'TMPDIR'}/$zipfile 
2>&1|")||&error_condition("u_f: cannot open $ENV{'TMPDIR'}/$zipfile - $!");
+         $status_line = $_ while(<ZIPPED>);
+         close(ZIPPED);
+         ($zip_ratio) = ($status_line =~ m/(\d+)%/);
+         if (defined $zip_ratio and $zip_ratio > $max_zip_compression_ratio) {
+           #Quarantine it!
+           $quarantine_description="Oversized zip files ($zipfile) - potential denial 
of service";
+           &debug("u_f: $quarantine_description");
+           $destring='problem';
+           $quarantine_event="Policy:Oversized_ZIP";
+           $description .= "\n---perlscanner results ---\n$destring 
'$quarantine_description' found in file $ENV{'TMPDIR'}/$zipfile";
+           return;
+         }
+       }
        &debug("u_f: run $unzip_binary $unzip_options $ENV{'TMPDIR'}/$zipfile 2>&1");
        open(ZIPPED,"$unzip_binary $unzip_options   $ENV{'TMPDIR'}/$zipfile 
2>&1|")||&error_condition("u_f: cannot open $ENV{'TMPDIR'}/$zipfile - $!");
        while (<ZIPPED>) {

Reply via email to