NoFollow Free!
SHIFT Weblog

Dieses Blog ist ein Online-Magazin für erfahrene Website-Entwickler und Webdesigner, die PHP und Webdesign lieben.

Allgemein, PHP

Spam bekämpfen – aber richtig!

spam

Das Leben ohne Spam könnte so schön sein. Der Benutzer einer Webseite muss bei einer Registrierung keine Wörter in ein Textfeld eingeben, die vorher durch den Fleischwolf gedreht wurden. Ja, vielleicht würde sogar die Registrierung entfallen. Ein Webseitenbetreiber müsste nicht täglich neue Kommentare auf seinem Blog freischalten. Der Spam-Ordner im E-Mail-Postfach würde ohne die Spam-Mails, die u.a. eine Vergrößerung des eigenen Geschlechtsteiles anbieten, sicherlich arbeitslos werden.

Hätte, könnte, würde – Wir sind leider wieder in der Realität – und hier wartet sicher schon bald der nächste Spam-Eintrag auf uns. Seit mehr als 30 Jahren kämpfen wir nun gegen Spam – und ein Allheilmittel scheint es auch 2010 nicht zu geben.

Und so müssen wir uns einfach mit der Frage auseinandersetzen, wie man Spam eigentlich am besten bekämpft. Hier lautet das Motto: Kenne deinen Feind – daher lautet unsere erste Frage: Wie arbeitet ein Spam-Bot eigentlich?

Wie arbeitet ein Spam-Bot?

Spam-Bots (“Harvester”) durchforsten das Internet und sind auf der Suche nach Formularen. Ein Formular lässt sich in einem Quelltext leicht finden – benötigt man doch immer das form-Tag für das Vorhaben. Die Felder dieses Formulares werden dann mehr oder weniger mit entsprechendem Inhalt befüllt. Anhand der Bezeichnung (input name=”email”) kann der Bot oft erraten, wie er ein Feld zu befüllen hat. Verschiedene Alogrithmen helfen dem Bot, die Felder richtig auszufüllen – er hat ja schließlich unendlich viele Versuche. Viele Webseitenbetreiber erstellen nur eine oberflächliche Überprüfung Ihrer Formularfelder – so wird beispielsweise oft nur geprüft, ob Feld X mit mindestens drei Zeichen befüllt wurde. Der Bot hat also leichtes Spiel. Der Knopf mit dem Attribut type=”submit” ist schnell lokalisiert und wird aktiviert.

Bewährte Bekannte Hilfsmittel – und die Probleme

Schnell wird klar, dass man gegen die Botmassen keine Chance hat, wenn man sich nicht schützt.

Eine relativ primitive Methode zur Vermeidung von Spam ist eine Blacklist. Diese enthält Wörter, die (oft) nur von Spambots genutzt werden, von “normalen” Benutzern aber nicht. Wird ein Wort in einem Kommentar registriert, dass auch in der Blacklist auftaucht, wird es gesperrt. In einer solchen Blacklist könnte beispielsweise das Wort “enlargement” stehen – unser normale Besucher wird dieses Wort sicher nicht nutzen. Möchte uns nun ein freundlicher Spambot auf eine Geschlechtsteilvergrößerung hinweisen, wird er automatisch gesperrt. Doch Spambots sind nicht dumm – denn das Wort “enlargement” lässt sich auch anders schreiben: “Enl4rgem3nt” oder “Enlarge-ment” – schon rattert der Kommentar an unserer Blacklist vorbei.

Es gilt also, den Bot vom Menschen zu unterscheiden. Doch das ist gar nicht so einfach.

Hier sind wir beim “Captcha” angelangt: Eine Aufgabe, die es zu lösen gilt und (hoffentlich) nicht von Bots erkannt wird. Oft wird man bei der Registrierung gezwungen, eine Rechenaufgabe zu lösen: “Was ist 5+3 ?”. Abgesehen von einem Vorschulkind könnte wohl nahezu jeder diese Aufgabe lösen. Leider ist mit “Jeder” auch der Spambot gemeint – denn mit mathematischen Funktionen ist die Lösung einer simplen Addition ein leichtes. Der Bot erkennt die Zahlen und mathematischen Symbole – und merkt, dass hier nun gerechnet werden muss.

Man müsste also den Text irgendwie vor dem Bot verschleiern…

…wird sich der aufmerksame Leser nun denken. Und genau das passiert und galt für einige Zeit als wirkungsvolle Spam-Prävention. Der Text wird also nicht mehr hardcodiert auf der Seite präsentiert, sondern ist Teil eines Bildes. Ganze Programmbibliotheken haben sich gebildet und entwickelt, um aus einem Text schnell und einfach ein Bild zu machen. Doch wie wir alle wissen, bedienen sich die besseren Spambots auch der computergestützten Texterkennung (OCR). Damit lässt sich ein “5+3 ?” auf einer Grafik entschlüsseln, übersetzen und lösen.

Warum man auf Grafikcaptchas verzichten sollte

In der Hoffnung, Spambots endlich aussperren zu können, wurde das einzugebene Wort immer weiter verschleiert. Den Text, den man eingeben soll, wird so stark verzerrt, dass er (zumindest für den Menschen) nur noch schwer leserlich ist. Wie lauten beispielsweise die zwei Wörter für das Captcha rechts? “ahnemous lol”? “annemaus 101″? ” annomous 1Ol”? Hat man das Rätsel nicht gelöst, erhält der User eine Fehlermeldung. Er muss man die Aufgabe erneut bewältigen – und so langsam wird sicher auch der toleranteste Benutzer fragen, ob er das wirklich durchstehen muss.

Teilweise muss der Benutzer noch härtere Rätsel lösen. Und selbst wenn man durch derart drastische Maßnahmen einen Großteil der Spambots auslöscht – viele potenzielle Registrierungen durch “echte” Benutzer bleiben hier ganz sicher auf der Strecke. Die Benutzer, die sich dann doch durch die aufwendige Prüfung (“Bist du wirklich ein Mensch?”) gequält haben, werden die Erfahrung auf Ihrer Webseite sicherlich nicht zu den positivsten zählen. Wo bleibt da die Zugänglichkeit (oder sollte ich lieber sagen: “Usability”)?

Die Spambots mit eigenen Waffen geschlagen

Machen wir uns zur Bekämpfung von Spam also das Vorgehen der Bots zunutze. Ein Spambot füllt alle Felder aus – und das soll ihm jetzt zum Verhängnis werden.

Ein Formular sollte um ein weiteres Feld ergänzt werden – das nicht ausgefüllt werden darf! Um es dem menschlichen Besucher zu vereinfachen, werden wir dieses Feld mit Hilfe von CSS verstecken:

1
2
3
4
5
6
7
8
9
10
11
12
13
<form accept-charset="utf-8" method="post">
    <label for="n_ame">Ihr Name:</label>
<input id="n_ame" name="n_ame" type="text" />
 
    <label for="p_assword">Passwort</label>
<input id="p_assword" name="p_assword" type="text" />
<input id="s_end" name="s_end" type="submit" value="Los!" />
 
<div class="spam_protect">
        <label for="nospam">Dieses Feld bitte nicht ausfüllen! (Spamschutz)</label>
<input id="nospam" name="nospam" type="text" /></div>
 
</form>

Unser Stylesheet wird nun um eine Angabe ergänzt:

1
form .spam_protect { display: none; }

Ich habe hier bei der Vergabe der Namen für die Felder darauf geachtet, es den Bots nicht zu einfach zu machen – und habe die Feldnamen mit einem Unterstrich (_) versehen. Bei der Validierung des Formulares müssen wir jetzt nur prüfen, ob das Feld “nospam” ausgefüllt wurde – wenn ja, ist unser Spambot in die Falle getappt. In PHP könnte eine solche Prüfung so aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(isset($_POST['n_ame'])) {
    // Formular wurde abgeschickt
    if(!empty($_POST['nospam'])) {
        // Honeypot
        die("Dear Spambot, i don't need penis enlargement!");
    } else {
        /*
         * Das Feld "nospam" wurde nicht ausgefüllt, es ist daher
         * wahrscheinlich dass es sich um keinen Spambot handelt
         */
 
        // Weitere Validierung der restlichen Felder, Verarbeitung und ggf. Weiterleitung...
    }
}

Ein Spambot ignoriert die CSS-Zuweisungen, füllt alle Felder brav aus und landet somit in der “Honigfalle”. Dabei begrüssen wir Ihn mit einer freundlichen Nachricht. Der Mensch wird von unserer Maßnahme gegen Bots gar nichts mitbekommen – es sei denn, er benutzt einen Screenreader oder hat die Styles deaktiviert (unwahrscheinlich, aber möglich). In diesem Fall sollte aber die Label-Bezeichnung lesen und somit Bescheid wissen.

Immer einen Schritt vorraus

Eigentlich ist unser System schon sehr ausgefeilt – und dies mit extrem einfachen Mitteln. Ein Ausblenden des Honigtopf-DIVs wäre eine weitere Variante – jedoch denke ich, dass mehr Besucher JS ausgeschaltet haben als Besucher mit deaktiviertem CSS.

Ein Besucher muss nun keine komplizierten Captcha-Bilder entziffern, um seine Registrierung abzuschließen. Jedoch können wir noch eine Stufe weitergehen – für den Fall, dass Spambots irgendwann mal CSS-Regeln entziffern und auswerten können. Wir verwenden jetzt ein Captcha, dass die Besucher nicht stört und vielleicht sogar zum schmunzeln bringt.

Wir werden dem Besucher keine Rechenaufgabe stellen – denn diese Tricks haben Bots mittlerweile auf dem Kasten. Eine einfache Frage aus dem Alltag wird die Besucher erwarten, etwa “welche Farbe hat eine Banane?”. Selbst ein Vorschulkind könnte diese Frage mit Leichtigkeit meistern – ein Spambot nicht. Es ist unmöglich, dass der Ersteller solcher Bots diesem alle Antworten auf eventuelle Fragen eintrichert. Wir werden die Sicherheit noch etwas erhöhen, indem wir jedes mal eine andere Frage erscheinen lassen. Auch hier lässt sich das sehr einfach in PHP realisieren. Wir erweitern unser “Honeypot”-Beispiel von eben um diese Funktion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
 
session_start();
 
if(isset($_POST['s_end'])) {
	if(!empty($_POST['nospam'])) {
		exit(); // Honepot
	} else {
		if(isset($_SESSION['answer']) && $_SESSION['answer'] == strtolower($_POST['c_aptcha'])) {
			echo 'Die Spamschutz-Frage wurde richtig beantwortet.';
			unset($_SESSION['answer']);
			// Weitere Validierung, ggf. Weiterleitung
		} else {
			exit('Spamschutzfrage falsch beantwortet!');
		}
 
	}	
} else {
	$qa = array();
 
	$qa[] = array('Welche Farbe hat eine Banane?'		  => 'gelb');
    $qa[] = array('Können Menschen fliegen?'              => 'nein');
    $qa[] = array('Nach der Ebbe kommt die...?'           => 'flut');
    $qa[] = array('Schere gegen Papier - wer gewinnt?'    => 'schere');
 
    $rand = rand(0, (count($qa)-1)); // Eine zufällige Frage auswählen
    $quest = $qa[$rand];
 
    $captcha = key($quest); // Unsere Frage...
	$_SESSION['answer'] = $quest[$captcha]; // ..und die dazugehörige Antwort
}
 
 
 
 
 
 
 
?>
<form accept-charset="utf-8" method="post">
    <label for="n_ame">Ihr Name:</label>
<input id="n_ame" name="n_ame" type="text" />
 
    <label for="p_assword">Passwort</label>
<input id="p_assword" name="p_assword" type="text" />
 
    <label for="c_aptcha">Spamschutz-Frage: <?php echo $captcha; ?></label>
<input id="c_aptcha" name="c_aptcha" type="text" />
<input id="s_end" name="s_end" type="submit" value="Los!" />
 
<div class="spam_protect">
        <label for="nospam">Dieses Feld bitte nicht ausfüllen! (Spamschutz)</label>
<input id="nospam" name="nospam" type="text" /></div>
 
</form>

Nun haben wir einen sehr wirkungsvollen Spamschutz. Selbst wenn ein Bot in der Lage ist, zu erkennen dass er ein bestimmtes Formularfeld nicht ausfüllen darf, so wird er spätestens dann an der Sicherheitsfrage scheitern. Und so machen wir es auch ohne Akismet den Bots mächtig schwer.

Zusammenfassung

Captchas, bei denen der Benutzer erst mühsam eine Grafik entziffern muss, sind kein schönes Erlebnis für die Benutzer. Wirkungsvoller sind da einfache Fragen aus dem Alltag (können Spambots deutsch?) und ein Feld, das nicht ausgefüllt werden darf. Wie sind eure Erfahrungen im Bezug auf Spam? Habt ihr eine andere raffinierte Methode, um den Spambots das Leben schwer zu machen?

 

Kommentare

Auf dieses Thema gibt es 9 Reaktionen

  1. juno

    Ich finde es ein wenig übertrieben zu sagen, dass wir seit 30 Jahren gegen Spam kämpfen, auch wenn der erste Spamversuch dort auftrat. Ich denke, Spam ist erst ein Problem dass am Ende des 20. Jahrhunderts auftrat.

  2. ueber

    @Juno
    ich empfinde Werbung via Fax oder Telefon schon als Spam und das gibt es schon seit 30 Jahren.

    Ein Allheilmittel wird es sicher nie geben, wie auch? Man müsste den User eindeutig als Mensch erkennen.
    Und ich bin mir sicher ab den Zeitpunkt an dem wir das können, stellen die Spamer menschen ein die den Spam verteilen. Ähnlich den Chinafarmern.

  3. Andreas

    Vielen Dank für diesen hilfreichen Artikel zur SPAM-Bekämpfung. Hat mir sehr geholfen und die aufgezeigten Möglichkeiten zur Unterbindung von SPAM funktionieren einwandfrei.

    Viele Grüße,
    Andreas

  4. Lobi

    dank für die anleitung. hab das nun eingebaut :)

  5. Oliver I.

    Hallo,

    die Lösung klingt sehr interessant, aber für den Endnutzer ist es “nervig”, dass das er keine Chance hat die Frage neu zu beantworten wenn er sich doch ausversehen verschriebt bei Beantwortung der SPAM-Frage. Geht man nach der Meldung “Spamschutzfrage falsch beantwortet!” einen Schritt zurück oder gibt die Meldung mit einem echo aus, dann kann man zwar die Feldwerte des Formulars einfach wieder einsetzen, aber die SPAM-Frage erscheint nicht mehr. Wie kann man die Frage erneut aufrufen?

    Danke und Grüße

  6. Krishan

    Ich hab bei unserem GB den Spiess einfach umgedreht:

    Die captcha-Abfrage mit css versteckt – und bei Eingabe ( richtig oder falsch) wird der Eintrag abgewiesen.

    Die allermeisten Bots scheitern daran.

    Gruß Krishan

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

 

Weitere Artikel der Kategorie PHP

PHP

Template Inheritance oder: Ein Kreuz mit verschachtelten Templates

In den letzten Monaten hatte ich nur sehr wenig Zeit, mich um PHP und auch demzufolge um mein Framework zu kümmern. Ich habe jedoch sehr häufig über bestimmte Sachverhalte nachgedacht, und ein Thema, dass mir schlaflose Nächte bereitete, war das Verschachteln von Templates innerhalb eines MVC-Systems. Hierbei gibt es bei den etablierten Frameworks fast immer

Weiterlesen ›

PHP

Mein Verständnis von MVC

MVC – diese drei Buchstaben haben es in sich. MVC ist ein Design Pattern, eine strukturelle Lösung für Entwickler. Kaum ein anderes Design Pattern löst so viel Kontroverse aus und regt zu endlosen Diskussionen an – zumindest in der PHP-Welt. Das liegt daran, dass MVC recht oberflächlich beschrieben wird, und möchte man sämtliche MVC-Erklärungsversuche zusammenfassen,

Weiterlesen ›

PHP

Ausnahmezustand: PHP und Exceptions

Mit PHP 5 wurde dem Entwickler ein Werkzeug zur Verfügung gestellt, dass es in anderen objektorientierten Sprachen wie C++ und Python schon lange gibt: Exceptions. Mit diesen hat der Entwickler die Möglichkeit, auf ungewollte Ereignisse zu reagieren. Exceptions werden “geworfen”, das bedeutet, sie unterbrechen den normalen Programmfluss und behandeln eine eventuelle Ausnahme, die den weiteren

Weiterlesen ›