Der Peter: Ein sicherer Formmailer

Hallo zusammen,
ich möchte auf meiner Website ein Kontaktformular anbieten. Daher brauch ich auch ein Mailingskript.
Mein Skript sieht so aus:

<?php  
// Erfassung der übermittelten Variablen in "Rohvatiablen"  
$emailroh = $_GET['eMail'];  
$nameroh =  $_GET['Name'];  
$nachrichtroh = $_GET['Nachricht'];  
  
// "Verbotene" Zeichen werden manuell(!) ausgefiltert  
$emailroh = str_replace("<", "&lt;", $emailroh);  
$emailroh = str_replace("\n", "", $emailroh);  
$emailroh = str_replace("\r", "", $emailroh);  
$emailroh = str_replace(">", "&gt;", $emailroh);  
$emailroh = str_replace(chr(34), "&quot;", $emailroh);  
$emailroh = str_replace("or", "-oder-;", $emailroh);  
$emailroh = str_replace(chr(39), "&quot;", $emailroh);  
$nameroh = str_replace("<", "&lt;", $nameroh);  
$nameroh = str_replace("\n", "", $nameroh);  
$nameroh = str_replace("\r", "", $nameroh);  
$nameroh = str_replace(">", "&gt;", $nameroh);  
$nameroh = str_replace(chr(34), "&quot;", $nameroh);  
$nameroh = str_replace("or", "-oder-;", $nameroh);  
$nameroh = str_replace(chr(39), "&quot;", $nameroh);  
$nachrichtroh = str_replace("<", "&lt;", $nachrichtroh);  
$nachrichtroh = str_replace(">", "&gt;", $nachrichtroh);  
$nachrichtroh = str_replace(chr(34), "&quot;", $nachrichtroh);  
$nachrichtroh = str_replace("or", "-oder-;", $nachrichtroh);  
$nachrichtroh = str_replace(chr(39), "&quot;", $nachrichtroh);  
$nachrichtroh = str_replace("\n", "", $nachrichtroh);  
$nachrichtroh = str_replace("\r", "", $nachrichtroh);  
  
  
// Sperre: Jede IP kann nur 1 Mail pro Tag senden  
  
$host =  $_SERVER["REMOTE_ADDR"];  
$eintragung = $host;  
$eintragung .= "|";  
$eintragung .=   date("j.m.Y");  
$dateiname = "mailsperre24h.txt";  
$securitydatei = file_get_contents($dateiname);  
  
$pos = strpos($securitydatei, $eintragung);  
  
if ($pos === false) {  
// IP hat heute(!) noch keine eMail verschickt!  
  
///////////////////////////////////////////////  
// Begin Mail  
  
// Empfänger definieren  
$empfaenger  = 'mail@example.org';  
  
// Betreff definiert  
$betreff = 'Ein Besucher hat das Kontaktformular auf der Webseite ausgefüllt';  
  
// Nachrichtentemplate definieren  
$nachricht = '  
<html>  
<head>  
  <title>Ein Besucher hat das Kontaktformular ausgefüllt</title>  
  <style type="text/css">  
     td { padding: 5px;  
       border-style: solid;  
        border-color: black;  
         width: 250px;  
     }  
    th { padding: 5px;  
       border-style: none;  
  
       text-align: left;  
  
     }  
  table { border-style:none;  
  
        }  
  </style>  
</head>  
<body>  
 <p>Sehr geehrter Admin,<br>&nbsp;<br>die folgende Nachricht wurde am *Datum* um *Zeit* mit dem Kontaktformular verfasst. Der Verfasser hat folgende IP:&nbsp;<b>*IP*</b></p>  
 <p><i>Die Daten der einzelnen Felder:</i><br>  
<table rules="rows">  
      <tr>  
     <th>Name:</th>  
     <td >*Name*</td>  
     </tr>  
     <tr>  
     <th>eMail:</th>  
     <td><a href="mailto:*eMail*">*eMail*</a></td>  
     </tr>  
      <tr>  
     <th>Nachricht:</th>  
     <td>*Nachricht*</td>  
     </tr>  
</table>  
 </p>  
 <p><br>Mit freundlichen Grüßen<br><i>Der Formmailer</i></p>  
</body>  
</html>  
';  
  
// für HTML-E-Mails muss der 'Content-type'-Header gesetzt werden  
$header  = 'MIME-Version: 1.0' . "\r\n";  
$header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";  
  
// zusätzliche Header  
$header .= 'To: Max Mustermann <mail@example.org>' . "\r\n";  
$header .= 'From: Formmailer <noreply@meinedomain.de>' . "\r\n";  
$header .= 'Cc: kollege@kollege.de' . "\r\n";  
  
// Standard-Klauseln aus dem eMail-Template durch geprüfte Nachrichtenelemente ersetzten  
$ende = str_replace("*eMail*", $_GET['eMail'], $nachricht);  
$ende = str_replace("*Name*", $_GET['Name'], $ende);  
$ende = str_replace("*Name*",nl2br( $_GET['Nachricht']), $ende);  
$ende = str_replace("*IP*", $_SERVER["REMOTE_ADDR"], $ende);  
$ende = str_replace("*Datum*", date("j.m.Y"), $ende);  
$ende = str_replace("*Zeit*", date("H:i"), $ende);  
  
// E-Mail senden  
mail($empfaenger, $betreff,$ende, $header);  
  
// In Sperr-Datei eintragen  
// Datei öffnen,  
// wenn nicht vorhanden dann wird die Datei erstellt  
$handler = fOpen($dateiname , "a+");  
// Dateiinhalt in die Datei schreiben  
fWrite($handler , $eintragung);  
fClose($handler); // Datei schließen  
// '''''''''''''''''''''''''''''''''''''''''''''''  
// Ende eMail-Script  
  
} else {  
  // Heute schon verschickt  
  echo "HACK!";  
}  
  
Header("Location: http://meinedomain.de/danke.html");  
?>

Meine Frage: Funktioniert das so und ist das Skript auch "hacksicher"?

Viele Grüße
Peter

  1. Nur mal ein paar Gedanken beim durchschauen, zur Funktion an sich halte ich mich nicht für genügend php-sicher.

    Du filterst Zeilenumbrüche aus dem Messagetext? (Im Namen ok, aber nötig sein sollte es ja nicht)
    Würd ich mir überlegen. Gerade bei längeren Texten wär ich froh wenn die sinnvoll formatiert sind.

    $emailroh = str_replace("or", "-oder-;", $emailroh);

    ???
    Thorsten heißt dann Th-oder-sten? Was soll das denn?

    // Sperre: Jede IP kann nur 1 Mail pro Tag senden

    Man kann nur DIR eine Mail schicken. Ich glaub nicht dass das Formular für Spam verwendet wird. Falls doch, kannst du diese Sperre dann einbauen wenn sie wirklich nötig ist. Du sperrst dir damit viel wahrscheinlicher nur sinnvolle Hinweise aus, die dir jemand schickt.

    echo "HACK!";

    Wenn ich dich auf irgendwas aufmerksam machen möchte das dir was bringt und mir kein bisschen, lass ich es spätestens dann bleiben ;-)

    Ob du die Nachricht wirklich als HTML schicken willst musst du selbst entscheiden, je nachdem welchen Mailclient du verwendetst.

  2. [latex]Mae  govannen![/latex]

    <?php

    // Erfassung der übermittelten Variablen in "Rohvatiablen"
    $emailroh = $_GET['eMail'];
    $nameroh =  $_GET['Name'];
    $nachrichtroh = $_GET['Nachricht'];

    Hier kopierst du die Werte aus $_GET in Variablen, um bestimmte Zeichen zu ersetzen ...

    // Standard-Klauseln aus dem eMail-Template durch geprüfte Nachrichtenelemente ersetzten
    $ende = str_replace("eMail", $_GET['eMail'], $nachricht);
    $ende = str_replace("Name", $_GET['Name'], $ende);
    $ende = str_replace("Name",nl2br( $_GET['Nachricht']), $ende);

    benutzt aber hier die ursprünglichen unsicheren Werte aus $_GET. Die Variablen mit den ersetzten Werten hingegen werden nie wieder benutzt.

    // "Verbotene" Zeichen werden manuell(!) ausgefiltert
    $emailroh = str_replace("<", "&lt;", $emailroh);
    $emailroh = str_replace("\n", "", $emailroh);
    $emailroh = str_replace("\r", "", $emailroh);
    $emailroh = str_replace(">", "&gt;", $emailroh);
    $emailroh = str_replace(chr(34), "&quot;", $emailroh);
    $emailroh = str_replace("or", "-oder-;", $emailroh);
    $emailroh = str_replace(chr(39), "&quot;", $emailroh);
    $nameroh = str_replace("<", "&lt;", $nameroh);
    $nameroh = str_replace("\n", "", $nameroh);
    $nameroh = str_replace("\r", "", $nameroh);
    $nameroh = str_replace(">", "&gt;", $nameroh);
    $nameroh = str_replace(chr(34), "&quot;", $nameroh);
    $nameroh = str_replace("or", "-oder-;", $nameroh);
    $nameroh = str_replace(chr(39), "&quot;", $nameroh);
    $nachrichtroh = str_replace("<", "&lt;", $nachrichtroh);
    $nachrichtroh = str_replace(">", "&gt;", $nachrichtroh);
    $nachrichtroh = str_replace(chr(34), "&quot;", $nachrichtroh);
    $nachrichtroh = str_replace("or", "-oder-;", $nachrichtroh);
    $nachrichtroh = str_replace(chr(39), "&quot;", $nachrichtroh);
    $nachrichtroh = str_replace("\n", "", $nachrichtroh);
    $nachrichtroh = str_replace("\r", "", $nachrichtroh);

    [code lang=php]str_replace()

      
    
    > // Nachrichtentemplate definieren  
    > $nachricht = '  
    > <html>  
    > <head>  
      
    [...]  
      
    
    > </html>  
    > ';  
      
    Heredoc macht die Sache übersichtlicher.  
      
      
    
    > // E-Mail senden  
    > mail($empfaenger, $betreff,$ende, $header);  
      
    Keine Überprüfung, ob mail() erfolgreich war?  
      
      
    
    > Meine Frage: Funktioniert das so und ist das Skript auch "hacksicher"?  
      
    Nö, ist es nicht (siehe erster Teil).  
      
      
    Cü,  
      
    Kai
    
    -- 
    ~~~ ken SENT ME ~~~  
    Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken  
    in Richtung "Mess up the Web".([suit](https://forum.selfhtml.org/?t=197497&m=1324775))  
    [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
    
  3. Hallo zusammen,
    vielen Dank für die tollen Tipps. Das mit dem Ersetzten der Platzhalter war wirklich blöd von mir... *schäm*.
    Aber ich habe den Code geändert und unten wieder angehängt. Ist er in dieser Form nun sicher?

    Vielen Dank schon mal im Voraus!
    Der Peter

    ===CODE===

    <?php  
    // Erfassung der übermittelten Variablen in "Rohvatiablen"  
    $emailroh = $_GET['eMail'];  
    $nameroh =  $_GET['Name'];  
    $nachrichtroh = $_GET['Nachricht'];  
      
    // "Verbotene" Zeichen  
    $verboten = array("<", ">","\n", "\r",chr(34), chr(39));  
    $neuezeichen = array("&lt;", "&gt;", "", "", "&quot;", "&quot;");  
    $verbotentext = array("<", ">", chr(34), chr(39));  
    $neuezeichentext = arry("&lt;", "&gt;", "&quot;", "&quot;");  
    $email = str_replace($verboten, $neuezeichen, $emailroh);  
    $name = str_replace($verboten, $neuezeichen, $nameroh);  
    $inhalt = str_replace($verbotentext, $neuezeichentext, $nachrichtroh);  
      
    // Empfänger definieren  
    $empfaenger  = 'mail@example.org';  
      
    // Betreff definiert  
    $betreff = 'Ein Besucher hat das Kontaktformular auf der Webseite ausgefüllt';  
      
    // Nachrichtentemplate definieren  
    $nachricht = <<<EOT  
    <html>  
    <head>  
    <title>Ein Besucher hat das Kontaktformular ausgefüllt</title>  
    <style type="text/css">  
    td { padding: 5px; border-style: solid; border-color: black; width: 250px; }  
    th { padding: 5px; border-style: none; text-align: left; }  
    table { border-style:none; }  
    </style>  
    </head>  
    <body>  
    <p>Sehr geehrter Admin,<br>&nbsp;<br>die folgende Nachricht wurde am *Datum* um *Zeit* mit dem Kontaktformular verfasst. Der Verfasser hat folgende IP:&nbsp;<b>*IP*</b></p>  
    <p><i>Die Daten der einzelnen Felder:</i><br>  
    <table rules="rows">  
    <tr>  
    <th>Name:</th>  
    <td >*Name*</td>  
    </tr>  
    <tr>  
    <th>eMail:</th>  
    <td><a href="mailto:*eMail*">*eMail*</a></td>  
    </tr>  
    <tr>  
    <th>Nachricht:</th>  
    <td>*Nachricht*</td>  
    </tr>  
    </table>  
    </p>  
    <p><br>Mit freundlichen Grüßen<br><i>Der Formmailer</i></p>  
    </body>  
    </html>  
    EOT;  
      
    // für HTML-E-Mails muss der 'Content-type'-Header gesetzt werden  
    $header  = 'MIME-Version: 1.0' . "\r\n";  
    $header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";  
      
    // zusätzliche Header  
    $header .= 'To: Max Mustermann <mail@example.org>' . "\r\n";  
    $header .= 'From: Formmailer <noreply@meine-domain.de>' . "\r\n";  
    $header .= 'Cc: kollege@kollege.de' . "\r\n";  
      
    // Standard-Klauseln aus dem eMail-Template durch geprüfte Nachrichtenelemente ersetzten  
    $ende = str_replace("*eMail*", $email, $nachricht);  
    $ende = str_replace("*Name*", $name, $ende);  
    $ende = str_replace("*Nachricht*", $inhalt, $ende);  
    $ende = str_replace("*IP*", $_SERVER["REMOTE_ADDR"], $ende);  
    $ende = str_replace("*Datum*", date("j.m.Y"), $ende);  
    $ende = str_replace("*Zeit*", date("H:i"), $ende);  
      
    // E-Mail senden  
    $erfolg = mail($empfaenger, $betreff, $ende, $header);  
      
    // Wenn es einen Fehler gibt, wird eine Fehlermeldung angezeigt  
    if($erfolg == TRUE)  
    { Header("Location: http://meine-domain.de/danke.html"); }  
    else  
    {  echo "Fehler beim Versenden der eMail"; }  
    ?>
    
    1. hi,

      Aber ich habe den Code geändert und unten wieder angehängt. Ist er in dieser Form nun sicher?

      Definiere mal "sicher", was soll denn bei Deinem Formmailer "sicher" sein? Dass er technisch funktioniert, oder dass er nicht zum SPAM missbraucht werden kann?

      Letzteres kannst Du ganz einfach verhindern, indem keine Benutzereingaben in die Mail-header gelangen. Das betrifft dann zwar auch den From-Header, aber der Absender hat ja immer noch die Möglichkeit, seine eMail-Adresse in den body zu schreiben, falls er eine Antwort wünscht, wird er dies auch machen.

      Hotti