[Mimedefang] Alternative zip blocking code

Chris Masters rotis23 at yahoo.com
Fri Mar 5 12:34:29 EST 2004


Hi All,

Thought I ought to post my solution to the zip
blocking problem seeing as I got most of the code from
the list. 

It only copes with blocking and problematic zips and
does no call to virus checkers. It could block if:

 - error reading file i.e. it's corrupt or not a zip
 - number of files within zip is greater than
$MAX_ARCHIVE_FILES
 - it contains a file with an extension in $bad_exts
regexp
 - it is a password protected/encrypted zip and
contains another zip
 - the number of zips within zips is greater than
$MAX_ARCHIVE_RECURSION
 - error decompressing file

It's just a test file with no mimedefang specific
functions but is easy to plug in.

Hope it helps someone - feel free to point out
intentional mistakes - use at your own risk and all
that.

Chris


use Archive::Zip;
Archive::Zip::setErrorHandler(sub {});

$ext='.zip';
$bad_exts = '(exe|txt|pif|gif|\{[^\}]+\})';
$inflate_count = 0;
$MsgID = "QF0000011AD";

$TEMP_DECOMPRESS_PATH = '/tmp/mimedefang_tmp_zip_';
$MAX_ARCHIVE_FILES = 10;
$MAX_ARCHIVE_RECURSION = 3;

sub scan_compressed($)
{
        my ($zipfilename) = @_;
        print "Attempting to scan $zipfilename\n";
        $zip = Archive::Zip->new();
        $res = $zip->read($zipfilename);
        if ($res == AZ_OK)
        {
                print "Found valid zip -
$zipfilename\n";
                my @members = $zip->members();

                if(@members > $MAX_ARCHIVE_FILES)
                {
                        print "Too many files\n";
                        print "Block whole attachment
here\n";
                        return;
                }

                foreach my $member (@members)
                {
                        my $file =
$member->fileName();
                        print "Checking file within
zip - $file\n";

                        my $re = '\.' . $bad_exts .
'\.*([^-A-Za-z0-9_.,]|$)';
                        if(lc($file) =~ $re)
                        {
                                print "Found a bad
extension within zip\n";
                                print "Block whole
attachment here\n";
                                return;
                        }

                        if($member->isEncrypted() &&
lc($file) =~ /zip$/)
                        {
                                print "Found a
password protected zip with a zip inside\n";
                                print "Block whole
attachment here\n";
                                return;
                        }

                        if(lc($file) =~ /zip$/)
                        {
                                print "Found a zip
with a zip inside\n";
                                print "Need to inflate
and scan again - bugger\n";

                               
scan_recursive_node($member)

                        }
                }
        }
        else
        {
                print "Not a zip or corrupt - $res\n";
                print "Block whole attachment here\n";
                return;
        }
}

sub scan_recursive_node($)
{
        my ($member) = @_;
        if($inflate_count < $MAX_ARCHIVE_RECURSION)
        {
                print "Inflating...\n";
                $inflate_count++;

                #unzip
                $res =
$zip->extractMember($member,$TEMP_DECOMPRESS_PATH .
$MsgID);
                if($res == 0)
                {
                        #call back this function with
zip file
                       
scan_compressed($TEMP_DECOMPRESS_PATH . $MsgID);
                }
                else
                {
                        print "Problem decompressing
zip - $res\n";
                        print "Block whole attachment
here\n";
                        return;
                }
                unlink($TEMP_DECOMPRESS_PATH .
$MsgID);
                $inflate_count--;
        }
        else
        {
                print "Too many recursions\n";
                print "Block whole attachment here\n";
                return;
        }
}

my $path = $ARGV[0];

if (lc($ext) =~ /\.zip$/)
{
        scan_compressed($path);
}

print "FIN\n";


__________________________________
Do you Yahoo!?
Yahoo! Search - Find what you’re looking for faster
http://search.yahoo.com



More information about the MIMEDefang mailing list