Captcha Alternative: effektiver JavaScript SpamFilter

 

Ich wollte einen BesucherzĂ€hler fĂŒr mein CMS schreiben und hab dabei relativ schnell bemerkt, dass der Großteil der Besucher keine wirklichen Besucher, sondern automatische Abfragen von Servern, sind. Das selbe Problem hatte ich seit jeher mit Formularen, diese wurden regelrecht zugespamt. 

Wie kann man effektiv einen Bot von einem richtigen Besucher unterscheiden?

Captcha

Eine sehr gĂ€ngige Variante sind Captcha, kleine Bilder bei denen Benutzer Zahlen oder Buchstabenkombinationen beantworten mĂŒssen. Aufgrund der KomplexitĂ€t der Bilder sind diese des öfteren nicht so leicht zu beantworten. Teilweise gibt es auch Varianten in denen eine Rechnung oder einfache Frage steht, Benutzer können diese meist leichter beantworten als ein Bot.

Das System funktioniert bei Formularen auf Kosten der Benutzerfreundlichkeit, nicht aber bei einem BesucherzÀhler. Wenn ich bei einem BesucherzÀhler echte Benutzer erkennen will, kann ich dem Leser kein Captcha zumuten um gezÀhlt zu werden.

Aus Benutzersicht wĂŒrde ich behaupten: Captcha nerven.

Was macht ein Browser, was ein Bot nicht kann?

Wie sieht das mit JavaScript aus: wieviel Javascript kann ein Bot?

Die Idee: Wenn Teile der Seite dynamisch mit Javascript generiert werden, beispielsweise der Aufruf des BesucherzĂ€hlers, könnten die Bots doch außen vor gelassen werden, oder?

das wollte ich testen:

 

Der Versuchsaufbau

jQuery lÀdt mittels ajax (also erst nachdem die Seite geladen wurde) dynamisch den BesucherzÀhler nach:

Jeder moderne Browser kann das, und da Bots meist nur statischen Inhalt abrufen können, kommen wir mit diesem Ansatz schon sehr weit.

 

Folgendes jQuery Script soll den BesucherzÀhler aufrufen:

$( document ).ready(function() {
$.ajax({url:'counter.php'});
});

(hier nur in vereinfachter Form dargestellt: natĂŒrlich könnte counter.php direkt aufgerufen werden und den Besucher dann zĂ€hlen, mit etwas zusĂ€tzlichem Code kann das leicht verhindert werden. Außerdem verlieren wir einige Informationen ĂŒber den Benutzer, z.B. den HTTP-Referrer. Auch hier benötigen wir noch zusĂ€tzlichen Code. Um das Beispiel einfach zu halten, lasse ich diesen zusĂ€tzlichen Code jetzt mal absichtlich weg.)

 

Ein Bot mĂŒsste als jQuery interpretieren können um die Datei zu laden.

Ich hab den Code auf meinen Seiten getestet und konnte mit dieser Variante alle Bots richtig einordnen, mit Außname des Googlebot: dieser hat unser Skript dennoch interpretiert und taucht in dem generierten Logfile auf:

Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

Mozilla/5.0 (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)

Googlebot kann also ein wenig JavaScript und folgt dem AJAX-Aufruf welcher mittels $( document ).ready(function()  beim laden der Seite aufgerufen wird. Auch wenn Googlebot das Skript richtig ausfĂŒhrt, gibt es dennoch Aktionen, die einem wirklichen Benutzer vorbehalten sind:

kann ein Bot die Maus bewegen?

Ich wĂŒrde mal behaupten, ein Bot hat gar keine Maus, diesen Nachteil können wir nĂŒtzen.

Ein Benutzer streicht doch bestimmt kurz mit der Maus ĂŒber den Bildschirm, wenn die Seite geladen wurde. GerĂ€te ohne Maus haben ein Touchdisplay, welches beim Laden unweigerlich berĂŒhrt wird.

Mit dem Evenhandler mousemove und touchmove liefert ein BesucherzÀhler wirklich gute Ergebnisse:

$( "body" ).one("mousemove touchmove",function()  {
$.ajax({url:'counter.php'});
});

auch Googlebot wird mit dieser Variante richtig erkannt. 

 

FĂŒr

Formulare

haben wir noch mehr Möglichkeiten, da der Benutzer das Formular ja ausfĂŒllen muss, hier kann beispielsweise das Event focus() verwendet werden.

 

Die Idee:

Ein Event befĂŒllt mittels jquery und einem Ajax Request ein verstecktes Formularfeld, der Server muss nach dem Post-Event ĂŒberprĂŒfen ob das Formularfeld den richtigen Wert enthĂ€lt. Die Berechnung des Wertes muss natĂŒrlich beim Ajax Request und dem eigentlichen speichern des Formulares, das selbe Ergebnis liefern. FĂŒr die Berechnung kann beispielsweise ein Hash einer Kombination aus Uhrzeit und Clientinformationen, wie der IP Adresse oder Ă€hnliches, gewĂ€hlt werden.

Diese Variante macht Captcha oder Ă€hnliche AnsĂ€tze völlig ĂŒberflĂŒssig.

 

Das Prinzip hab ich in dem Content Management System LiBe CMS umgesetzt und erfolgreich getestet, sowohl fĂŒr den BesucherzĂ€hler, als auch fĂŒr Formulare; siehe:BesucherzĂ€hler

positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE fĂŒr deine Bewertung!

Fragen / Kommentare


(sortiert nach Bewertung / Datum) [alle Kommentare(neueste zuerst)]

✍anonym
14.07.2020 14:53
Sehr cooler Ansatz. ABER:
„Ein Benutzer streicht doch bestimmt kurz mit der Maus ĂŒber den Bildschirm, wenn die Seite geladen wurde. GerĂ€te ohne Maus haben ein Touchdisplay, welches beim Laden unweigerlich berĂŒhrt wird.“
Diese Annahme ist falsch. User mit Sehbehinderung oder auch User mit Körperbehinderungen, z.B. mit Tremor der HÀnde, nutzen weder Maus noch Touchscreen. Sie nutzen Tastaturen oder EingabegerÀte, die Tastatureingaben simulieren.
Möglicherweise gibt es noch andere Nutzergruppen, auf die die Annahme nicht zutrifft.

✍anonym
13.10.2015 12:27
User: Michael 
Mensch, da ĂŒberlegt man die ganze Zeit und entschließt sich, die Frage zu posten, weil man nicht weiter kommt... und 2 Minuten spĂ€ter fĂ€llt einem die Lösung ein :-)

FĂŒr alle, die dasselbe Problem haben: Ich lese einfach den Titel der Seite in der Hauptseite aus uns speichere ihn in eine Variable. Diese ĂŒbergebe ich dann an die analyse.php, indem ich diese folgendermaßen einbinde:

 $.ajax({url:'analyse.php?titel='});

In der Analyse.php lese ich den Wert mit GET aus und kann diesen dann in die Datenbank schreiben. So funktioniert es!

✍anonym
13.10.2015 12:17
User: Michael 
Moin, moin! Ich habe mir selbst ein Skript gebastelt, um mir live anschauen zu können, wieviele User gerade auf meinen Seiten sind. Und aufgrund der vielen Bots wichen die Zahlen von den Live-Stats von zB Google Analytics sehr weit ab. Dank Deines Beitrags kann ich nun realistischere Zahlen ausgeben. Denn ich laden die analyse.php-Datei einfach per Javascript nach.

Das Problem was ich nun habe: Ich kann jetzt nicht mehr auslesen, welche Seite der Besucher gerade anschaut. Entweder ist die Angabe leer oder aber es wird der Name der analyse.php ausgegeben; ich schaffe es aber nicht, den Namen der Datei ausgeben zu lassen, die vom User aufgerufen wird und innerhalb der dann die analyse.php nachgeladen wird. Gibt es hierfĂŒr eine Lösung?

GrĂŒĂŸe!

✍anonym
07.07.2015 17:19
User: udo 
geniale Sache!