In Zeiten, in denen Email immer wichtiger für die Firmen-Kommunikation ist, und viele Firmen eine volle Kontrolle über ihre Emails haben wollen, spielen verteilte Email-Systeme eine immer größere Rolle, selbst für Admins in mittelgrossen Betrieben. Diese bestehen zumeist aus einem Mail-Gateway, der Spam- und Virenfilter-Funktionen übernimmt, einem MTA/SMTP-Server und einem IMAP/POP3-Server.
Wer schonmal mit Spamassassin gearbeitet hat, wird da schnell auf die Frage kommen „Aber wie kann ich ein effektives Learning des Spamfilters erreichen, wenn sa-learn garkeinen Zugriff mehr auf die Postfächer hat?“ Auch dafür hat fast jeder Admin seine eigenen Ansätze. Manch einer richtet eine Email-Adresse ein, an die die User ihre nicht erkannten Spammails weiterleiten können. Und manch einer hängt via NFS o.ä. die Maildirs der Benutzer auf dem Mailgateway ein und richtet in den Mailboxen der User einen Ordner ein, in den sie ihre nicht erkannten Spammails werfen können.
Ein NFS-Mount stellt natürlich ein Sicherheitsrisiko dar, da ein erfolgreicher Angriff auf den Gateway auch gleichzeitig einen Zugriff auf die Postfächer gewährt, die man durch Trennung der einzelnen Systeme ja auch verhindern will. Über das Parsen von Emails hatte ich ja bereits vor geraumer Zeit unter http://www.hackerwiki.org/index.php/Email_Parsing_mit_den_MIME-Tools_für_Perl schonmal was geschrieben, wenn auch eher „andersrum“. Aus diesem Text geht eigentlich ja auch recht gut hervor, was man alles beachten muss beim Parsen von Emails, was bei weitergeleiteten Nachrichten immer notwendig ist, wenn man die eigentliche Spammail dort rausholen will.
Beide Methoden haben also ihre Vor- und Nachteile. Eine weitere Methode, die weder kompliziertes Email-Parsing noch NFS-Mounts auf dem Gateway benötigt, könnte so aussehen…
Zuerstmal richtet man einen extra Account auf dem Mail-Gateway ein. Dieser bekommt via sudoers das Recht ‘sa-learn’ als Mailuser auszuführen. Nun legen wir auf dem IMAP-Server ein Skript an, das die Spam-Mails einsammelt:
#!/usr/bin/perl
use File::Copy;
use File::Path qw(mkpath);
my ($action) = @ARGV;
my $targetdir = ($ENV{HOME}."/spammails");
my $targetfile = ($ENV{HOME}."/spammails.tar.gz");
sub collect_spammails
{
my @spammails = </imap/*/*/Maildir/.INBOX.spam_unknown/cur/*>;
# pruefen ob der zielordner vorhanden ist
if(! -e "$targetdir") {
mkpath($targetdir);
}
# spammails nach $targetdir moven
foreach my $this_spammail (@spammails) {
move($this_spammail, $targetdir)
or die "Couldn't move file: $!n";
}
}
sub compress_spammails()
{
my $cmd = "tar -czf ".$targetfile." ".$targetdir;
my $out = `$cmd`;
print $out;
}
sub cleanup_spammails
{
if(unlink($targetfile != 0)) {
print "Couldn't cleanup $targetfile.n";
}
my $files_path = $targetdir."/*";
my @files = <$files_path>;
foreach my $this_file (@files) {
unlink($this_file);
}
}
if($action eq 'collect') {
&collect_spammails();
&compress_spammails();
} elsif($action eq 'cleanup') {
&cleanup_spammails();
} else {
print "Unknown parameter.n";
}
Der Pfad zu den Maildirs muss natürlich angepasst werden. Dieses Beispiel geht davon aus, dass die Spam-Emails in /imap/<domain>/<benutzername>/Maildir/.INBOX.spam_unknown/cur/ liegen. Es lässt sich nun ganz einfach vom Gateway aus mittels SSH aufrufen und sammelt die Spammails in einem Tarball zusammen, den man dann via ‘scp’ auf den Gateway holen und auspacken kann. Auf dem Gateway müsste also nur folgendes ausgeführt werden:
1. ssh -i keyfile benutzer@imapserver /pfad/zum/skript.pl collect
2. scp -i keyfile benutzer@imapserver:/pfad/zum/tarball/spammails.tar.gz ./
3. tar -xzf spammails.tar.gz
4. cd spammails
5. sudo -u mailbenutzer sa-learn –spam *
5. cd .. && rm -r spammails*
6. ssh -i keyfile benutzer@imapserver /pfad/zum/skript.pl cleanup
Natürlich lässt sich das auch in einem Skript zusammenfassen.
Der Keyfile-Parameter deutet ja schon darauf hin, dass hier SSH mit Key-Auth verwendet wird. Deswegen wird auch ein extra User verwendet und nicht der Benutzer des Mailservers oder gar root. Ein Angreifer kann somit auch wenn er auf die Idee kommt die User-Accounts auf Keyfiles zu durchforsten nur einen unauthorisierten Zugriff auf die anderen Systeme erlangen. Und selbst dies kann man ja auch noch einschränken, indem man eine restricted Shell verwendet, die nur die für seinen Job notwendigen Befehle zulässt.