Sicherheits-Abfragen
Das im Internet nicht nur nette Menschen unterwegs sind, dürfte inzwischen hinreichend bekannt sein. Vor allem Spammer haben sich zu einer enormen Plage entwickelt, und kennen diverse Tricks, um unschuldige Opfer als Spam-Relais zu missbrauchen - momentan wäre auch unser Skript ein solches Opfer.
Warum? Die Funktion schickt sämtliche Daten an das Mail-Programm, ohne jegliche Überprüfung. Kämen die
Daten beispielsweise direkt aus einem HTML-Formular, in dem der User seine eigene Email-Adresse angeben kann,
könnte jeder halbwegs versierte Benutzer einfach folgenden Absender eingeben:
name@domain.com\nCc: beliebige@andere_adresse.com; zweite_beliebige@andere_adresse.com; [...]
Das Resultat? Perl interpretiert \n brav als Zeilenumbruch, und das Mail-Programm folglich die
nächste Zeile als Header-Zeile, mit der Folge, dass die Email auch an beliebig viele weitere Empfänger versandt
werden würde!
Natürlich könnte man an dieser Stelle davon ausgehen, dass die Daten bereits vom aufrufenden Script auf derartige Schwachstellen überprüft wurden. Einige Prüfungen lassen sich aber in der Tat problemlos zentral in unserem Package durchführen.
Als Konsequenz aus o.g. Schwachstelle sollten wir also definitiv sämtliche 'White-Space'-Angaben aus den Header-Variablen entfernen. Weitere sinnvolle Checks sind die Überprüfung sämtlicher angegebener Email-Adressen mittels einem geeigneten regulären Ausdruck sowie des Nachrichten-Textes.
Erweitert sieht die Funktion dann wie folgt aus:
#[...]
sub sendMail {
my %mail = @_;
###
# Voreinstellungen
###
# Sicherheits-Einstellung:
# - White-Space-Zeichen in Header-Variablen in Leerzeichen umwandeln
my @mail_header = (
\$mail{'to'},
\$mail{'from'},
\$mail{'namefrom'},
\$mail{'cc'},
\$mail{'bcc'},
\$mail{'subject'}
);
foreach (@mail_header) {
${$_} =~ s/\s/ /g;
}
# - Mail-Format testen
my @mails = ($mail{'from'},$mail{'to'},$mail{'cc'},$mail{'bcc'});
foreach (@mails) {
if ($_ !~ /^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$/ ) {
$mail_error = "Die eMail-Adresse '$_' entspricht nicht dem
vorgeschriebenen Syntax";
print STDERR $mail_error;
return undef;
}
}
# - Plain-Text testen
if (!$mail{'text'}) {
$mail_error = "Es wurde kein Email-Text angegeben";
print STDERR $mail_error;
return undef;
}
###
# Mail-Programm starten
###
#[...]
}
Hinweise:
- Den recht komplex anmutenden regulären Ausdruck zur Überprüfung des Email-Syntax habe ich von der Seite http://www.regenechsen.de/ übernommen, die eine sehr gute Einführung in reguläre Ausdrücke bietet.
- Aufgrund der Zeichen
^und$am Anfang und Ende des regulären Ausdrucks, die ja für Anfang bzw. Ende des Strings stehen, wird gleichzeitig auch die Eingabe von mehreren Adressen in einer Adress-Zeile unterbunden, wie z.B.beliebige@andere_adresse.com; zweite_beliebige@andere_adresse.com;, und somit eine weitere Möglichkeit des Mißbrauchs unterbunden. - Die letzte Abfrage prüft, ob überhaupt eine Nachricht angegeben wurde - eine E-Mail ohne Text macht meist wenig Sinn.












