Zum Inhalt springen

Mail Anhänge mit Rspamd per Whitelist filtern

Mein bisheriger Ansatz war es via Blacklist die Anhänge zu filtern und nur jene zum Empfänger durch zu lassen die auf die Blacklist nicht anschlugen. Bei der Vielzahl von Dateiendungen und der Kreativität von Entwicklern ist die Liste irgendwie immer elendig lang und veraltet. Auf Kundenwunsch bin ich jetzt der Sache via Whitelist auf den Grund gegangen, anhand bestehender Mail Kommunikation kann man recht gut einschätzen welche Anhänge gewünscht sind – die Liste ist deutlich kürzer und alles andere landen dann automatisch im „banned“ Postfach.

Dieses „banned“ Postfach dient dem Sammeln der Mails, damit sie vom Admin kontrolliert und gegebenenfalls an den User ausgeliefert werden können. Der User bekommt gleichzeitig ein Email mit dem Text-Inhalt der Original Email und der Info welche Anhänge dort vorhanden waren. Für den Fall dass es ein legitimes Mail ist und der Anhang benötigt wird, kann er sich an den Admin wenden.

Aber wie setzt man das jetzt mit Rspamd um?

Erstmal eine Whitelist erstellen, ich habe sie goodfiles.map benannt und unter /etc/rspamd/local.d/ abgelegt. Hier eine kurze Beispielliste:

css
csv
docx
xlsx
pptx
dwg
gif
heic
ico
ics
jpeg
jpg
pdf
ps
png
txt
trc
xml
p7s
pkpass
vcf

Gegenüber einer Blacklist mit tausenden Einträgen ist das hier deutlich kürzer! 🙂

In der Datei /etc/rspamd/local.d/multimap.conf füge ich noch folgende beiden Einträge hinzu:

filename_whitelist {
	type = "filename";
	filter = "extension";
	map = "/${LOCAL_CONFDIR}/local.d/goodfiles.map";
	symbol = "FILENAME_WHITELISTED";
}

filename_extensions {
	type = "filename";
	filter = "extension";
	regexp = true;
	map = "/${LOCAL_CONFDIR}/local.d/allextensions.map";
	symbol = "FILENAME_EXTENSIONS";
}

Das führt dazu dass im Email Header unter „X-Spamd-Result:“ folgende Einträge hinzugefügt werden:

        FILENAME_EXTENSIONS(0.00)[png,jpg,txt,exe,csv,zip];
        FILENAME_WHITELISTED(0.00)[png,jpg,txt,csv];

Man kann also schon mal recht schnell erkennen dass FILENAME_EXTENSIONS und FILENAME_WHITELISTED nicht überein stimmen. Aber wie verschwindet diese Mail jetzt aus der Mailbox und landet im „banned“ Postfach?

Dafür nutze ich den Sieve Filter von Dovecot!

Die Dovecot Konfiguration für den Sieve Filter sieht bei mir wie folgt aus:

managesieve_notify_capability = mailto
managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date ihave
plugin {
 mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
  mail_log_fields = uid box msgid size
  sieve_global_dir = /srv/imap/sieve/global/
  sieve = file:/srv/imap/sieve/%d/%n/scripts;active=/srv/imap/sieve/%d/%n/active-script.sieve
  sieve_plugins = sieve_imapsieve sieve_extprograms
  sieve_before = /srv/imap/sieve/global/files-global.sieve
  sieve_dir = ~/sieve
  sieve_pipe_bin_dir = /srv/imap/sieve/bin
  sieve_execute_bin_dir = /srv/imap/sieve/bin
  sieve_global_extensions = +vnd.dovecot.pipe +duplicate +vnd.dovecot.execute
}
protocols = imap lmtp sieve
service anvil {
 client_limit = 8000
}
service managesieve-login {
 inet_listener sieve {
  address = 192.168.0.0/16 127.0.0.1
   port = 4190
 }
}

Die Datei /srv/imap/sieve/global/files-global.sieve sieht dann wie folgt aus:

require ["mailbox", "fileinto", "envelope", "copy", "duplicate", "comparator-i;ascii-numeric", "relational", "variables", "enotify", "vnd.dovecot.execute"];

if duplicate {
	discard;
	stop;
}

if header :matches "Subject" "*" {
	set "subject" "${1}";
}

if header :matches "From" "*"{
	set "from" "${1}";
}

if header :matches "To" "*"{
	set "to" "${1}";
}

if allof (header :contains "X-Spamd-Result" ["FILENAME_EXTENSIONS", "FILENAME_WHITELISTED"], not envelope "To" "banned@ruetz.at", not execute :pipe "fileext-mismatch-notify.sh" ["${from}", "${to}", "${subject}"]	) {
 redirect :copy "banned@ruetz.at";
 discard;
 stop;
}

Wie ich finde eigentlich überschaubar, mein erster Ansatz wäre gewesen an dieser Stelle FILENAME_EXTENSIONS und FILENAME_WHITELISTED zu vergleichen, die Email auszufiltern und den User zu benachrichtigen. Allerdings sind die Möglichkeit die Benachrichtigung via Sieve zu gestalten überschaubar, daher habe ich auf das externe Script „fileext-mismatch-notify.sh“ gesetzt.

Dieses Bash Script nimmt die Email entgegen und prüft die Header Daten, sobald Whitelist und Extensions nicht übereinstimmen wird dem Sieve Filter ein „exit 1“ übergeben und der Anwender bekommt eine Email Benachrichtigung. An dieser Stelle kann man kreativ werden und z.B. alle Anhänge per Checksumme via Virustotal prüfen lassen und eine Bericht an den Admin senden, oder auch den Versender benachrichtigen dass Anhänge vom Typ XY nicht erwünscht sind und er die Informationen falls wichtig doch besser im Format YZ schicken soll…

Die Datei fileext-mismatch-notify.sh liegt im Verzeichnis /srv/imap/sieve/bin/ und sieht wie folgt aus:

#!/bin/bash

FROM=$1
TO=$2
SUBJECT="=?UTF-8?B?"$(echo "Blockierter Mailanhang von $FROM - Betreff des Orignal Mails: $3"|base64)"=?="

if [ ! -d "/var/tmp/mailcheck/" ]; then
	mkdir "/var/tmp/mailcheck/"
fi

TEMPF=$(tempfile -d "/var/tmp/mailcheck/")
TEMPD=$(mktemp -d -p "/var/tmp/mailcheck/")

IFS=" "

EMAIL=$(cat)
XSPAM=$(echo $EMAIL |grep -A50 X-Spamd-Result:)

FILENAME_EXTENSIONS=$(echo $XSPAM | grep "FILENAME_EXTENSIONS"| awk -F'[' '{print $2}')
FILENAME_WHITELISTED=$(echo $XSPAM | grep "FILENAME_WHITELISTED"| awk -F'[' '{print $2}')

if [ ! "$FILENAME_EXTENSIONS" = "$FILENAME_WHITELISTED" ]; then
 # unerlaubte File Extensions - Benachrichtigung schicken und Email analysieren...
 echo $EMAIL > $TEMPF
 cd $TEMPD
 ripmime -i $TEMPF -d $TEMPD
 MAILINFO=$(mu view $TEMPF)
 # https://www.virustotal.com/gui/search/
 FILEINFO=$(find $TEMPD -type f -exec sha256sum {} \;|awk -F'/' '{print "<a href=\"https://www.virustotal.com/gui/search/"$1"\">"$6"</a><br>"}')

 # Benachrichtigung versenden
 (
 echo -e "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title>Blockierter Mailanhang von $FROM</title></head><body>"
 echo "<h3>Aus Sicherheitsgründen wurde dieses Mail in Quarantäne gestellt, falls der Inhalt legitim ist bitte mit dem Admin XY in Verbindung setzen!</h3>"
 echo " "
 echo "<strong>Es folgt der Inhalt der Original Email:</strong>"
 echo " "
 echo "<pre>$MAILINFO</pre>"
 echo " "
 echo "</body></html>"
#		echo "<strong>Folgende Dateien sind im Mail enthalten:</strong><br>"
#		echo " "
#		echo "$FILEINFO"
#		echo " "
 ) 2>&1 | mailx -a "Content-type: text/html; charset='UTF-8'" -r "postmaster@empfaengerdomain" -s "$SUBJECT" -- $TO

 # aufräumen
 rm $TEMPF
 rm -r $TEMPD

 # Email ablehnen
 exit 1;
fi

# Email annehmen
rm $TEMPF
rmdir $TEMPD
exit 0

Die vier auskommentierten Zeilen beim Mailversand würden dem Empfänger der Email die Direktlinks für Virustotal mitschicken, dient nur als Beispiel und macht so vermutlich wenig Sinn. Besser wäre es das Ergebnis direkt abzufragen diese Info dem Admin zu liefern. Es soll hier aber nur als Anregung dienen.

Zum Auswerten der Mail habe ich folgende zusätzliche Pakete installiert:

bsd-mailx
maildir-utils
ripmime

Alle drei sind in den Standard Repositories von Ubuntu/Debian zu finden.

Schlagwörter:

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert