Eigene AntiVirus engine via Amavis

2013-04-27 19:53

Vor einigen Wochen habe ich meine Idee umgesetzt, in amavis einen zusätzlichen Virenscanner zu implementieren. Da ich ja nur Systemadministrator bin, bestand meine Idee darin, einfach virustotal.com zu automatisieren.

Die API ist gut, aber ungesehen Dokumente aus E-Mails hochzuladen, schien mir nicht geheuer. Es könnte ja ein vertrauliches Dokument sein. Muss man ein bisschen aufpassen, gerade als postmaster. Daher läuft das jetzt ohne API. Gefunden werden mit den einfachen HTTP curl requests nur Dokumente, die bereits durch die Community analysiert wurden.

Wie geht das nun von statten: Amavis zerlegt die E-Mails in ihre Bestandteile (multiparts) und übergibt das zu scannende Verzeichnis den Virenscannern, denn der base64-stream einer e-Mail hilft meinem curl-Skript wenig, daher „zerlegen lassen“. Das machen wir mit bypass_decode_parts explizit:

/etc/amavis/conf.d/99-virustotal
# To disable virus or spam checks, uncomment the following:
#
# @bypass_virus_checks_maps = (1); # controls running of anti-virus code
# @bypass_spam_checks_maps = (1); # controls running of anti-spam code
# $bypass_decode_parts = 1; # controls running of decoders & dearchivers

$bypass_decode_parts = 0;

Einer der Virenscanner ist nun also mein perl-skript, das wie folgt mit den dekodierten Daten (E-Mail-parts) arbeitet:

Es ermittelt für alle Dateien im Verzeichnis den Typ. Plain-Text wird übersprungen. Ebenso image/png. Bei HTML wird nach dem String script gesucht, wenn er enthalten ist, wird dieser mailpart nicht ignoriert.

Für jeden nicht zu überspringenden Mail Part wird nun der MD5 oder SHA256 Hash ermittelt. Dieser wird mit einem einfachen HTTP request bei virustotal geprüft, wenn er noch nicht in den lokalen cache-files notiert ist, die als erstes geprüft werden und HTTP-Abfragen einsparen helfen.

Sollten bei virustotal mindestens drei Scanner die Datei als schädlich einstufen (und das beim parsen des HTML erkannt wird), wird der hash der Datei in einer lokalen Blacklist gespeichert. Wenn 0/xx als Ergebnis zurück kommt, wird der hash in eine whitelist eingetragen. Wenn der Hash nicht bekannt ist, kommt er in eine lokale greylist.

Fertig.

ToDo ist nun noch die Implementierung von TTLs, um white und greylist Einträge nach einer Zeit erneut zu prüfen. Idee war, das mit einem Key-Value NoSQL wie redis zu machen, es wird wohl aber doch auf MySQL hinauslaufen, weil zum einen die Unterscheidung in white/grey/black aufgrund des eineindeutigen hash stattfinden soll, zum anderen sollen die results (z.B. Virusnamen der verschiedenen engines auch gespeichert werden um sie in den Virus in den Benachrichtigungs E-Mails benennen zu können.)

Die Trefferquote ist nun mit der ersten Version dieser meta-engine um einiges höher, als wenn ClamAV allein die Entscheidung treffen müsste. Es gibt ja doch einige Virenscanner, die etwas häufiger updates ihrer Virensignaturen erhalten.

Comments are closed.