Viele glauben, dass die meisten von PHP-Programmierern fabrizierten Sicherheitslücken bei include, require oder bei mySQL-Queries liegen. Doch dem ist nicht so - denn gerade die Spammer nutzen unsichere Formulare aus, um ihre ungeliebten Werbenachrichten über fremde Server zu versenden.
1. Die Sicherheitslücke
Viele Programmierer, vor allem Neulinge, verwenden die mail()-Funktion von PHP, mit der bequem E-Mails versendet werden können, beispielsweise über ein Kontaktformular.
Ein Blick in das Manual zeigt:
bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]] )
Ein typisches Kontaktformular könnte z.B. diesen Aufbau enthalten:
Name:
E-Mail:
Betreff:
Nachricht:
Der Aufruf der Mail-Funktion könnte demnach in etwa so aussehen:
PHP-Code:
mail('admin@website.com', $_POST['betreff'], $_POST['nachricht'], 'FROM: '.$_POST['email']);
1.1 Das Problem
Der häufig unterschätzte Fehler ist, dass die Daten nicht auf ihre Korrektheit überprüft werden, sondern direkt an die mail()-Funktion übergeben werden.
Spammer suchen nach solchen Formularen und nutzen diese systematisch aus.
1.2 Die Ursache
Nach RFC2822 ist der Aufbau einer E-Mail festgelegt - sie muss einen Header und Body enthalten, wobei der Body mit der Nachricht gleichbedeutend ist. Die Nachricht kann auch leer sein.
Original von http://www.faqs.org/rfcs/rfc2822.html
Messages are divided into lines of characters. A line is a series of
characters that is delimited with the two characters carriage-return
and line-feed; that is, the carriage return (CR) character (ASCII
value 13) followed immediately by the line feed (LF) character (ASCII
value 10). (The carriage-return/line-feed pair is usually written in
this document as "CRLF".)
A message consists of header fields (collectively called "the header
of the message") followed, optionally, by a body. The header is a
sequence of lines of characters with special syntax as defined in
this standard. The body is simply a sequence of characters that
follows the header and is separated from the header by an empty line
(i.e., a line with nothing preceding the CRLF).
Messages are divided into lines of characters. A line is a series of
characters that is delimited with the two characters carriage-return
and line-feed; that is, the carriage return (CR) character (ASCII
value 13) followed immediately by the line feed (LF) character (ASCII
value 10). (The carriage-return/line-feed pair is usually written in
this document as "CRLF".)
A message consists of header fields (collectively called "the header
of the message") followed, optionally, by a body. The header is a
sequence of lines of characters with special syntax as defined in
this standard. The body is simply a sequence of characters that
follows the header and is separated from the header by an empty line
(i.e., a line with nothing preceding the CRLF).
Insbesondere ist zu beachten, dass der Header und Body mit einer Leerzeile voneinander getrennt sind.
2. Der Angriff
Versetzen wir uns in die Perspektive eines Angreifers. Er wird mit Sicherheit zuerst einmal das Formular auf seine Sicherheit überprüfen, indem er Daten einfüllt, auf die das Script hoffentlich nicht vorbereitet ist.
Beispielsweise könnte er in das Feld 'Absender' folgende Daten eingeben (zu beachten ist hierbei, dass es keine Rolle spielt, wie die Felder in einem Internetbrowser dargestellt werden!)
bla@test.de
Subject: Unser neues Angebot
To: mail@empfaenger.com
bcc: mehrempfaenger@domain.com
Unser neues Angebot! Jetzt kaufen!
Subject: Unser neues Angebot
To: mail@empfaenger.com
bcc: mehrempfaenger@domain.com
Unser neues Angebot! Jetzt kaufen!
Dadurch, dass wir ungeprüfte Parameter an die Mailfunktion übergeben, wird nun als Headerinformationen übergeben:
FROM: bla@test.de
Subject: Unser neues Angebot
To: mail@empfaenger.com
bcc: mehrempfaenger@domain.com
Unser neues Angebot! Jetzt kaufen!
Subject: Unser neues Angebot
To: mail@empfaenger.com
bcc: mehrempfaenger@domain.com
Unser neues Angebot! Jetzt kaufen!
Alle anderen Informationen aus dem Kontaktformular werden nun lediglich an den Body angehängt - nicht an den Header, wie eigentlich beabsichtigt. Durch die Kontrolle über den Header hat man nun auch die Kontrolle über den Empfänger - der fest eingestellte Empfänger wird ignoriert und stattdessen an beliebige Empfänger versendet.
2.1 Abhilfe schaffen
Abhilfe schafft man, indem man die Daten vorher überprüft und nicht direkt an mail() übergibt.
So sollte man z.B. per str_replace jedes Vorkommen von \r und \n in der E-Mailadresse ersetzen.
PHP-Code:
str_replace(array("\r", "\n"), '', $_POST['absender']);
3. Die hidden-field Methode...
... sollte man nie verwenden.
Hierbei handelt es sich um Formulare, die bereits ein verstecktes input-field enthalten, in denen der Empfänger enthalten ist.
Das könnte z.B. so aussehen:
Code:
<input type="hidden" name="reciever" value="meinemail@domain.com" />
PHP-Code:
mail($_POST['reciever'], $subject, $message, 'FROM: '.$from);
Das Problem hierbei ist jedoch, dass HTML-Code für jedermann einsehbar ist - und natürlich auch manipulierbar. So könnte ein Spammer jeden beliebigen Absender in das hidden-field schreiben (und somit den vom Programmierer eingetragenen Empfänger einfach überschreiben) und auch so das Formular für seine Zwecke missbrauchen. Ein Angriff über den Header ist somit unnötig geworden.
Fazit
1. Daten niemals ungeprüft an mail() übergeben, auf Carriage-Returns (\r) und Newlines (\n) überprüfen.
2. Keine hidden-felder für wichtige Daten verwenden - diese können eingesehen und leicht manipuliert werden!
Wenn man sich an solche grundlegenden Regeln hält, macht man es den Spammern schon wesentlich schwieriger, die eigene Website für ihre Zwecke zu missbrauchen....
Einen Kommentar schreiben: