Jeder, der Perl dazu verwendet, um Internetseiten zu betreiben bzw. Internetdienste betreibt, steht irgendwann vor dem Problem, daß er auch mal eine oder auch mehrere Emails versenden will bzw. muß.
Der meist verwendete Ansatz ist die Verwendung von sendmail. Sendmail ist ein Systemdienst von Unix bzw. Linux (das ja ein Unix-Derivat ist).
Eine Lösung könnte z.B. so aussehen:
$text="Dies ist der Text, der versendet werden soll. Natürlich ist dies nur zum Ausprobieren gedacht";
$SENDMAIL='/usr/sbin/sendmail'; open (SENDMAIL,"|$SENDMAIL -t -f -odq meine.mailadresse\@mein-server.de") || &fehler("Kann sendmail nicht öffnen"); print SENDMAIL <<EOF;
To: $sendto
Subject: $subject
From: meine.mailadresse\@mein-server.de
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
Auf diese Art und Weise eine Mail zu verschicken ist eigentlich Standart und wird noch oft in Scripten gefunden.
Sie birgt jedoch vielerlei Risiken: Sie ist anfällig für Spam
Es gibt ja so Schlaumeier, die meinen, die Ganze Welt mit Viagra und so'n Gedöns beglücken zu müssen. Dazu werden millionenfach Emails versendet, in der Hoffnung, daß es ein paar Leute gibt, die dann was kaufen. Für den Versender der Mails ein gutes Geschäft, da solche Mails kein Geld kosten und automatisiert ablaufen.
Das Problem ist jedoch, daß man Server braucht, um Mails zu versenden. Und hier liegt eine Gefahr von sendmail: Unsauber programmierte Scripte können als Spamschleuder verwendet werden.
Ich hatte das Problem auch mal und hab dann in Verbindung mit meinem Hoster herausgefunden, was schief läuft.
Und zwar sah mein Script folgendermaßen aus:
use CGI;
$query=new CGI;
$sender = $query->param('sender');
$text=$query->param('text');
$SENDMAIL='/usr/sbin/sendmail'; open (SENDMAIL,"|$SENDMAIL -t -f -odq meine.mailadresse\@mein-server.de") || &fehler("Kann sendmail nicht öffnen"); print SENDMAIL <<EOF;
To: meine.mailadresse\@mein-server.de
Subject: Kontaktformular
From: $sender
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
Dies war ein Script für ein Kontaktformular, ein Formular also, in dem jemand einen Kommentar und seine Absender-Mailadresse eingeben konnte. Dieses Formular leitete dann eine Mail an mich weiter. Funktionierte auch wunderbar und ist auf den ersten Blick eigentlich Idiotensicher. Meint man zumindest.
Bis mein Hoster mich anrief und meinte, über das Script wurden eben Zigtausend Mails versand und ob ich nun in Viagrahandel eingestiegen bin...
So, wo lag nun das Problem? Zuerst natürlich an dem Typen der die Mails versand hatte. Aber das brachte mich ja nun auch nicht weiter. Wo lag also das Sicherheitsloch im Script?
Nochmal zur Funktion des Scriptes: Es wird der Text und der Absender als Parameter eingelesen, das ist auf den ersten Blick schon mal ein Sicherheitsrisiko. Dann wird eine Mail an MEINE Adresse versendet, die war sogar fest eingegeben, ohne Variable. Lediglich die Absenderadresse war "variabel". Aber wo hat der Absender etwas mit dem Empfänger zu tun, denn Sinn des Spams ist es ja, daß viele Leute die Mail kriegen sollen, und nicht ich in Millionenfacher Ausführung.
Also Serverlogs gewälzt, und siehe da, etwas fiel auf: Natürlich wurde das Script direkt aufgerufen, also nicht über die Kontaktseite. Aber das war eh klar. Und noch was fiel auf: Die übergebene Parameter hatte eine Form, so daß hinter 'sender' nochmal ein to: eingeführt wurde.
Wie das nun ging, zeige ich nun nicht, weil ja die bösen Buben mitlesen. Jedenfalls stellte sich heraus, daß man dem eigentlichen from: noch ein to: mit beliebig vielen Mailempfänger anhängen konnte und sendmail hat das brav mitgemacht, laut Hoster ist das sogar ein "feature" von sendmail (da fällt mir ein Spruch von früher ein: Es ist kein bug, es ist ein feature... haha ...).
Wenn man also etwas per sendmail versendet, sollte man UNBEDINGT darauf achten, daß die Parameter nicht gefakt werden können.
Also |, %00 und Zeilenumbrüche sowie alles ausfiltern, was nicht in ein to: oder from: oder subject: oder cc: oder bcc: (hab ich was vergessen?) hineingehört oder besser erkennen und per Fehler abbrechen! Denn wenn da was drin steht, was da nicht hineingehört, ist es wahrscheinlich ein Spamversuch!
Sendmail ist fehleranfällig und läuft nicht auf allen Servern sendmail ist ein Systemdienst von Unix, meist unter /usr/sbin/sendmail zu finden. Aber eben nur meist, manchmal auch wo anders. Das heißt: Fehlermeldungen! Und zum Anderen läuft es nicht unter Windows, da Windows sendmail nicht kennt. Also blöd, wenn man grad nicht weiß, auf welcher Maschine das Script mal laufen soll... Das kann man natürlich per Software-Abfragen ausbgeln, aber nee, ist nicht der richtige Weg!
Die Verwendung von sendmail ist also relativ einfach, man sollte aber ungebingt auf eine gute Implementierung achten!
Man sollte lieber Module anstatt Sendmail direkt verwenden. Zum Beispiel MIME::Lite oder Mail::Sender.
Zum Überprüfen der Mail-Adressen sollte man sich auch nicht auf eine relativ einfache RegEx verlassen. Die RegEx, die auf RFC822-Konsistenz überprüft ist ziemlich lang. Auch hier gibt es Module wie Mail::RFC822::Address.
Und wenn man doch mit Sendmail arbeiten will, sollte man die Option "oi" verwenden.
Kommentar von Admin
Wie gesagt, ich selbst halte sendmail auch nicht für das Gelbe vom Ei, aber mir ist es auf verschiedenen Maschinen schon passiert, daß ich darauf zugreifen mußte, weil o.g. Module nicht vorhanden waren.
Prinzipiell kann ich aber nur zustimmen: sendmail ist fehleranfällig und kann zum Versenden von Spam verwendet werden, man sollte also unbedingt o.g. Module verwenden, falls diese vorhanden sind.
Noch etwas zu sendmail:
Es gibt ja in sendmail noch unzählige "Schalter", aber selbst diese funktionieren nicht auf allen Servern, wie ich aktuell auf dem hier laufenden feststellen muß...
Kommentar von Renee Bäcker
Ja, dass verschiedene Optionen nicht überall funktionieren ist mir auch schon passiert. Das kann ein echtes Problem sein und lange Fehlersuche bedeuten (man vermutet ja doch erstmal den Fehler im eigenen Code und nicht in fehlenden sendmail-Optionen).
Kommentar von alex
Vorallem den Sendmail-Parameter -t raus nehmen!!! Sehr gefährlich!
Siehe man sendmail
-t Extract recipients from message headers. These are added to any recipients specified on the command line.
Damit macht mans Spammer leicht!
Kommentar von Bastian
Tja, etwas spät. Aber trotzdem.
Eine andere Möglichkeit wäre die Option -t bei sendmail weg zu lassen. Dann wird nur an den Empfänger verschickt, der auf der im Parameter von sendmail angegeben wird, und es wird nicht noch versucht, andere Empfänger aus dem Header der Email zu extrahieren.
Hab ich nicht getestet, sollte aber doch eigentlich funktionieren.