Ankündigung

Einklappen
Keine Ankündigung bisher.

Gästebuch -> Spam verhindern?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Gästebuch -> Spam verhindern?

    Hallo,

    ich habe erfolglos versuch mein Gästebuch mit einen kleinen Captcha-Script gegen Spambots zu sichern. Ich beschreibe mal, wie ich das gemacht habe, vielleicht ist ja ein gravierender Fehler drin.

    Ich habe eine Tabelle captcha mit 2 Spalten

    Code:
    ----------------------------------------
    input | hash
    ----------------------------------------
    12f5  | 43895743958792jewkfjsdhkfj
    1452  | sjlkj34kjff9dsfdfkfdjslfkjsd
    ...
    In die Tabelle habe ich 100 zufällig generierte Einträge gemacht. Einmal mit 4 Zeichen, das andere mal mit 32 Zeichen.

    Ich generiere nun über einen random-Hash im Formular ein Bild, in dem der zugehörige input dargestellt wird. Übergeben tu ich im Formular den Hash und das was der User in das Sicherheitscodefeld eingibt

    Vor dem Gästebucheintrag speichern überprüfe ich anhand des mitgeschickten Hashes ob das $_POST['sicherheitscode'] == $input ist.
    Wenn nicht, wird der GB-Eintrag nicht gemacht.

    Hier der Link zum Beispiel:
    http://www.ground-zeroo.de/guestbook...ion=new&page=0

    Also ich bekomme im Schnitt trotz der Codeabfrage ca 10 Spameinträge am Tag.

    Hat jemand eine Idee?
    Vielen Dank im Vorraus,
    Stephan

  • #2
    Halllo,
    eigentlich brauchst du das nicht über eine Datenbank lösen, du kannst den zufällig erzeugten String im Bild auch in der Session speichern und das Bild eben dynamisch generieren lassen.
    Es darf natürlich nichts auf die Lösung hinweisen, also auch nicht der Dateiname des Bildes.

    Ohne Script ist das jetzt schwer zu sagen und 10 Spam-Einträge könnten auch von einem Menschen kommen.
    Eventuell musst du dir überlegen, Gästebuch-Einträge erst freizugeben, wenn sie eine Administrator gelesen hat.

    Kommentar


    • #3
      Hier ist der Code für das dynamisch generierte Bild:

      PHP-Code:

      <?php

      include("db.inc.php");

      $sql "SELECT input FROM captcha WHERE hash='".$_GET['hash']."'";
      $result mysql_query($sql);


      $input mysql_result($result,0,0);

      mysql_close();


      header('Content-type: image/png');
      $img ImageCreateFromPNG('captcha.png'); //Backgroundimage
      $color ImageColorAllocate($img000); //Farbe
      $ttf "arial.ttf"//Schriftart
      $ttfsize 25//Schriftgrösse
      $angle rand(0,5);
      $t_x rand(5,50);
      $t_y 35;
      imagettftext($img$ttfsize$angle$t_x$t_y$color$ttf$input);
      imagepng($img);
      imagedestroy($img);


      ?>
      Und hier, wie ich die Abfrage beim versendeten Formular mache:

      PHP-Code:
      <?php

      include("db.inc.php");

      $sql "SELECT input FROM captcha WHERE hash='".$_POST['hash']."'";
      $result mysql_query($sql);

      $input mysql_result($result,0,0);

      mysql_close();

      if(
      $_POST['sicherheitscode'] != $input){
         
      $error 2;
      }


      if (
      $error == 0){
         
      # Gästebucheintrag machen
      }
      Ich hoffe das ist ausführlich genug

      Kommentar


      • #4
        nimm dir doch ein fertiges Captcha ??? o.O

        http://de.wikipedia.org/wiki/Captcha

        Wikipedia hat auch gute Beispiele parrat ...
        Captchas können auch LIVE erstellt und brauchen nicht via DB erzeugt werden.

        Ich meine 100 Einträge .. *hm* sind doch schnell mal zusammenkopiert

        Kommentar


        • #5
          Ich habe mir das eigentlich vom Backe gemacht, solche Sachen mit $_POST, GET oder REQUEST zu behandeln.

          Für Captcha benutze ich nur noch SESSION.
          Dort wird der Code erzeugt, und später wieder abgefragt.
          Also ohne jegliche Query zu einer DB.

          PS:
          http://www.ground-zeroo.de/guestbook_control.php
          Irgendwie das Resultat auf die oben genanten Dinge

          Kommentar


          • #6
            In deinem Beispiel benötigt ein Spammer lediglich eine gültige Kombination aus Hash und Eingabecode und kann so problemlos bei jedem Request diese beiden Werte mitschicken und dein Captcha umgehen.

            Kommentar


            • #7
              Hallo,

              erstmal vielen Dank für die Antworten! Das mit der DB ist ja eigentlich nur eine Nebensache. Daß 100 Einträge evtl zuwenig sein könnten, leuchtet mir ein.

              Mich würde interessieren, woher ein Spammer eine gültige Kombination aus Hash und Eingabecode bekommt? Das kann ich nicht nachvollziehen.

              CIX88, was meinst Du mit Deinem PS?

              M3g4Star, welches Captcha würdest Du empfehlen?


              Gruß,
              Stephan

              Kommentar


              • #8
                Naja man nimmt einmal eine gültigen Input und den Hash dazu! Und jedes mal wenn du nen Eintrag machen willst übergibst du halt diesen Input und Hash! Es wird ja nicht geprüft ob wirklich der Input und Hash von dem Formular genommen wird, es kann ja irgend eine Kombination genommen werden.

                Wenn dann musst du wirklich den Hash über ne Session übergeben ...

                Außerdem ist dein Script für SQL Injection anfällig!

                Kommentar


                • #9
                  Hallo Razor,

                  danke für die SQL Injeciton Info! Ich schau mir jetzt mal die Beispiele auf der Wikipediaseite an.

                  Steph

                  Kommentar


                  • #10
                    mysql_real_escape_string($_POST['hash']) sollte eigentilch reichen gegen die SQL Injection.

                    Mit dem Hash solltest du zum einen nicht mehr feste Werte nehmen die in der DB stehen sondern zufällig die dann über die Session weitergegeben werden, so brauchst du keine Datenbank und du kannst davon ausgehen das jedes mal ein neuer String gebildet wird.

                    Kommentar


                    • #11
                      Zitat von aktionkuba
                      Mich würde interessieren, woher ein Spammer eine gültige Kombination aus Hash und Eingabecode bekommt? Das kann ich nicht nachvollziehen.
                      Na er trägt selbst einen Spam-Eintrag ein, notiert sich input und hash und den Rest macht Brute-Force. Irgendwann wird die Kombination schon wieder geladen. Die Chance ist 1/100, lächerlich für ein Skript.

                      Aber wie gesagt, woher willst du wissen, ob der Eintrag maschinell eingetragen wurde?

                      Kommentar


                      • #12
                        wichtig und richtig ist die aussage von xabbuh
                        das system funktioniert nur mit session. sobald ich den hash per GET/POST mitsende kann dieser auch manipuliert werden. und dann reicht eine gültige kombi, die ich vorher manuell ausprobiert habe.
                        du gehst davon aus, daß dein hidden field 'hash' unveränderlich ist.

                        Kommentar


                        • #13
                          Das tolle an dem Script ist ja dass er nicht mal Brute-Force braucht! Der Skript überprüft nicht welches Bild angezeigt wurde! Du kannst also immer ein und den selben Hash übergeben und du hast immer einen Eintrag!

                          Kommentar


                          • #14
                            Juten morning alle!

                            Ich habe vor einiger Zeit auch das Problem gehabt, jo... und was dann rausgekommen ist, das will ich zeigen

                            Da ist eine einzige Datei (ich hab's mal ccode.php genannt), die man includen muss,
                            und darin sind 3 Funktionen enthalten,
                            nämlich create_ccode(), check_ccode() und gen_ccode_img():
                            http://gelamu.homelinux.net:88/8f50b...888763db0888d8
                            http://gelamu.homelinux.net:88/dc915...97c756c9fee273

                            Ich zeige lieber ein Beispiel, sonnst dauert das wenn ich anfange etwas zu erklären
                            Ordner mit Leserechten: ./fonts
                            und 1.ttf in ./fonts
                            Ordner mit Lese+Schreibrechten: ./tmp
                            test.php
                            PHP-Code:
                            <?php

                            require("./ccode.php");

                            if(isset(
                            $_POST['ccode']) && !check_ccode($_POST['ccode'], $_POST['chash']))
                                
                            $meldung "<h2>Bestaetigungs-Code ist falsch!</h2>
                            \n"
                            ;

                            $ccode create_ccode();




                            $SELF_DIR dirname($_SERVER['PHP_SELF']);

                            echo <<<EOT
                            <html>
                            <head><title>test</title></head>
                            <body>
                            <script type=text/javascript>
                                var ccode_img_counter = 1;
                                function refresh_ccode_img(obj) {
                                    obj.src = "http://
                            $_SERVER[HTTP_HOST]$SELF_DIR/ccode_img.php?hash=$ccode[hash]&"+(ccode_img_counter++)
                                }
                            </script>
                            <div align="center">
                            $meldung
                            <form action="test.php" method="post">
                                <input type="hidden" name="chash" value="
                            $ccode[hash]">

                                [img]ccode_img.php?hash=
                            $ccode[hash][/img]

                                <input name=ccode value="">

                                <input type=submit value=OK>
                            </form>
                            </div>
                            </body>
                            </html>
                            EOT;

                            ?>
                            ccode_img.php
                            PHP-Code:
                            <?php

                            require("./ccode.php");
                            gen_ccode_img($_GET['hash']);

                            ?>
                            ccode.php
                            PHP-Code:
                            <?php

                            // Hier werden die Dateien mit den Bestaetigungs-Codes abgelegt
                            define("CCODE_TMP_DIR""./tmp"true);

                            // Hier befinden sich die Schriften,
                            // moeglichst numerisch geordnet von 1 bis WEISS_DER_GEIER_WIEVIEL
                            define("CCODE_TTF_DIR""./fonts"true);

                            // Unser Keeks
                            define("CCODE_COONAME"md5(dirname($_SERVER['PHP_SELF']), true));

                            // Lebensdauer des Keekses (hier 30 min)
                            define("CCODE_COOEXPT"60*30);

                            // Ist einfach bequemer :)
                            define("CCODE_REMADDR"$_SERVER['REMOTE_ADDR'], true);




                            function 
                            create_ccode($len 6) {

                               
                            $CharList = array(
                                  
                            "3""4""6""7""9",
                                  
                            "A""C""D""E""F""G""H""J""K""L""M",
                                  
                            "N""P""Q""R""T""U""V""W""X""Y"
                               
                            );
                               
                            $NumChars sizeof($CharList)-1;

                               
                            $CCode "";
                               
                            $i 0;
                               while(
                            $i++ < $len)
                                  
                            $CCode .= $CharList[rand(0$NumChars)];



                               
                            $CharList = array(
                                  
                            "0""1""2""3""4""5""6""7""8""9",
                                  
                            "A""B""C""D""E""F""G""H""I""J""K""L""M",
                                  
                            "N""O""P""Q""R""S""T""U""V""W""X""Y""Z",
                                  
                            "a""b""c""d""e""f""g""h""i""j""k""l""m",
                                  
                            "n""o""p""q""r""s""t""u""v""w""x""y""z"
                               
                            );
                               
                            $NumChars count($CharList)-1;

                               
                            $CHash "";
                               
                            $i 0;
                               while(
                            $i++ < 16)
                                  
                            $CHash .= $CharList[rand(0$NumChars)];

                               @
                            unlink(CCODE_TMP_DIR."/".md5($_COOKIE[CCODE_COONAME].CCODE_REMADDR).".php");

                               
                            $CFile CCODE_TMP_DIR."/".md5($CHash.CCODE_REMADDR).".php";
                               if(@
                            file_put_contents($CFile'<?php $_'.$CCode.' ?>')) {
                                  @
                            setcookie(CCODE_COONAME$CHashtime()+CCODE_COOEXPT""""0);
                                  return 
                            $CHash;
                               }

                               return 
                            false;
                            }

                            function 
                            check_ccode($CCode$CHash) {

                               if(empty(
                            $CCode) || empty($CHash))
                                  return 
                            false;

                               
                            $CFile CCODE_TMP_DIR."/".md5($CHash.CCODE_REMADDR).".php";
                               if(
                            file_exists($CFile)) {

                                  
                            $TmpCCode = @substr(@file_get_contents($CFile), 8, -3);
                                  @
                            unlink($CFile);

                                  return 
                            $TmpCCode == $CCode true false;
                               }

                               return 
                            false;
                            }


                            function 
                            gen_ccode_img($CHash) {

                               
                            $ImgType     =   1// 1 => JPEG, 2 => GIF, alles andere (bzw. Standartauswahl) ist PNG
                               
                            $JpegQuality =  50// Nur fuer JPEG
                               
                            $FontSize    =  20;
                               
                            $ImgWidth    150;
                               
                            $ImgHeight   =  30;
                               
                            $FontId      =   1// Eine bestimmte Schrift waehlen
                               //$FontId      = rand(1, 10); // zufaellige Schriftauswahl (hier: zwischen 1, 10)

                               
                            if(empty($CHash))
                                  return 
                            false;

                               
                            $CFile CCODE_TMP_DIR."/".md5($CHash.CCODE_REMADDR).".php";
                               
                            $CCode = @substr(@file_get_contents($CFile), 8, -3);
                               if(empty(
                            $CCode))
                                  return 
                            false;

                               
                            $FgPlt = array(rand(0,255), rand(0,255), rand(0,255));
                               
                            $BgPlt = array(rand(0,255), rand(0,255), rand(0,255));

                               
                            $Img     imagecreatetruecolor($ImgWidth$ImgHeight);
                               
                            $FgColor imagecolorallocate($Img$FgPlt[0], $FgPlt[1], $FgPlt[2]);
                               
                            $BgColor imagecolorallocate($Img$BgPlt[0], $BgPlt[1], $BgPlt[2]);

                               
                            imagefilledrectangle($Img00$ImgWidth$ImgHeight$BgColor);
                               
                            imagettftext($Img$FontSize0525$FgColorCCODE_TTF_DIR."/".$FontId.".ttf"$CCode);

                               
                            // Gammakorrektur vornehmen
                               //ImageGammaCorrect($Img, 30, 20);

                               
                            if($ImgType == 1) {

                                  
                            header("Content-type: image/jpeg");
                                  
                            imagejpeg($Img""$JpegQuality);
                               
                               } else if(
                            $ImgType == 2) {

                                  
                            header("Content-type: image/gif");
                                  
                            imagegif($Img);

                               } else {

                                  
                            header("Content-type: image/png");
                                  
                            imagepng($Img);

                               }

                               
                            imagedestroy($Img);
                               return 
                            true;

                            }

                            ?>

                            Nimmt's mir net übel wenn ich keine $sString, $iInteger oder $aArray benutze.
                            Ich werd wohl früher oder später mein Programmierstil ändern müssen

                            EDIT: mit sessions wäre das alles bestimmt viel sicherer


                            Grüße,
                            GelaMu

                            Kommentar


                            • #15
                              http://forum.developers-guide.net/showthread.php?t=688

                              Hier ist eine schöne Seite zwecks Sicherheit etc. Solltest evtl. mal den einen oder anderen Punkt durchgehen.

                              Ich hoffe du hast xabbuh's post nicht überlesen. Denn wo er recht hat hat er recht ^^ (*lol* Hab die 2. Seite "überlesen" )
                              Sobald ich einen wert habe aus deiner DB kann ich den immer wieder verwenden was dir bei der zufälligen Erzeugung des Codes nicht passieren kann ... Captchas gibt es wie Sand am Meer

                              Wenn du nix gegen PEAR hast könntest ja wie empfohlen http://pear.php.net/package/Text_CAPTCHA das nehmen

                              Ansonsten klick dich durch die Beispiele bei Wikipedia.
                              z.B.: hier hast du eine ausführliche Beschreibung
                              http://www.deruwe.de/captcha.html

                              Kommentar

                              Lädt...
                              X