Re: [Exim] Mental Core Dump: Virus Scanning from a system fi…

Top Page
Delete this message
Reply to this message
Author: Barry Pederson
Date:  
To: exim-users
Subject: Re: [Exim] Mental Core Dump: Virus Scanning from a system filter revisited
Marc Haber wrote:
>
> We should have a system filter that calls an embedded perl function
> that does the scanning. It uses exim -Mvb and exim -Mvh (or the
> possibly future exim -Mva [1]) to obtain the message's header and body
> and do its scanning business. If the message is classified malicious,
> the embedded perl function could create new messages according to
> configuration (see (f) above) and subsequently fail delivery in the
> system filter, preventing the malicious message from being delivered
> in the first place. Probably, a bounce would be created to the sender,
> but I'd consider that a feature if the message is failed with "see
> notification report sent in a separate e-mail message". If the
> function determines a message to be clean, normal delivery can be
> continued. Thus, a clean message is only passed through the MTA a
> single time.
>
> What are your opinions about this concept?


Marc Haber wrote:
>
> Actually, I don't think that any modifications in the exim code base
> are necessary to implement this concept. It is nice to hear that you
> didn't see any obvious mistakes in here, so I'll probably go for a
> proof of concept next week.


I've setup Exim 3.16 to do a mailscan pretty close to what Marc
described, and can attest that the plan is definitely workable without
changes to Exim. Have been running this for a year now on a server
that handles about 6,000 msgs/day. Currently, I have a system filter
and perl script that look like:

-----
# Exim filter

if first_delivery
and ($received_protocol is not "virusscan")
and (${perl{mailscan}} is "fail")
then
    seen finish
endif
-----
#!/usr/bin/perl


$real_scanner = '/usr/local/etc/exim/mailscan.py';

sub mailscan
    {
    $message_id     = Exim::expand_string('$message_id');
    $sender_address = Exim::expand_string('$sender_address');
    $header_subject = Exim::expand_string('$header_subject');


    $header_subject =~ s(\\)(\\\\)g;
    $header_subject =~ s(\")(\\\")g;
    $header_subject =~ s(\`)(\\\`)g;


    $result = `$real_scanner $message_id "$sender_address"
"$header_subject"`;
    chomp $result;


    if (($result ne 'ok') && ($result ne 'fail'))
        {
        open(LOGFILE, ">>/var/log/mailscan.log");
        print LOGFILE "$message_id <$sender_address>---------\nSubject:
[$header_subject]\n$result\n----------\n";
        close(LOGFILE);
        system("cp /var/spool/exim/input/$message_id-*
/var/mailscan/hold")
        }


    return $result;
    }
------


I ended up writing the actual scanner in Python (like it better than
Perl), which makes a copy of the message (cheated and read directly from
the queue, instead of using -Mvb and -Mvh - will have to go back and
clean that up), parses all attachments, ponders the names of the files
(looking for .exe and such), and runs F-Secure Antivirus for Linux (this
in actually on a FreeBSD box).

If any problems are found, I send a reply to the sender (with "-oMr
virusscan" so the system doesn't bother scanning the reply), resend the
original to a quarantine address (again with "-oMr virusscan" so it
doesn't get scanned again), and print "fail" to stdout - which works its
way back to the exim system filter causing the original message to just
be dropped.

It's probably a bit inefficient to fire up a Perl interpreter inside
Exim just to invoke a Python interpreter :) I've started hacking at
3.16 a bit to see if Python can be integrated, the same way Perl is now.

    Barry