Zruck zum Blog, du Zniachtl
Mai 2018·4 Min. zum LesnVo da KI übersetzt

SPAM-Protection-Methoden Nr. 2: Timing is olles

#protection#spam

Im Rahmen vo da Reihe "SPAM protection methods" geht's weiter mit Teil 2 und dem ominösen Titel "Timing is olles". Dem liegt die Überlegung zu Grunde, dass Nutzer, wenn's a Webformular ausfülln, ned innerhoib vo a poar Sekunden sofort des gesamte Formular ausgfüllt hom. Geht ma von da allwissenden Wikipedia aus, betrogt die Anzoi an Tastaturanschlägen bei ana/am Fachkauffrau/-mann für Büromanagement etwa 230 Zeichen pro Minute. Bei mir woarn's in am Selbsttest 512 pro Minute (des kann ma do ganz einfach rausfinden). Gengan mia amoi von am Mittelwert aus und sogn, wer schneller ois 400 Zeichen pro Minute tippen kann, is höchstwahrscheinlich a Bot und füllt des Formular automatisch aus. Gengan mia's o.

1. De Mathematik (bäh)

Mia miassn also erstmoi rechnen, wia vül Anschläge ma pro Sekunde machn darf, wenn mia von 400 Zeichen pro Minute ausgehn, und rechnen 400 / 60 = 6,66666667 (also 7). Mehr ois 7 Anschläge pro Sekunde is also kritisch zu betrachten. Um den Durchschnitt zu kriagn (manchmoi tippt ma schneller, manchmoi langsamer) sogn mia weiterhin, dass jeder, der in 5 Sekunden mehr ois 35 (= 5x7) Anschläge mocht, a Bot sei kunnt. Des woar's mit Mathe. Easy.

2. Da Ablauf

Mia setzn a Interval, des olle 5 Sekunden den Anschlagszähler zruck setzt. Bei jedem "Keypress" wird da Zähler um 1 erhöht, und wenn mia die 35 überschreiten, treffn mia geeignete Maßnahmen gegn den Bot. Diese "geeigneten Maßnahmen" schaun so aus, dass mia an Post-Request an die captcha.php schickn (warum de so heißt, sehn mia weiter unten. Klans Tipperl: Sie enthoit a Captcha) und dort dann in da Session speichern, dass es si um an Bot handelt. Um's einfach zu hoitn, nutzn mia jQuery ois Hilfsmittel.

3. Le Javascript

var typecounter = 0;
setInterval(function(){
  typecounter = 0;
}, 5000);
$(document).keypress(function(){
  typecounter++;
  if (typecounter > 35){
    $.post("captcha.php", { action: 'block' }).done(function(data) {
      if (data == 'block') {
        location.reload();
      }
    });
  }
});

Olle 5 Sekunden wird do jetzt da typecounter auf 0 zruckgsetzt. Bei am Keypress wird er um 1 erhöht, und wenn er die 35 erreicht, lodn mia die Seitn neu und zeign a Fehlermeldung o.

4. Le PHP (captcha.php)

session_start();
$_SESSION['is_bot'] = true;
die('block');

De captcha.php mocht erstmoi nix ondres, ois die Sessionvariable 'is_bot' auf true zu setzn und die Meldung 'block' zruckzugebn.

5. Rausgholtn!

Damit da Bot jetzt nimma auf unsere Seitn kummt (und a sofort a Fehlermeldung angezeigt kriagt), miassn mia an den Anfang von jeder Datei, de gschützt wern soi, folgende zwoa Zeiln hängen:

session_start();
if (isset($_SESSION['is_bot']) && $_SESSION['is_bot'] === true) die("Kein Zugang für Bots");

Des mocht nix ondres, ois die Session zu starten und den Wert von da Session-Variable 'is_bot' zu prüfn, de mia ja unter Umständen in da captcha.php scho gsetzt hom. Wenn de 'true' enthoit, dann wird die Ausgabe beendet und die Meldung 'Kein Zugang für Bots' angezeigt.

6. Optimierungen

Optimaler wär's natürlich, mia tatn vorher scho a Captcha obfrogn. Vielleicht handelt's si ja doch um an Menschen, der einfach nur schnö tippt? Also - los geht's.

7. Captcha

Mia fügn unserer Datei no zwoa klane Divisions-Layer (aka DIVs) hinzu und schreibn an fancy Text eini. I hob amoi drauf valzichtet, die Styles auszulagern oda in den Header zu packn, damit's übersichtlicher wird.

<div id="captcha_wrapper" style="display:none; width:100vw; height:100vh; background-color:rgba(0,0,0,.8); align-items: center; justify-content: center;">
  <div style="background-color:#fff; padding:1em;">
    <h2>Bist du ein Mensch</h2>
    Hoooman! Du tippst ja schnell - leider lässt das für mich nur den Schluss zu, dass du ein böser Bot bist. Daher bitte ich dich, folgendes einfaches Captcha zu lösen. Was siehst du für einen Text in dem Bild?
    <img src='captcha.php' id='captcha_out'>
    <input type="text" id="txtCaptcha">
    <button id="checkCaptcha">Prüfen</button>
  </div>
</div>

In den Input '#txtCaptcha' muass des Captcha auf dem Bild eingtragn wern, und da Button '#checkCaptcha' führt später amoi dazu, dass da eingebene Wert überprüft wird.

8. Le Javascript - für des Captcha

Natürlich wandeln mia jetzt a des Javascript a bissl ab. Statt "location.reload" zeign mia jetzt des Captcha-DIV.

var typecounter = 0;
setInterval(function(){
  typecounter = 0;
}, 5000);
$(document).keypress(function(){
  typecounter++;
  if (typecounter > 35){
    $.post("captcha.php", { action: 'block' }).done(function(data) {
      if (data == 'block') {
        $("#captcha_wrapper").css('display', 'flex');
      }
    });
  }
});

Im Prinzip des Gleiche wia oben, nur die Zeiln

$("#captcha_wrapper").css('display', 'flex');

is neich. I hob mi für 'display: flex' entschieden, damit die Captchabox mittig zentriert wird.

9. Captcha.php

A da PHP-Code muass jetzt natürlich ogepasst wern. Mia blockn amoi (zunächst temporär) den Nutzer, und dann wolln mia aber no a Captcha zruckgebn und des in am weiteren Schritt abgleichn.

session_start();
if (isset($_POST['action']) && $_POST['action'] == 'block'){
  $_SESSION['blocked'] = true;
  die('block');
}else if (isset($_POST['action']) && $_POST['action'] == 'check'){
  if ($_POST['value'] == $_SESSION['captcha']){
    $_SESSION['human'] = true;
    $_SESSION['is_bot'] = false;
    die('unblock');
  }
}else{
  header('Content-Type: image/png');
  $width = 200;
  $height = 30;
  $im = imagecreatetruecolor($width, $height);
  $white = imagecolorallocate($im, 255, 255, 255);
  imagefilledrectangle($im, 0, 0, 399, 29, $white);
  $characters = '123456789abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ';
  $randomString = '';
  for ($i = 0; $i < 6; $i++) {
    $char = $characters[rand(0, strlen($characters) - 1)];
    imagestring($im, '2', 5+$i*20+rand(0, 10), 10, $char, imagecolorallocate($im, rand(0,100), rand(0, 100), rand(0, 100)));
    $randomString .= $char;
  }
  $_SESSION['captcha'] = $randomString;
  imagepng($im);
  imagedestroy($im);
}

Mit dem Code kann ma a bissl experimentiern. I hob mi für 6 Buchstabn aus am Range von [0-9a-Z] entschieden, ohne die Buchstabn o, O und 0, damit unter den älteren Nutzern ka Valwechslung auftritt :-)

10. Check vom Captcha

Schlussendlich checkn mia no den Wert vom Captcha. Dazu ergänzen mia folgendes Javascript:

$("#checkCaptcha").click(function(){
  $.post("captcha.php", { action: 'check', value: $('#txtCaptcha').val() }).done(function(data) {
    if (data == 'unblock') {
      $("#captcha_wrapper").css("display", 'none');
    }else{
      $("#captcha_out").attr("src", "captcha.php");
    }
  });
});

Mia postn do bei Klick auf den #checkCaptcha-Button amoi ois action den Wert 'check' und amoi den eingebenen String aus #txtCaptcha. Wenn mia ois Wert 'unblock' zruckkriagn, dann blenden mia den Captcha-Wrapper wieda aus, und da Nutzer kann ganz normal weitermachn. Andernfalls wird a neichs Captcha angezeigt.

11. Wertüberprüfung

Schlussendlich ändern mia no den Check am Anfang von jeder gschützten Datei und prüfn no, ob $_SESSION['human'] ned true is. Des hot den Zweck, dass a scho eingebenes Captcha a dazu führt, dass zukünftige "zu schnelle Tipper" nimma ois Botaktivität bewertet wern.

session_start();
session_destroy();
$_SESSION['is_bot'] = false;
if (isset($_SESSION['is_bot']) && $_SESSION['is_bot'] === true && !$_SESSION['human'] === true) die("Kein Zugang für Bots");

De Meldung "Kein Zugang für Bots" kann natürlich a a bissl lustiger gstoitet wern, und wer wirklich auf Nummer sicher gehn wü, kann do nochamoi a Captcha obfrogn - möglicherweise hot da Nutzer des Captcha bei da ersten Abfrage ned korrekt eingebn (oda gor ned versucht), den Browser gschlossn und wü jetzt nochamoi an neichn Versuch mit dem Captcha starten - dann miasst er theoretisch wartn, bis die Session abglaufn is (oda Cookies glöscht worn sand). Aber des is dann eam seine Schuld, dem Tschapperl.

TL;DR

  1. Nutzer tippt schneller ois 35 Zeichen in 5 Sekunden? Vielleicht a Bot?
  2. DIV einblenden mit am Captcha - jetzt scho temporär den Nutzer aussperrn via Session
  3. Captcha obfrogn - wenn korrekt, dann Session-Variable setzn; wenn ned - neichs Captcha generiern.
NeicherTrau kaum Scan, den du ned söba gfälscht hostElterSPAM-Protection-Methoden Nr. 3: Timing is wiedamoi olles