zur « Themenübersicht Webmaster-Tricks

HTML_CSS - Sparte Schutz

PHP Formularcheck

Eingetragen am 13.11.2007

Wie an anderer Stelle erwähnt, können PHP-Formulare zu unliebsamen Überraschungen führen. Dass wir mit Spam zugemüllt werden, ist noch die harmlose Form. Schwerer wiegt da eine evtl. Mailinjektion, womit dann über unseren Server Spam verteilt wird. Siehe auch Spammschleudern

Eine Regel lautet:
Übergebe per mail() keine Variable, die nicht vorher geprüft wurde!
Wie können wir uns nun schützen?
Ich führe hier einige Gedanken, Beispiele und Lösungen auf, ganz unten befindet sich dann ein Downloadlink für das fertige Formular.
Als Erstes solltet Ihr Wert, das gilt für jede Datenbankabfrage oder Übergabe von Variablen, auf eine saubere Übergabe legen!
Eine per POST übergebene Variable könnte ich auch so übergeben:
http://www.DeineDomain.de/script.php?name=Variable&IchhackeDeineSeite
Damit wäre einem Missbrauch, Hackversuchen und Injections Tür und Tor geöffnet!
Einige Provider haben sich darauf eingestellt und eine globale Variablenübergabe ist so nicht mehr möglich. Auch wenn doch, sollte man sich eine saubere Übergabe angewöhnen.
Die per POST übergebene Varibable wird an eine weitere Übergeben und diese durchläuft dann die weiteren Prüfungen.
$variable = ($_POST["send_variable"]);
Damit stellen wir sicher, dass die Variable nur über ein Formular per POST übergeben wurde.

Dann soll das Script bei bestimmten Eingaben unmittelbar abbrechen, da mit Spam oder einer Injektion zu rechnen ist. Gefährlich ist der Zeilenumbruch, damit könnte man weitere Headerinformationen und ein bcc einschmuggeln. So etwas kommt im Namen oder der Mailadresse nicht vor!
Abbruch bei Zeilenumbruch:
strstr($Absendername, '\n') and die 
('Datenfehler, Mail nicht versandt!');
Klartext wie hier hilft meistens nicht, da die Variablen auch im Unicode versandt werden. Besser ist es, diesen zusätzlich als Filterkriterium zu verwenden.
\n in Unicode = \n

Prüfung der Maildresse auf das richtige Format. Mailadressen beinhalten Buchstaben und Zahlen, mal einen Punkt, aber keine Sonderzeichen wie z.B. ein \, so fällt die Prüfung relativ leicht.
Erlaubt sind Mailadressen wie
name@xyz.de, mein.name@xyz.de, oder mein.name75@xyz.de.
ereg("^([a-zA-Z0-9\.\_\-]+)@([a-zA-Z0-9\.\-]+\.[A-Za-z]+)$", $Absendermail)
or die ('Datenfehler, falsche Mailadresse!');
Abrechen soll das Script auch bei offentsichtlichem Spam. Hierbei filtern wir Zeichen aus den Variablen heraus.
strstr($Absendername, 'http') and die 
('Datenfehler, Mail nicht versandt!');
Auch hier sollte auch der Unicode nicht vergessen werden!
http

Steht z.B. für http, ein Spamkriterium. Diese Funktion können wir mit weiteren Begriffen beliebig erweitern!

Nun entfernen wir gefährliche Spitzklammern:
$Mitteilung = ereg_replace("<"," ",$Mitteilung);
$Absendername= ereg_replace("<"," ",$Absendername);
Nun begrenzen wir die Anzahl der Zeichen, hier für die Mail auf 30 Zeichen. Die Checks müssen natürlich für jede Variable vorgenommen werden!
Gerade die Varibale $Mitteilung sollte hier begrenzt werden. Zumeist reichen hier 600-1.000 Zeichen aus.
$Absendername = substr($Absendername ,0,30);

Nun Maskieren wir die Hochkommas:
$Absendername = mysql_escape_string($Absendername);
Nun ist unser Formular schon eigentlich recht sicher.
Aber...

Weitere Gefahren:
Leider erkennen Bots unser Formular und kein Spammer macht sich die Mühe, unser Formular manuell aufzurufen. Die können augenscheinlich auch Formulare emulieren und übergeben die Variablen sauber per POST. Es muss also sichergestellt werden, dass der Scriptaufruf auch von unserer Seite erfolgt.
Eigentlich kann man die Bots, leicht aussperren. Es kann noch eine Prüfung statt finden, ob die Übergabe der Variablen von der eigenen Seite statt findet. Dies geht relativ leicht, in dem man die Header-Informationen mit $_SERVER['HTTP_Referrer'] ausliest und das Script abbrechen lässt, wenn der Aufruf nicht von der eigenen Seite erfolgt.
Nachteil: Etliche Browser übertragen gewollt nicht den Referrer und diese Besucher wären dann ausgeschlossen. Ich löste das Problem ein mal in der Weise, dass eine Zufallszahl als Grafik, ein sog. Captcha generiert wurde. Nur wenn diese mit der Eingabe übereinstimmt, läuft das Script und nachfolgend finden dann die o.g. Prüfungen statt.
Allerdings stellte sich das auch nicht als so vorteilhaft dar, da einige Leute die verfremdete Zahl nicht lesen konnten, oder genervt die Seite verließen.
Eine weitere Möglichkeit ist es vielleicht mit zufälligen Abfragen. Auch hier sehe ich ein Problem. Es verärgert und viele sind einfach zu blöde ;-)
Bei einer einfachen Rechenaufgabe wie 2+3*2 kämen zu viele falsche Antworten heraus und viele wären wieder ausgeschlossen.

Meine Meinung:
Captchas, Cookies und Abfragen sind relativ sicher, schließen aber viele Besucher aus. Letztendlich ist es eine Sache der Philosphie, denn ganz ohne Hürden geht es nicht.

Hier einige Strategien:
Es soll ja sicher gestellt werden, dass eine Abfrage von der eigenen Seite erfolgt, dies könnte man so lösen:
Vor dem Mailversand ermittelt Ihr den Referrer, d.h., von welcher Seite der Besucher gekommen ist. Das kann ja nur die EigenesScript.php sein!
Nur wenn der Referrer mit der DeineDomain/EigenesScript.php übereinstimmt, wird das Formular versandt.
Nun entsteht allerdings ein Problem!
Manche Browser, oder solche, die entsprechend konfiguriert sind, übermitteln nicht den Referrer. Wir wollen natürlich, dass auch diese Besucher uns eine Nachricht übersenden können
Wir verfassen eine Fehlermeldung und gleichzeitig einen einfachen mailto-Link. Damit der Besucher nicht seine ganzen Eingaben wiederholen muss, übergeben wir auch diese Variablen.
Natürlich stellt auch dies eine Hürde dar, denn es muss ein Mailprogramm installiert sein. Allerdings sehe ich dies Kompromiss an, da wohl fast jeder ein Mailprogramm installiert hat.
Zudem denke ich, dass die Leute, die bewußt den Referrer abschalten, für diese Maßnahme Verständnis aufbringen.
Das würde dann so ablaufen:
$Url = getenv("HTTP_Referrer");
if (strstr($Url, 'DeineDomain.de/EigenesScript.php')) {
Script
} else {
echo "<p>Datenfehler! Error! Verdacht auf Spam oder Injection!</p> <p>Vielleicht wurde auch einfach nicht Ihr Referrer übertragen.
Leider müssen wir uns vor Spam und Mailinjections schützen. Ihre Nachricht können Sie uns trotzdem übermitteln,
allerdings muss ein Mailprogramm auf Ihrem Rechner installiert sein. Ihre Eingaben sind auch nicht verloren und brauchen nicht neu eingegeben zu werden!
<a href="mailto:DeineMailadresse.de?subject=Anfrage&Body=$Absendername $Absendermail $Mitteilung\">Mitteilung senden »</a></p>"; }
Damit stellt Ihr auf einfache Weise sicher, dass der Scriptaufruf nur von Eurer Seite kommt. Nachteil, es muss auf jeden Fall ein Mailprogramm installiert sein
Natürlich könnte trotzdem noch Spam übermittelt werden, das ist nie zu vermeiden.
Allerdings arbeiten hier ja bekanntlich Robots und keiner macht sich die Mühe, die Eingaben per Hand vor zu nehmen.
Leider ist nun auch die Mailadresse offen zu lesen. Zwar wird kaum ein Robot einerseits das Formular missbrauchen und gleichzeitig die Mailadresse auslesen, aber sicher ist sicher...
Den mailto-Befehl solltet Ihr besser mit Unicode verschleiern!
Link: unicode.php  Zum Verschleiern von Mailadressen und Texten.

Es muss ein Kompromiss zwischen Sicherheit und geringen Hürden gefunden werden. Mailinjections sind durch saubere Variablenübergabe zu lösen, egal, ob hier ein Bot arbeitet.
Spam ist nie gänzlich auszuschließen, aber Bots kann man gut durch eine Zufallsvaribale ausschließen.
Ich verwende mittlerweile zwar kein Captcha (einige Bots können mittlerweile auch diese Grafiken auslesen), aber bei mir muss eine offen zu lesende Codezahl eingegeben werden. Damit schließe ich niemanden aus und stelle gleichzeitig sicher, dass der Aufruf von meiner Seite kommt.
Dass der Code offen zu lesen ist, sehe ich nicht als Nachteil an, da die Zufallszahl erst nach Übergabe der Variablen geschieht.
Selbst wer sich die Mühe macht, die Seite aufzurufen, den Code in sein lokales Formular einträgt, es erfolgt keine Übergabe der Variablen, es folgt eine Fehlermeldung. Der Code muss von der Script-Seite stammen, sonst funzt das Formular nicht. Also ist es egal, dass der Code offen zu lesen ist.
Wer sich dafür interessiert, hier kann man es herunter laden: kontakt.zip



Bisherige Kommentare:        Kommentar schreiben»

Klaus schrieb am 20.03.2007
Irgend jemand hatte mein Formular vergewaltigt und über meinen Server tausende von Mails versandt :-( Danke! Nun ist das Übel vorbei!

 

Bisherige Kommentare:        Kommentar schreiben»

Klaus schrieb am 20.03.2007
Irgend jemand hatte mein Formular vergewaltigt und über meinen Server tausende von Mails versandt :-( Danke! Nun ist das Übel vorbei!