So sichern Sie Ihre PHP-Kontaktformulare gegen Spammer ab und verhindern Mißbrauch.
Häufig verwenden Spammer Kontaktformulare von Webseiten, um Ihre E-Mails zu versenden. Dieses Tutorial beschreibt, wie man diesen Mißbrauch wirksam eindämmen kann.
Viele glauben, dass Ihnen so etwas nicht passieren kann. Schließlich haben Sie ja das Eingabefeld Name als einzeiliges Textfeld mit einer Länge von z.B. 20 Zeichen angelegt. Dies hilft nicht, da der Spammer Ihr Script direkt aufrufen kann und dort so viele Zeichen eingeben kann, wie er möchte. Auch eine Prüfung mit Javascript vor dem Senden erhöht den Schutz in keiner Weise!
Beispiel eines kontakt.php-Scripts:
<?
//Zusammenbestellen des Mailtextes
$body="Kontaktformular:\n\n";
$body.="Name: $_POST[name] \n";
$body.="E-Mail: $_POST[email] \n";
$body.="\nText:\n $_POST[text] ";
$Betreff="Kontaktformular";
$Header="From: $_POST[name]<$_POST[email]>";
mail("betreiber@email.de",$Betreff,$body,$Header);
?>
Dieses Script sieht eigentlich sicher aus. Die Variablen werden mit $_POST geladen und verwendet. Auch der Empfänger wurde fest eingegeben. Eigentlich dürfte es nicht möglich sein, darüber Spam zu versenden.
Das Problem liegt in der Variable $Header. Diese trägt den Namen aus dem Formular als Absender der E-Mail ein. Dies könnte man auch weglassen, und das Formular ist sicher. Allerdings verliert der Webseitenbetreiber den komfort, einfach auf Antworten klicken zu können, um dem Absender eine Antwort zu schicken.
Das Problem liegt in der Struktur einer E-Mail.
Diese besteht immer aus einem Kopf und einem Body. Der Kopf enthält alle wichtigen Daten zum Empfänger, Betreff etc.
Der Body enthält die eigentliche Nachricht. Getrennt werden beide durch eine Leerzeile.
Beispiel einer E-Mail mit Header (gekürzt)
To: "Betreiber Name " <betreiber@email.de>
From: Hans Muster<hans@muster.de>
Subject: Ich bin der Betreff
Date: Fri, 23 Mar 2007 11:25:30 +0100
Hallo,
ich bin der Text der E-Mail
Ein potentieller Spamversender versucht nun, in den einzelnen Formularfeldern andere, als die gewollten Daten einzutragen. Würde der Angreifer in unserem Beispiel anstatt den Namen "Hans Muster " dieses hier eintragen:
Beispiel einer manipulierten Eingabe:
Hansmuster
To: SpamOpfer@Mailserver.de
Subject: By super good items
Dieses ist der Inhalt der Spam-Mail
So würde das Kontaktformular tatsächliche eine Spam-Mail versenden:
Hier ein Beispiel für das Kontaktformular nachdem ein Spammer eine Mail über diese Art versendet hat:
E-Mail-Quelltext:
To: "Betreiber Name " <betreiber@email.de>
From: Hansmuster
To: SpamOpfer@Mailserver.de
Subject: By super good items
Dieses ist der Inhalt der Spam-Mail
Subject: Ich bin der Betreff
Date: Fri, 23 Mar 2007 11:25:30 +0100
Hallo,
ich bin der Text der E-Mail
Der Quelltext, den der Spammer eingefügt hat, ist rot dargestellt. Wir sehen nun, dass es 2 mal das Feld to gibt. Die meisten Mailserver interpretieren beide oder das letzte von beiden. Deshalb wird die Mail nun an den manipulierten Empfänger verschickt. An der Stelle, wo der Spammer eine Leerzeile eingefügt hat, beginnt der Mailtext. Aus diesem Grund kann der Angreifer beliebigen Text einfügen.
Es gibt noch weitaus bessere Methoden, den Spam zu versenden um z.B. mehrere Empfänger auf ein mal zu adressieren oder um den eigentlichen Mailtext vom Formular verschwinden zu lassen. Dies ist für die Lösung des Problems aber unerheblich (außerdem will ich hier keine Anleitung zum Spammen verschicken!)
Wie in jedem PHP-Script, sollten Sie die Eingaben Ihrer Besucher genau prüfen, bevor Sie diese verarbeiten.
Mit Hilfe von regulären Ausdrücken, können Sie sehr einfach testen, ob die eingegebenen Daten wirklich dem beabsichtigtem Format entsprechen.
Quelltext mit Absicherung:
<?
$fehler=0;
//Prüfen der Daten:
//Festlegen der Suchmuster für die Prüfung
$regex[email]="^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@([a-zA-Z0-9-]+\.)+([a-zA-Z]{2,4})$";
$regex[name]="^[a-z\ßäüöÄÜÖ\-\ ]{1,}$";
//Prüfen der E-Mail-Adresse:
if (!eregi($regex[email],$_POST[email]))
{
echo "Fehler: Die E-Mail-Adresse ist ungültig"
die();
$fehler=1;
}
//Prüfen des Namen:
if (!eregi($regex[name],$_POST[name]))
{
echo "Fehler: Der Name ist ungültig "
die();
$fehler=1;
}
//Zusammenbestellen des Mailtextes
$body="Kontaktformular:\n\n";
$body.="Name: $_POST[name] \n";
$body.="E-Mail: $_POST[email] \n";
$body.="\nText:\n $_POST[text] ";
$Betreff="Kontaktformular";
$Header="From: $_POST[name]<$_POST[email]>";
if ($fehler != 1) {
mail("betreiber@email.de",$Betreff,$body,$Header);
}
?>
Dieses Beispiel sorgt dafür, dass nur ein gültiger Name bzw. E-Mail-Adresse eingegeben werden können. Sobald ein Zeilenumbruch stattfindet, oder Sonderzeichen vorkommen, verhindert das Script das versenden der Mail.
Diese Prüfung müssen Sie mindestens für alle Felder durchführen, die im Kopfteil der E-Mail eingebunden werden. Ich empfehle jedoch, die Prüfung auch für alle anderen Formularfelder zu machen.
Ich hoffe, Sie können die Tipps aus diesem Workshop weiter verwenden.
Für Fragen und Anregungen, nehmen Sie einfach Kontakt auf.