Mit PHP einen simplen Captcha cracken

Solange ein Captcha nicht sehr aufwändig generiert wurde, ist er auch entsprechend leicht zu knacken. Ich habe hier mal ein Beispiel für einen schlechten Captcha:

Ein Beispiel für einen schlechten Captcha

Was ist an diesem Captcha schlecht? Der auszulesende Inhalt ist nicht abwechselnd genug (immer nur Zahlenfolgen), nicht verzerrt, nicht farblich variierend und hebt sich zu gut vom Hintergrund ab. Das alles werden wir nun ausnutzen um den Captcha zu knacken.

Zuerst müssen wir „Zahlendefinitionen“ schreiben. Das heißt wir legen für jede Zahl einige eindeutige Fixpunkte fest, mit denen die Zahl eindeutig identifizierbar ist.

Beispiel an der Zahl „1“:

     OO             
    OOO             
   OOOO             
     OO             
     OO             
     OO             
     OO             
     OO             
     OO             
   OOOOOO           

Die Definition:

function is_one($pix, $x, $y) {
	$c = 0;
	$c += check($pix, $x, $y, 2, -2); // 5 / 5
	$c += check($pix, $x, $y, 3, -2); // 6 / 5
	$c += check($pix, $x, $y, 1, -1); // 4 / 6
	$c += check($pix, $x, $y, 2, -1); // 5 / 6
	$c += check($pix, $x, $y, 3, -1); // 6 / 6
	$c += check($pix, $x, $y, 0, 0); // 3 / 7
	$c += check($pix, $x, $y, 1, 0); // 4 / 7
	$c += check($pix, $x, $y, 2, 0); // 5 / 7
	$c += check($pix, $x, $y, 3, 0); // 6 / 7
	$c += check($pix, $x, $y, 2, 1); // 5 / 8
	$c += check($pix, $x, $y, 3, 1); // 6 / 8
	$c += check($pix, $x, $y, 2, 2); // 5 / 9
	$c += check($pix, $x, $y, 3, 2); // 6 / 9
	$c += check($pix, $x, $y, 2, 3); // 5 / 10
	$c += check($pix, $x, $y, 3, 3); // 6 / 10
	$c += check($pix, $x, $y, 2, 4); // 5 / 11
	$c += check($pix, $x, $y, 3, 4); // 6 / 11
	$c += check($pix, $x, $y, 2, 5); // 5 / 12
	$c += check($pix, $x, $y, 3, 5); // 6 / 12
	$c += check($pix, $x, $y, 2, 6); // 5 / 13
	$c += check($pix, $x, $y, 3, 6); // 6 / 13
	$c += check($pix, $x, $y, 0, 7); // 3 / 14
	$c += check($pix, $x, $y, 1, 7); // 4 / 14
	$c += check($pix, $x, $y, 2, 7); // 5 / 14
	$c += check($pix, $x, $y, 3, 7); // 6 / 14
	$c += check($pix, $x, $y, 4, 7); // 7 / 14
	$c += check($pix, $x, $y, 5, 7); // 8 / 14
	if ($c == 27) {
		return true;
	}
	return false;
}

Dort sind nun alle Fixpunkte relativ zum „ersten“ Fixpunkt gespeichert. Der „erste“ Fixpunkt ist bei der eins der Punkt ganz unten rechts. Nachdem wir solche Definitionen für alle Zahlen von 0-9 erstellt haben geht’s nun an die Wiedererkennung der Zahlen. Dazu muss zuerst der Hintergrund herausgefiltert werden und die Grafik in ein besser (für unser Programm) lesbares Format gebracht werden. Dies mache ich wie folgt:

function read($path) {
	$im = ImageCreateFromPNG($path);
	$pix = array();
	$sy = ImageSy($im);
	$sx = ImageSx($im);

	for ($y = 0;$y<$sy;$y++) {
		for ($x = 0;$x<$sx;$x++) {
			$col = imagecolorat($im, $x, $y);
			$rgb = imagecolorsforindex($im, $col);

			if ($rgb["red"] <= 150) {
				$pix[$x][$y] = "O";
			}
			else {
				$pix[$x][$y] = "W";
			}
		}

	}

	// ...
}

Nun haben wir den Array $pix, der bei [x][y] entweder W (für weiß) oder O (für schwarz) enthält. Jetzt müssen wir nur noch durch den Array durchgehen und nach unseren Fixpunkt-Mustern suchen:

        // ....

        $no = 0;
	$complete_string = "";
	$found_at = array();
	
	for ($x = 0;$x<$sx;$x++) {
		for ($y = 0;$y<$sy;$y++) {
			if ($pix[$x][$y] == "O" && !in_array("$x|$y", $found_at)) {
				$no = 0;
				
				if (is_one($pix, $x, $y)) {
					$no = 1;
				}
				if (is_two($pix, $x, $y)) {
					$no = 2;
				}
				if (is_three($pix, $x, $y)) {
					$no = 3;
				}

				if (is_four($pix, $x, $y)) {
					$no = 4;
				}

				if (is_five($pix, $x, $y)) {
					$no = 5;
				}

				if (is_six($pix, $x, $y)) {
					$no = 6;
				}

				if (is_seven($pix, $x, $y)) {
					$no = 7;
				}

				if (is_eight($pix, $x, $y)) {
					$no = 8;
				}

				if (is_nine($pix, $x, $y)) {
					$no = 9;
				}
				
				if ($no != 0) {
					$found_at[] = "$x|$y";
					$complete_string .= $no;
				}
			}
		}
	}

	//...

Die Variable $complete_string enthält nun den ausgelesenen String. Simple as that 😉

Hier der gesamte Code inklusive der Hilfsfunktion check(). Der Code ist schon etwas älter, also nicht über schlechten Code-Stil wundern – er soll legendlich das Prinzip erklären: http://agrafix.net.pastebin.com/b6exg0SW

Noch ein Screenshot:
Geknackter Captcha

Das war’s schon – viel Vergnügen damit!

 

Crawler – eine „Gefahr“?

Letztes Jahr im Herbst ging „SchülerVZ“ durch die Presse – persönliche private (?) Daten wurden von Crawlern „geklaut“. Und jetzt ist es wieder passiert (siehe hier), wieder sind Millionen von Daten geklaut worden. Das ganze ging eigentlich relativ problemlos – ein Crawler bewappnet mit der entsprechenden RegEx krabbelte durch die Seiten von 1,6 Millionen Nutzern. Gehindert werden sollte der Crawler von einer „Klicksperre“, die ein maximum von Klicks pro Zeiteinheit erlaubt. Doch dies umging der Crawler ganz ohne Probleme – der Programmierer legte einfach 800 SchülerVZ-Accounts an, die parallel benutzt werden konnten. SchülerVZ hatte zuvor die Captchas wieder ausgebaut und hatte somit mehr oder weniger alle Tore zu ihren Daten offen – abgesehen von den Daten jener, die sie nur für den Freundeskreis einsehbar gemacht hatten.

Nun kann man sich Fragen ob Crawler eine Gefahr für die eigene Privatsphäre sind oder einfach nur harmlos Daten sammeln. Denn Crawler durchforsten nicht nur „normale“ Seiten, sondern das ganze Internet und dessen Soziale Netzwerke. Die Daten werden dann abgespeichert und auf irgendwelchen Archiv-Servern gespeichert. Google zum Beispiel nimmt riesige Mengen an Daten in seinen Cache auf – das heißt selbst wenn diese vom ursprünglichen Server gelöscht wurden kann man sie noch einsehen. Andere Crawler erstellen jeden Monat einen „Schnappschuss“ von einer Webseite und archivieren ihn dann. Daten die einmal im Internet sind, bleiben dort wohl for eine (wenn auch) begrenzte „Ewigkeit“.

Es gibt dank verschiedensten Crawlern schon Suchmaschienen, die nach Informationen über Personen suchen. Und wenn in dessen Datenbanken jetzt noch Daten aus Sozialen Netzwerken wie etwa Bilder, Vorlieben oder Lebensweise kommen, dann kann jeder (!) im Internet alles über eine wildfremde Person erfahren. Bei einem Bewerbungsgespräch würde es dann nicht mehr „Hallo Herr Crawlerman, erzählen Sie von sich“ sondern „Hallo Herr Crawlerman, ich habe gehört sie trinken viel Alkohol, sind sehr freizügig und ihre Freundin hat sie wohl grade verlassen?“ heißen. Ist das wirklich wünschenswert?

In dieser Hinsicht denke ich sind Crawler eine Gefahr für die Privatsphäre des Einzelnden, allerdings sehr nützlich um andere Daten zu erfassen und zu durchsuchen. Man müsste eine Lösung finden, Crawler effektiv aus der „Cyber-Privatsphäre“ herauszuhalten, und man muss die Betreiber von sozialen Netzwerken dazu zwingen schärfere Maßnahmen in Hinsicht auf Privatsphäre zu ergreifen.