paul: hilfe! mailform von robots erfasst :-(

hallo experten,

seit einiger zeit werde ich mit spammails, großteils ohne irgend einem sinnvollen inhalt, bombardiert, oft über 100 am tag.

meine frage wäre nun, ob ich in meinem mailformular bzw. der dazupassenden mail.php-datei einen fehler gemacht hab. kann ich mich gegen diese angriffe überhaupt wehren? und wenn, wie?

vielen dank für eure hilfe!

hier die mail.php, an die die form-daten weitergegeben werden:

<?php

if (isset($_POST)) {

foreach($_POST as $key=>$element) {
          ${"form_$key"} = $element;
   }
ini_set("SMTP","mail.mailserver.de");
ini_set("paul@mail.de");
   @mail("paul@mail.de", $form_betreff, $form_nachricht ,"from: $form_email");
   @mail($form_email, "Nachricht erhalten!", "Liebe(r) Freund(in) von Paul!

Wir haben Ihre Nachricht erhalten und werden uns in Kürze mit Ihnen in Verbindung setzen!
);

header("location: http://www.paulsdomain.de/erfolgContact.shtml");
}
else {
header("location: http://www.paulsdomain.de/sorry.shtml");
}
?>

  1. Anscheinend haben Bots jetzt auch gelernt, wie man sich in einen Formmailer einträgt...erst Gästebuch, jetzt das...
    Die einzige Möglichkeit wäre, so eine Art Zahlencode-Prüfung einzubauen...

    1. Lieber Florian,

      Die einzige Möglichkeit wäre, so eine Art Zahlencode-Prüfung einzubauen...

      ... oder das abzusendende Formular _nicht_ abzusenden, sondern erst zur Überprüfung nocheinmal (mit "Vorschaufunktion") ausgeben, um es dann endgültig abzuschicken. Das checken die meisten Bots nicht, da sie das Folgeformular nie zu Gesicht bekommen (und daher auch nicht abschicken können).

      Wenn Du das ursprüngliche Formular nie direkt abschickst, sondern erst die Eingaben bestätigen lässt, dann brauchst Du auch keinen wie auch immer gearteten Bild-abschreiben-Mechanismus, egal ob in Gästebuch oder Formmailer!

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

  2. Hallo

    <?php

    if (isset($_POST)) {

    foreach($_POST as $key=>$element) {
              ${"form_$key"} = $element;
       }

    Du überprüfst keinen der übergebenen Werte auf Plausibilität und Gültigkeit? Tätest du es, dürfte dir (zumindest) ein Großteil des Spams erspart bleiben.

    Formularfelder, die nur Ziffern enthalten dürfen, kannst du genau darauf prüfen. Formularelemente, aus denen heraus per Auswahl Text übergeben wird (z.B. <select ...><option value="text">Bla</option></select>) kannst du mit einem Array vergleichen, welches alle dort möglichen Werte enthält (Mit diesem könntest du die Auswahl auch zusammenbauen.). Text, von dem du nicht weißt, wie er aussehen wird, solltest du mindestens mit strip_tags() und htmlentities() entschärfen. Wird er in eine MySQL-DB eingetragen, muss er mit mysql_real_escape_string() behandelt werden, damit keine fremde MySQL-Anweisung  in der DB landet.

    Dies ist nur ein sehr kleiner Exkurs in die Erfordernisse und Möglichkeiten der Formularprüfung. Aber mit einigen Stichworten wirst du auch erfolgreich an anderen Stellen suchen können.

    Tschö, Auge

    --
    Die Musik drückt aus, was nicht gesagt werden kann und worüber es unmöglich ist zu schweigen.
    (Victor Hugo)
    Veranstaltungsdatenbank Vdb 0.1
    1. danke für den tipp, aber das, was du hier ansprichst, macht wohl eher für formulareinträge in eine datenbank sinn. bei mir geht es ja nur nur um das versenden von emails, und ich weiss nicht, ob da eine derartige überprüfung viel sinn macht. das überprüfen von html oder sql-abfragen könnte ich zwar vornehmen, ist aber nicht mein vorrangiges problem. ich möchte auch keine mails wegfiltern, wo jemand eine falsche emailadresse angegeben hat (es könnte ja trotzdem eine gültige nachrticht dabei sein).

      wenn du aber tipps hast, was ich wegfiltern könnte, wäre ich dir dankbar (da es sich um ein "freies" textfeld handelt, das sowohl zahlen als auch buchstaben enthalten darf, sehe ich da jedoch wenig möglichkeiten...

      1. Hi paul,

        wenn du aber tipps hast, was ich wegfiltern könnte, wäre ich dir dankbar

        Vielleicht gibt's hier Tipps für Dich:
        http://aktuell.de.selfhtml.org/tippstricks/php/formularvalidierung/index.htm

        Viele Grüße
        Mathias Bigge

  3. echo $begrüßung;

    @mail("paul@mail.de", $form_betreff, $form_nachricht ,"from: $form_email");

    Prüfst du, ob nur das in $form_email und $form_betreff steht, was du erwartest? Statt "hugo@example.com" kann auch jemand "hugo@example.com\r\nbcc: egon@example.org" usw. mitsenden. Dann bekommst nicht nur du den Spam ...

    echo "$verabschiedung $name";

    1. Hallo dedlfix.

      Statt "hugo@example.com" kann auch jemand "hugo@example.com\r\nbcc: egon@example.org" usw. mitsenden.

      Dazu zwei Fragen:

      Wie kann ich diese beiden Zeichen (CR und LF) per Tastatur eingeben oder woher kann ich sie zum einfügen kopieren?

      Genügt es, die zusätzlichen Mailheader (vierter Parameter von mail()) mit "\r\n\r\n" zu terminieren, um das Anfügen weiterer zu unterbinden?

      Einen schönen Dienstag noch.

      Gruß, Ashura

      --
      sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
      mathbr:del.icio.us/ mathbr:w00t/
      1. Hallo.

        Wie kann ich diese beiden Zeichen (CR und LF) per Tastatur eingeben oder woher kann ich sie zum einfügen kopieren?

        (Meine unpräzise Frage war auf input-Elemente bezogen.)

        Jedenfalls habe ich eine Behelfslösung gefunden, in dem ich die Zeichen per JS einfügen lasse.

        Einen schönen Mittwoch noch.

        Gruß, Ashura

        --
        sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
        mathbr:del.icio.us/ mathbr:w00t/
      2. echo $begrüßung;

        Statt "hugo@example.com" kann auch jemand "hugo@example.com\r\nbcc: egon@example.org" usw. mitsenden.

        Wie kann ich diese beiden Zeichen (CR und LF) per Tastatur eingeben oder woher kann ich sie zum einfügen kopieren?

        Das ist weniger relevant. Der Formular-Missbraucher wird sich sicherlich nicht die Mühe machen, das Formular im Browser per Hand auszufüllen. Man kann die Daten, die per POST übertragen werden sollen, ja auch anderweitig erzeugen.

        Genügt es, die zusätzlichen Mailheader (vierter Parameter von mail()) mit "\r\n\r\n" zu terminieren, um das Anfügen weiterer zu unterbinden?

        Bestimmt nicht. Es gibt da auch noch das Subjekt (zweiter Parameter von mail()), das ebenfalls im Header landet. Wenn du dafür auf die dort einzufügenden Daten eine CR/LF-Entfernungsfunktion anwendest, kannst du die auch gleich noch für den vierten Parameter verwenden.

        Wo dachtest du denn, willst du das \r\n\r\n anfügen? An die vom Nutzer gesendeten Daten? :-)

        echo "$verabschiedung $name";

        1. Hallo dedlfix.

          Genügt es, die zusätzlichen Mailheader (vierter Parameter von mail()) mit "\r\n\r\n" zu terminieren, um das Anfügen weiterer zu unterbinden?

          Bestimmt nicht. Es gibt da auch noch das Subjekt (zweiter Parameter von mail()), das ebenfalls im Header landet.

          Dieses wird bereits auf "\r\n" (und sicherheitshalber auch auf "\n") untersucht. Diese beiden Suchmuster haben in den betreffenden Formularfeldern nichts zu suchen und erzeugen eine Fehlermeldung.

          Wenn du dafür auf die dort einzufügenden Daten eine CR/LF-Entfernungsfunktion anwendest, kannst du die auch gleich noch für den vierten Parameter verwenden.

          Alles, was im vierten Parameter landet, wurde bereits vorher auf obige Zeichenketten hin überprüft.

          Wo dachtest du denn, willst du das \r\n\r\n anfügen? An die vom Nutzer gesendeten Daten? :-)

          Nein, am Ende des Mailheaders. Oder wie sollte ich diesen Kommentar deuten?

          Und kann man irgendwie den dritten Parameter vorzeitig beenden, um zusätzliche Mailheader einzuschmuggeln? (Daher überhaupt meine Frage bzgl. "\r\n".)

          Einen schönen Mittwoch noch.

          Gruß, Ashura

          --
          sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
          mathbr:del.icio.us/ mathbr:w00t/
          1. echo $begrüßung;

            Wo dachtest du denn, willst du das \r\n\r\n anfügen? An die vom Nutzer gesendeten Daten? :-)

            Nein, am Ende des Mailheaders. Oder wie sollte ich diesen Kommentar deuten?

            Beispielsweise als nicht richtig. Wenn mail() nicht von selbst die Header mit einer Leerzeile abschließen würde, wäre es fehlerhaft.

            Ich habe mal etwas im Quelltext von mail.c gelesen. Die entscheidenden Zeilen sind (zu finden im letzten Viertel):

              fprintf(sendmail, "To: %s\n", to);  
              fprintf(sendmail, "Subject: %s\n", subject);  
              if (headers != NULL) {  
                fprintf(sendmail, "%s\n", headers);  
              }  
              fprintf(sendmail, "\n%s\n", message);
            

            Hier siehst du, wie die Parameter zusammengesetzt und an sendmail gegeben werden. Du erkennst sicherlich auch, dass message (dritter Parameter) ein Extra-\n bekommt und dass to (erster), subject (zweiter) und headers (vierter parameter) alle zum Header gehören. Ebenso sicherlich die Sinnlosigkeit des Userkommentars.

            Und kann man irgendwie den dritten Parameter vorzeitig beenden, um zusätzliche Mailheader einzuschmuggeln? (Daher überhaupt meine Frage bzgl. "\r\n".)

            Sollte sich nun geklärt haben, oder?

            Die Reihenfolge der Parameter von mail() sind dem Anwender angepasst. To, Subject und Message brauchts immer. Headers kann weggelassen werden, deswegen steht es hintendran.

            echo "$verabschiedung $name";

            1. Hallo dedlfix.

              Beispielsweise als nicht richtig. Wenn mail() nicht von selbst die Header mit einer Leerzeile abschließen würde, wäre es fehlerhaft.

              Hm, wie kommt es dann zu Header-Injections?

              Du erkennst sicherlich auch, dass message (dritter Parameter) ein Extra-\n bekommt …

              Das erkenne ich zwar, aber nicht warum. Was bewirkt er?

              Einen schönen Mittwoch noch.

              Gruß, Ashura

              --
              sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
              mathbr:del.icio.us/ mathbr:w00t/
              1. echo $begrüßung;

                Beispielsweise als nicht richtig. Wenn mail() nicht von selbst die Header mit einer Leerzeile abschließen würde, wäre es fehlerhaft.

                Hm, wie kommt es dann zu Header-Injections?

                So wie bereits gesagt. Jemand sendet in einem Feld, das letzten Endes im Header landet (also To, Subject oder ein Extra-Header-Wert), statt eines umbruchlosen Strings einen mehrzeiligen und der Script-Autor prüft das nicht, weil er es einfach nicht erwartet hat: "Ist ja nur ein einzeiliges Eingabefeld".

                Du erkennst sicherlich auch, dass message (dritter Parameter) ein Extra-\n bekommt …

                Das erkenne ich zwar, aber nicht warum. Was bewirkt er?

                Er fügt die Leerzeile zwischen den Headern und Message ein.

                echo "$verabschiedung $name";

                1. Hallo dedlfix.

                  […] und der Script-Autor prüft das nicht, weil er es einfach nicht erwartet hat: "Ist ja nur ein einzeiliges Eingabefeld".

                  Gut, also habe ich zumindest dies doch richtig verstanden.

                  Du erkennst sicherlich auch, dass message (dritter Parameter) ein Extra-\n bekommt …

                  Das erkenne ich zwar, aber nicht warum. Was bewirkt er?

                  Er fügt die Leerzeile zwischen den Headern und Message ein.

                  Ah, ich glaube meinen Denkfehler gefunden zu haben: ich ging davon aus, dass du das zweite "\n" in "\n%s\n" meintest, was im Nachhinein betrachtet nicht wirklich Sinn ergäbe.

                  Danke für deine geduldige Erklärung!

                  Einen schönen Mittwoch noch.

                  Gruß, Ashura

                  --
                  sh:( fo:} ch:? rl:( br: n4:~ ie:{ mo:| va:) de:> zu:} fl:( ss:) ls:[ js:|
                  mathbr:del.icio.us/ mathbr:w00t/