Andy: php mail Zeilenumbruch

Guten Morgen,

ich möchte ein PHP Script erstellen, welches eine Email versendet, im ersten Schritt so weit wie möglich gegen MailInjektionen absichern.

Nach lesen verschiedener Bespiele im Netz bin ich etwas verwirrt.
Klar ist mir wie ich herangehen muss.

Unklar ist mir braucht der Mailheader nun Zeilenumbrüche oder nicht?

Einmal lese ich (auch hier im Forum) "Ja, Email-Header werden durch Zeilenumbrüche voneinander abgetrennt."
An einer anderen Stelle
"Sämtliche Informationen, die in den E-Mail-Header gelangen werden (wie z.B. Absender oder Betreff) benötigen keine Zeilenumbrüche."

  
$header .= "From: "Mir" < "Ich@beiMir.de>\n";  
$header .= "Reply-To: "zumir"\n";  
$header .= "MIME-Version: 1.0\n";  
$header .= "Content-type: text/plain; charset=iso-8859-1\n";  

Brauche ich den Zeilenumbruch?

Danke
Andy

  1. echo $begrüßung;

    Unklar ist mir braucht der Mailheader nun Zeilenumbrüche oder nicht?

    Die einzelnen Zeilen des Mailheaders müssen mit Zeilenumbrüchen getrennt sein. Header und Body werden durch zwei Zeilenumbrüche getrennt.

    "Sämtliche Informationen, die in den E-Mail-Header gelangen werden (wie z.B. Absender oder Betreff) benötigen keine Zeilenumbrüche."

    Deutlicher formuliert: Informationen, die als Wert in eine E-Mail-Header-Zeile gelangen sollen, benötigen keine Zeilenumbrüche (jedenfalls nicht im Normalfall).
    Durch den Zeilenumbruch würde der Rest als neue Header-Zeile betrachtet werden. Das gilt es zu vermeiden.

    $header .= "From: "Mir" < "Ich@beiMir.de>\n";

    $header .= "Reply-To: "zumir"\n";
    $header .= "MIME-Version: 1.0\n";
    $header .= "Content-type: text/plain; charset=iso-8859-1\n";

    
    > Brauche ich den Zeilenumbruch?  
      
    Ja, zwischen den Zeilen, nicht in den Werten. Wenn du allerdings beispielsweise einen benutzereingegebenen Namen in die From-Zeile einbauen willst, und du stellst fest, dass bereits in der Eingabe ein Zeilenumbruch enthalten ist, dann ist das vermutlich ein Angriffsversuch. Besonders dann, wenn sich das Eingabefeld üblicherweise einzeilig verhält.  
      
      
    Vermutlich wird dich auch noch jemand darauf hinweisen wollen, dass die Headerzeilen eigentlich mit \r\n abzutrennen sind. Das ist aber unter PHP nicht nötig und unter bestimmten Systemkonstellationen sogar ungünstig (siehe Handbuchseitenhinweise zur Funktion mail()). PHP selbst fügt als Trennzeichen zwischen Header und Body nur einfache \n ein. Ein Mail-Transfer-Agent muss also auch damit klarkommen. Demzufolge kann man selbst ruhigen Gewissens auch nur \n verwenden. Wenn der MTA nicht damit klar kommt, scheitert er ja spätestens bei der Header-Body-Trennung. Außerdem ist der MTA des Betriebssystems dafür verantwortlich, betriebssystemübliche Trennzeichen in normgerechte/kontextgerechte umzuwandeln.  
      
      
    echo "$verabschiedung $name";
    
    1. Hallo dedfix,

      vielen Dank für die ausführliche Antwort.

      »»Vermutlich wird dich auch noch jemand darauf hinweisen wollen, dass die »»Headerzeilen eigentlich mit \r\n abzutrennen sind. Das ist aber unter PHP »»nicht nötig und unter bestimmten Systemkonstellationen sogar ungünstig »»(siehe Handbuchseitenhinweise zur Funktion mail()).

      Ich habe noch ein bisschen gesucht, je mehr man sucht um so mehr verwirrt es einen
      Ok, da ich aber mit der Mailfunktion noch ziemlich am Anfang stehe, Schritt für Schritt sonst wird das nix.;)
      lt. manual

        
      $header  = 'MIME-Version: 1.0' . "\r\n";  
      $header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";  
      // zusätzliche Header  
      $header .= 'To: Simone <simone@example.com>, Andreas <andreas@example.com>' . "\r\n";  
      $header .= 'From: Geburtstags-Erinnerungen <geburtstag@example.com>' . "\r\n";  
        
       $header= preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', "", $header);  
      
      

      sollte den Header absichern, auch mail to und den Betreff?

      \n ist ein Carriage Return
      \r ist ein Line Feed
       %0A ist die Hexadezimale Schreibweise für ein Linefeed LF
       %0D ist die Hexadezimale Schreibweise für ein Cariage Return CR

      Warum aber auch noch CA und LF uind für was Hexadezimal?

      Meine nächste Frage, im Inhalt kann ich das nicht nutzen, Für den Inhalt wäre es besser

      $inhalt= preg_replace( "/(content-type:|bcc:|cc:|to:|from:)/im", "", $inhalt); ?

      Weil da brauch ich doch die Zeilenumbrüche.

      Eigentlich sollte ich jedes Formularfeld mit der zweiten Variante (wie Inhalt) prüfen ?

      Vielen Dank
      Andy

      1. echo $begrüßung;

        $header  = 'MIME-Version: 1.0' . "\r\n";

        $header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
        // zusätzliche Header
        $header .= 'To: Simone simone@example.com, Andreas andreas@example.com' . "\r\n";
        $header .= 'From: Geburtstags-Erinnerungen geburtstag@example.com' . "\r\n";

        $header= preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\n|\r)\S).*=i', "", $header);

        
        > sollte den Header absichern, auch mail to und den Betreff?  
          
        Nein, so wird das nichts. Du sollst nicht vom gesamten Header die Zeilenumbrüche entfernen, sondern nur darauf achten, dass keine Zeilenumbrüche in Werten sind, die in eine der Header-Zeilen eingefügt werden sollen. Man kann, wenn man Zeilenumbrüche in diesen (vom Benutzer stammenden) Werten feststellt, die Verarbeitung im Prinzip grußlos abbrechen. Denn mit ziemlich hoher Wahrscheinlichkeit hat da ein Automat versucht, Lücken auszunutzen. Den interessieren dann auch keine Fehlermeldungstexte.  
          
        Das Suchmuster deines Regulären Ausdrucks sieht abenteuerlich aus. Es versucht diverse harmlose Zeichenfolgen oder \n oder \r zu finden, die von einem Nicht-Whitespace-Zeichen und beliebigen anderen gefolgt werden zu ersetzen. Wenn jemand Email-Header-Injection versucht, wird auch der erste Wert vor dem Zeilenumbruch sicher nichts gewünschtes sein. Es sollte also reichen, mit einer einfachen Stringsuche nach \r und \n zu suchen.  
          
        if (strpos($value, "\n") !== false or strpos($value, "\r") !== false)  
          exit;  
          
        
        >  %0A ist die Hexadezimale Schreibweise für ein Linefeed LF  
        >  %0D ist die Hexadezimale Schreibweise für ein Cariage Return CR  
        > Warum aber auch noch CA und LF uind für was Hexadezimal?  
          
        Sowohl im PHP-String-Kontext als auch im PCRE-RegExp-Kontext und im mail()-Kontext sind das alles nur Zeichen ohne besondere Bedeutung.  
          
        
        > Meine nächste Frage, im Inhalt kann ich das nicht nutzen, Für den Inhalt wäre es besser  
          
        Der Inhalt ist harmlos. In dem kann alles stehen.  
          
          
        echo "$verabschiedung $name";
        
        1. Hallo Dedlfix,

          wieder Da´nke für Deine Mühe.

          ich sag ja, je mehr ich lese, je verwirrter bin ich. Naja (anwesende sind ausgenommen) das Internet ist halt ne Ansammlung subjektiver Meinungen.

          Ich habe heute nix anderes gemacht als mich mit der Mailinjection beschäftigt....

          Ich versuche mal zusammenzufassen.
          Ich entferne aus allen Werten die (Inhalt nicht) die Zeilenumbrüche zu entfernen. Dr, Web sagt mir wie.

          Díeses Forum heißt zwar Self, aber kannst Du mir sagen wie ich die Zeilenumbrüche aus meinen Header entferne, weil ich weiß nicht wie ich das nur von einen Teil machen soll?

          Danke
          Andy

          1. echo $begrüßung;

            Ich entferne aus allen Werten die (Inhalt nicht) die Zeilenumbrüche zu entfernen.

            Unter normalen Umständen hat ein Wert aus einem einzeiligen Eingabefeld keinen Zeilenumbruch. Wenn der Server doch so einen Wert erhält, ist das mit hoher Wahrscheinlichkeit ein Manipulationsversuch. Du kannst dann die Verarbeitung abbrechen. Es kommt auch nichts Sinnvolles mehr zustande, wenn man die Zeilenumbrüche rausfiltert. Insofern ist es bezüglich der Zeilenumbrüche vergebliche Liebesmüh, mehr Aufwand hineinzustecken als zu testen ob selbige vorhanden sind oder nicht. Ein Codeschnipsel dazu schrieb ich ja schon.

            Díeses Forum heißt zwar Self, aber kannst Du mir sagen wie ich die Zeilenumbrüche aus meinen Header entferne, weil ich weiß nicht wie ich das nur von einen Teil machen soll?

            Die Zeilenumbrüche allein zu entfernen ist nicht sinnvoll. Hinter einem Zeilenumbruch stehen ja meist eine oder mehrere  vollständige Headerzeilen. Ein in eine Headerzeile einzufügender Wert, nahtlos ergänzt um weitere Headerzeilen, ist nichts Gescheites. Du könntest nun mit den üblichen Stringfunktionen den Teilstring bis ausschließlich des Zeilenumbruchszeichens abschneiden, um einen (vielleicht) gültigen Wert zu erhalten. Doch was bringt dir dieser Wert am Ende, wenn er doch nur Teil einer missbräuchlichen Nutzung deines Formulars ist?

            echo "$verabschiedung $name";

          2. Hi,

            Ich habe heute nix anderes gemacht als mich mit der Mailinjection beschäftigt....

            benötigst Du überhaupt Usereingaben im Mail-Header, also in From, To oder Subject?
            Wenn nicht und Du alle Usereingaben in den Mail-Body übernimmst, hast Du Dir völlig unnötige Gedanken gemacht.

            freundliche Grüße
            Ingo

            1. Guten Abend,

              benötigst Du überhaupt Usereingaben im Mail-Header, also in From, To oder Subject?

              Nein, die sind alle fest.
              ich habe 6 Felder,
              drei Listenfelder,
              eine Textare,
              sowie zwei Textfelder.

              Wenn nicht und Du alle Usereingaben in den Mail-Body übernimmst, hast Du Dir völlig unnötige Gedanken gemacht.

              Irgendwo las ich aber das spielt keine Rolle, ich habe das jetzt versucht so zu richten, wie dedlfix es mir riet.

              Vielen Dank
              Andy

              1. Hi,

                Wenn nicht und Du alle Usereingaben in den Mail-Body übernimmst, hast Du Dir völlig unnötige Gedanken gemacht.

                Irgendwo las ich aber das spielt keine Rolle, ich habe das jetzt versucht so zu richten, wie dedlfix es mir riet.

                dann hast Du vermutlich etwas falsch verstanden. Der dritte Parameter in mail() beendet die Mail-Header mit einem doppelten Zeilenumbruch, so dass die folgenden Daten zwangsläufig im Mail-Body landen und keine Manipulation mehr möglich ist.

                freundliche Grüße
                Ingo