How to block malicious VBA documents and spreadsheets with spam assassin or amavisd

Monitoring our net streams for SMTP traffic, I have a particular Splunk alert configured to alert when a spam campaign in underway. It’s quite interesting to see what tricks spammers try and how long some campaigns last.

Something that has caught my attention is the increased use of unsolicited “invoice” and “order” emails which get sent with .doc documents attached. Reviewing the documents nearly all of them contain malicious VB scripting usually set to auto run, which downloads and tries to execute binaries.

Now I have created a number of spam assassin rules to block these types of emails (invoices with .doc files attached) but it’s a cat and mouse game, and you can’t be too generic as you may block legitimate email. What I can block ruthlessly is documents and spreadsheets which contain autorun VB scripting.

Here is how to do it:

Create the following file on your amavisd server at the location “/usr/local/bin/”

#!/usr/bin/perl -w
# Detects vba macros containing blacklisted strings.
# Mods by
# Suggested amavisd/maiad.conf config:
# ['Detect-VBA',
#   '/usr/local/bin/', "{}",
#      [0], qr/INFECTED/, qr/\bINFECTED (.+)\b/m ],
use strict;

my $sigtool = '/usr/bin/sigtool'; #Clamav sigtool path

if ($#ARGV != 0) {
    print "Please supply directory to scan\n";
    exit 0;

#Sanity check directory
my $dir = $ARGV[0];
if ($dir !~ /^[a-z0-9A-Z\/-]+$/) {
    print "Invalid directory passed\n";
    exit 0;

opendir DIR, $dir or die "Cannot open dir $dir: $!";
my @files = readdir DIR;

foreach my $file (@files) {
    next if $file =~ /^\.$/;
    next if $file =~ /^\.\.$/;
    my $scan = `$sigtool --vba="$dir/$file"`;
    if ($scan =~ /autoopen/i ) {
        print "Scanning $file: INFECTED VBA\n";
        exit 1;
    } else {
        print "Scanning $file: OK\n";

closedir DIR;

exit 0;

Then in amavisd.conf (/etc/amavisd/amavisd.conf on CentOS) modify the section “@av_scanners” and insert as a primary scanner the following stanza:

   '/usr/loca/bin/', "{}",
      [0], qr/INFECTED/, qr/\bINFECTED (.+)\b/m ],

Then after that just restart your amavisd service and you should see, it finds Detect-VBA as a primary scanner, test it by sending yourself a malicious macro document lol.

Download the raw howto here, so that special characters are intact as FlatPress has a habit of removing them….https://www.cammcken … assin-or-amavisd.txt

Amavisd default action isn’t to discard spam

When you install amavisd-new it appears the spam still gets passed on to the sender.
The default action in /etc/amavisd.conf around line 163 is:

# final_spam_destiny   => D_BOUNCE;

One would presume based on prior experience with config files that, while it is commented out, that would be the default action. From what I have seen it isn’t. What seems to actually happens is that if ‘$*_quarantine_to’ variable is assigned emails will get delivered there and to the original recipient. Suggesting the D_PASS is the default.

Anyway to fix it, just uncomment and change

# final_spam_destiny   => D_BOUNCE; 


final_spam_destiny   => D_DISCARD; 

and restart amavisd service.

Further information:

D_PASS Mail will pass to recipients, regardless of bad contents. If a quarantine is configured, a copy of the mail will go there, if not, at least the recipient received the mail. Note that including a recipient in a @*_lovers_maps is functionally equivalent to setting $final_*_destiny = D_PASS; for that recipient.

D_BOUNCE Mail will not be delivered to its recipients. A non-delivery notification (bounce) will be created by amavisd-new and sent to the sender by amavisd-new. Exceptions: bounce (DSN) will not be sent if a virus name matches @viruses_that_fake_sender_maps , or to messages from mailing lists (Precedence: bulk|list|junk), or for spam level that exceeds the $sa_dsn_cutoff_level. If a quarantine is configured, a copy of the mail will go there. If not, we have lost the mail, but if the mail was legitimate, the sender should receive notification of the disposition of the message.

D_DISCARD Mail will not be delivered to its recipients and the sender normally will NOT be notified. If a quarantine is configured, a copy of the mail will go there. If not, we have lost the mail. Note that there are additional settings available that can send notifications to persons that normally may not be notified when an undesirable message is found, so it is possible to notify the sender even when using D_DISCARD.

Report on Exchange mailbox folder sizes (powershell)

Recently had the task of finding out how a users Exchange mailbox quota was nearly full.
The command I used was:

Get-MailboxFolderStatistics -Identity "User A" | fl Name, ItemsInFolder, FolderSize
Get-Mailbox | Get-MailboxStatistics | fl DisplayName, ItemCount, TotalItemSize

Turns out it was the sent items folder…. :-)

Powershell command to check Send-As Permissions

Find all users who have Full Access to the mailbox of others:

Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission | ? {($_.AccessRights -match "FullAccess") -and 
not ($_.User -like "NT AUTHORITYSELF")} | ft Identity, User

Finding all users who have Send-As :

Get-Mailbox -Resultsize Unlimited | Get-ADPermission | ? {($_.ExtendedRights -like "*send-as*") -and -not
($_.User -like "nt authorityself")} | ft Identity, User -auto

Finding all users who have Send-As (Restricted to an OU):

Get-Mailbox -Resultsize Unlimited | Get-ADPermission | ? {($_.ExtendedRights -like "*send-as*") -and
($_.Identity -like "*/SomeOU/Users/*") -and -not ($_.User -like "nt authorityself")} | ft Identity, User -auto

Find out who a particular user can Send-As:

Get-Mailbox -Resultsize Unlimited | Get-ADPermission | ? {($_.ExtendedRights -like "*send-as*") -and -not
($_.User -like "nt authorityself") -and ($_.User -like "DOMAINUsernameUwantToFind")} | ft Identity, User -auto

Delete certain messages from Postfix Queue

Ever had some alerting software spam your production mail queue with 1000’s of alerts?
And you dont want to delete every message individually…

Here is the solution to delete all messages destined for

mailq | tail -n +2 | grep -v '^ *(' | 
gawk 'BEGIN {RS = ""} / {print $1}' | 
tr -d '*!' | postsuper -d - 

Thanks to for that one!