Mail Header Injection: Irgendwann lernen es alle [Sicherheitsupdate]

Im Rahmen einer Arbeit zur Sicherheit von PHP-Webanwendungen stolpere ich über immer mehr
Seiten, die sich diesem Thema – meist nebensächlich – gewittmet haben. Diese Auseinandersetzungen
mit der Sicherheit bei Webanwendungen sind sehr zu begrüßen. Jedoch weiß nicht jeder, der etwas
darüber schreibt, auch wirklich Bescheid. (Natürlich weiß ich auch nicht über alles Bescheid!)
Und wenn Halbgares ins Netz gelangt und dank einer guten
Platzierung bei Google auch von anderen ungeprüft übernommen wird, dann verschlechtert sich die
Chance auf sichere Webanwendungen mit dem Grade der Ausbreitung des unvollständigen Wissens.

Mail Header Injection

Was das ist und wie es kommt, möchte ich andere erklären lassen. Hierzu meine Empfehlung:

http://www.securephpwiki.com/index.php/Email_Injection
(SecurePHP)

Und schon kommen wir zu dem, was ich zeigen wollte. Wer bei Google nach „email“ und „injection“ sucht,
trifft auf Anleitungen mit Namen wie E-Mail Injection in PHP verhindern und Sicheres Kontaktformular mit PHP – Spam verhindern.
Diese Anleitungen sind unvollständig!

So nicht!

Die meisten Codebeispiele prüfen nicht alle der Eingabewerte für die Funktion mail(). Hier einige Beispiele aus dem Netz:

Beispiel 1 ($_POST[‚Betreff‘] und $_POST[‚Nachricht‘] ohne Prüfung!):
[code]

[/code]

Beispiel 2 ($_POST[’subject‘] und $_POST[‚message‘] ohne Prüfung!):
[code]

[/code]

Welche Parameter muss ich säubern?

Um Mail Injection mit ziemlicher Sicherheit zu verhindern, müssen alle Eingabewerte gesäubert werden!
Hier nochmal ein Aufruf der mail()-Funktion zur Erinnerung:

[code][/code]

Nochmal, damit endlich mal alle verstehen: ALLE PARAMETER SÄUBERN! Mit einigen Tricks und unter Ausnutzung von Bugs in
manchen PHP-Versionen, können Spamer auch über den Betreff und dem E-Mail-Körper unerwünschte Sachen mit euren
Formularen anstellen.

Alle Parameter säubern

Laut [RFC822]http://www.ietf.org/rfc/rfc0822.txt gehören im Header der E-Mail keine Zeilenumbrüche. Also weg damit. Sollten sich trotzdem – duch Bugs
oder was auch immer – Zeilenumbrüche einschmuggeln lassen, so entfernen wir Schlüsselwörter, die im Header eine Bedeutung für den Mailversand haben.
Den E-Mail-Inhalt können wir nicht von Zeilenumbrüchen säubern, sonst zerstören wir den Mailtext. Aber wir können auch
hier nach Schlüsselwörter Ausschau halten und sie entfernen. Im Link am Anfang wird vorgeführt, wie sich der komplette
E-Mail-Text unter Zuhilfenahme von Schlüsselwörter verändern lässt.

Meine Empfehlung [Sicherheitsupdate 04.12.2008]

[Sicherheitsupdate 04.12.2008]: Entfernt verschachtelte Schlüsselworte.

[code]
= 2) {
/* replace until done */
while ($param_ != $filtered || !isset($filtered)) {
if (isset($filtered)) {
$param_ = $filtered;
}
$filtered = preg_replace(
„/(%0A|\\\\r|%0D|\\\\n|%00|\\\\0|%09|\\\\t|%01|%02|%03|%04|%05|“ .
„%06|%07|%08|%09|%0B|%0C|%0E|%0F|%10|%11|%12|%13)/ims“, „“, $param_);
}
}
return $param_;
}
?>
[/code]

Der zweite Parameter ist beim Säubern des E-Mailtextes auf „1“ zu setzen, damit Zeilenumbrüche und andere Sonderzeichen nicht
entfernt werden.

Und so wird die Funktion verwendet:
[code]
[/code]

Das könnte dich auch interessieren …

11 Antworten

  1. Holger sagt:

    Guten Abend,

    ich bekomme die Meldung:

    Notice: Undefined variable: filtered in /usr/export/www/vhosts/funnetwork/hosting/pacman1973/inc/function.php

    Aber ich finde nicht heraus, warum ich diese Meldung bekomme… :-(

    Kann mir evtl. jemand helfen?

    LG

  2. Erich Kachel sagt:

    Danke Holger, es war eine nicht initialisierte Variable in meinem Code. In der nächsten Version nach 0.7.1 ist dies behoben.

  3. Holger sagt:

    Alles klar, vielen Dank noch einmal für deine Hilfe! :-)

  4. Jürgen sagt:

    Hallo Erich,
    sehr schönes Skript und sehr gute Erklärung zu Mail-Injektion.
    Ich hätte nur noch einen Vorschlag, der den doch recht aufwendigen Vergleich des gefilterten mit dem ungefilterten Text einzusparen, der bei jedem Durchlauf der while-Schleife erforderlich ist.

    Man könnte den Parameter Anzahl nutzen, den die Funktion preg_replace() bietet; dieser gibt die Anzahl der Ersetzungen an. Solange er nicht 0 ist, läuft die Schleife weiter.
    Ich denke, das würde die Sache sehr beschleunigen, oder?

  5. Erich Kachel sagt:

    Hallo Jürgen,

    der Grund warum ich „Anzahl“ in preg_replace() nicht verwende ist die Abwärtskompatibilität der sseq-lib bezüglich PHP. Heute habe ich den freehoster „multimania.de“ ausprobiert und z.B. fest gestellt, dass er standardmässig mit PHP 4.4.9 arbeitet. Der Parameter „Anzahl“ kommt aber erst in PHP 5.1.0 dazu. Ich kann also durch diese Konstruktion auch denjenigen Schutz bieten, die – warum auch immer – mit einer älteren Version arbeiten.

  6. Mathias Bank sagt:

    Hallo Jürgen,

    an sich ein guter Artikel. Leider ist er in meinen Augen nicht ganz korrekt. Laut Spezifikation ist es beispielsweise absolut erlaubt, im Betreff „Subject:“ zu haben. Das Problem ist nicht der Schlüsselbegriff, sondern ein evtl. vorhandener Zeilenumbruch mit dem Schlüsselbegriff am Zeilenanfang. Auf den prüft dein regulärer Ausdruck aber gar nicht.

    Im Weiteren macht es doch gar keinen Sinn, beim Matchen des regulären Ausdrucks einen leeren String zum Ersetzen zu verwenden. Statt dessen sollte beim Matchen die Verarbeitung abgebrochen werden.

  7. Andreas sagt:

    Hallo,

    was mir noch unklar ist: wieso filterst du in dem preg_replace nach \n und %0A ? Sind die nicht equivalent ?

    Andreas

  8. Erich Kachel sagt:

    Ja, sind sie; aber in einer normalisierten Form. Hier wird die unterschiedliche Kodierung geprüft.

  9. Andreas sagt:

    Wird ein %0a in der URL also im PHP-String nicht in jedem Fall zu einem \n Zeichen ? Bei mir verhält sich das so.

    Und wenn ich im Formular %0a eingebe, wird es sowieso als normale Zeichenfolge interpretiert, nicht als Steuerzeichen.

  1. 2. Mai 2009

    […] und an jquery/ajax zurückzugeben und weiter zu verarbeiten. Wenn es einen Trick gibt die Funktion Mail Header Injection: Irgendwann lernen es alle [Sicherheitsupdate] | PHP Application and Website D… im JavaScript-Code verfügbar zu machen, wäre das auch gut zu wissen. Aber ich möchte das Problem […]

  2. 4. Mai 2010

    […] reicht, bzw. Anfragen mit solchen Umbr