Text Captcha

Flex

(aka Felix Jacobi)
Nachdem in letzter Zeit der TextCaptcha ein wenig häufiger aufgekommen ist, habe ich mich mal dran gesetzt und einen einfachen Text Captcha geschrieben... Und versucht dabei mich ein wenig weiter in OOP zu üben.

Nun bin ich kein Profi darin und habe auch keinerlei fachliche Ausbildung in diesem Bereich, deshalb bin ich nun offen für jedwede Verbesserung:

txtcaptcha.class.php
PHP:
<?php  
/**
 * txtcaptcha.class.php, txtCaptcha
 * 
 * This file is used to read, show and validate the Questions
 * @author Felix Jacobi <root@flexmex.net>
 * @version 0.1
 * @copyright 2007
 *
 */
class txtCaptcha {
	
	protected $_config;
	protected $_questions;
	protected $_solutions;
	
	public $question;
	
	/**
	 * Creates Database Connection
	 *
	 * @param array $config 
	 */
	public function __construct($config) 
	{
		$this->_config = $config;
		
		if($this->_config['debug'] == "false") {
			error_reporting(0);
		} else error_reporting(E_ALL);
		
		$this->_conn = mysqli_connect($this->_config['db']['host'],
									  $this->_config['db']['user'],
									  $this->_config['db']['pass'],
									  $this->_config['db']['dbname']);
			
	}
	
	/**
	 * Reads all Questions into $this->_questions
	 *
	 */
	protected function _getQuestions() 
	{
		$sql = "SELECT `id`, `question`
				FROM `txtcaptcha`";
		$result = mysqli_query($this->_conn, $sql) or die(mysqli_error($this->_conn));
		while($row = mysqli_fetch_assoc($result)) 
		{
			$this->_questions[$row['id']] = $row['question'];
		}
	}
	
	/**
	 * Returns a random Question out of the database
	 *
	 * @return array Random Question and ID
	 */
	protected function _randQuestion() 
	{
		srand((float)microtime() * 1000000);
		$id = array_rand($this->_questions);
		$this->question['question'] = $this->_questions[$id];
		$this->question['id'] = md5($id);
		
	}
	
	/**
	 * checks if the given Answer is correct
	 *
	 * @return bool
	 */
	public function checkAnswer() 
	{
		if(get_magic_quotes_gpc() === true) {
			$post_id = mysqli_real_escape_string($this->_conn, stripslashes($_POST['txtcaptcha_id']));
		} else {
			$post_id = mysqli_real_escape_string($this->_conn, $_POST['txtcaptcha_id']);
		}
		$sql = "SELECT `id`
				FROM `txtcaptcha`
				WHERE MD5(`id`) = '".$post_id."'
				AND `answer` = '".(int)$_POST['txtcaptcha_answer']."'";
		$result = mysqli_query($this->_conn, $sql);
		$status = mysqli_num_rows($result);
		
		if($status == '0') {
			return false;
		} else return true;
	}
	
	/**
	 * Returns the question to public
	 *
	 * @return array random Question
	 */
	public function showQuestion() 
	{
		$this->_getQuestions();
		$this->_randQuestion();
		
		return $this->question;
	}

}

example.php
PHP:
<pre>
<?php
include_once("txtcaptcha.class.php");

/* Config */
$config['db']['host'] = "localhost";
$config['db']['user'] = "root";
$config['db']['pass'] = "";
$config['db']['dbname'] = "test";

$config['debug'] = "true";

$txtCaptcha = new txtCaptcha($config);

$question = $txtCaptcha->showQuestion();

if(isset($_POST['submit'])) {
	if($txtCaptcha->checkAnswer() === true) echo "ja<br/>";
	else echo "nein<br/>";
}
?>
<form action="./example.php" method="post">
	<label for="txtcaptcha_answer"><?php echo $question['question']; ?></label>
	<input type="text" name="txtcaptcha_answer" />
	<input type="hidden" name="txtcaptcha_id" value="<?php echo $question['id']; ?>" />
	<input type="submit" name="submit" value="send" />
</form>
</pre>

Das ganze gibts hier auch nochmal als Source zu begutachten:

http://dev.flexmex.net/temp/txtcaptcha.class.phps
http://dev.flexmex.net/temp/example.phps

Die Kommentare sind mir leider nicht so gut gelungen (sollen möglichst phpDoc valide sein), da nehme ich auch gerne Ratschläge entgegen.

Die example.php ist auch nicht wirklich fertig. In der finalen Version soll man nur noch an der entscheidenden Stelle die captcha.php includen und die macht den Rest.
 
Zuletzt bearbeitet:
Ach, sorry, das ist mir jetzt gar nicht aufgefallen, weil es vorher mit PDO und Prepared Statements am Laufen war.

Ist geändert.
 
unter php4 lauffähig?

Ich will auch OOP lernen, hab mit n buch drüber gekauft, dummerweise behandelt des nur php5, deswegen frag ich :) Mir iss wichtig, dass diese Dinge immer unter PHP4 laufen, weil viele schlichtweg PHP4 aufm server laufen haben :(

Aber frage: Worin liegt der Sinn bei TextCaptcha? Ich mein, klar, jemand der die Frage beantworten kann wird kaum Probleme haben, aber da muss ja auch die schreibweise der Antwort gegeben sein, und die antwort selbst muss man ja auch wissen... Man kann ja nicht davon ausgehen, dass jedwede frage für jeden beantwortbar ist^^
 
Welches Jahr haben wir? 2007
Wieviele Augen hat der Mensch? 2
Wieviel ist 2+2? 4
Wieviele Beine hat der Mensch? 2
Wieviele Finger hat der Mensch? 10
Wieviele Stunden hat ein Tag? 24
Wieviele Monate hat ein Jahr? 12
Wieviele Minuten hat eine Stunde? 60
Wieviele Monde hat die Erde? 1
Wieviele Räder hat ein Automobil? 4

Ich denke diese Fragen sollten 99% aller Besucher beantworten können ;)

Weitere Vorteile des TextCaptchas ist, dass ein Bot sie nicht beantworten kann. Dafür müsste er "denken" können. Er kann die Fragen nicht mit einer OCR Software erfassen und automatisch wiedergeben (wie es bei grafischen Captchas der Fall ist) sondern müsste auf verschiedene Wörter in der Frage reagieren.

Ein weiterer Vorteil ist, dass man Text vorlesen lassen kann und vergrößern kann, wie es einem beliebt, sprich einfacher für Menschen mit einer Behinderung o. ä.

Und nein, so wie die Klasse jetzt ist, ist sie nicht unter PHP4 lauffähig, allerdings sollten
 
mmmh, okay :D weiss nich, kennste die sendung "SAM" auf PRO7? Da machen die manchmal so "Fragestunden" bei Passanten, da schlägt man sich die Hand vorm Kopp, wenn man deren Antworten zu den Fragen hört :D deswegen mein ich, müsst man die Fragen derart einfach sein, dass die auch vom letzten Hinterwäldler beantwortbar iss :D

Naja, und es iss praktisch nur ne Frage der Zeit, bis die Bots auf diese Captchas umgehen können, denk ich mal, gerade bei Fragen wie "Wie viele Beine hat ein Mensch?" - brauchst praktisch nur das Dokument nach dem Begriff scannen, suchst das nächste Formular, trägst da 2 ein und fertig iss die Luzi - theoretisch nicht schwer sowas zu programmieren. Und wenn vieeeeele dieselben Fragen haben ist es unter Umständen nicht irrealistisch, dass es recht schnell gehen könnt^^

Naja, bin mal gespannt. Ich programmier ja auch immo n eigenes CMS, dass ich auch woanders einsetzen will, problem ist ja immer PHP aufm Server upzudaten, z.B. gerade dann wenn Plesk aufm Server läuft, oder gar der Serverhoster nicht auf Version 5 updaten will...
 
Hi, ich schon wieder... ;)

Noch ein kleiner Nachtrag zu mysql_real_escape_string():

Du musst aufpassen, ob Magic Quotes GPC aktiviert ist, falls nicht, ist alles richtig so, andernfalls solltest du vorher noch stripslashes() benutzen, da es sonst zu Problemen kommen kann, da z.B. Anführungszeichen doppelt mit einem Backslash escaped werden.

PHP:
if(get_magic_quotes_gpc())
  $_POST['txtcaptcha_id'] = stripslashes($_POST['txtcaptcha_id']);

...

mysql_real_escape_string($_POST['txtcaptcha_id'])
 
Zuletzt bearbeitet:
Ja, allerdings sind sämtliche grafischen Captchas anfälliger als Text Captchas.

Für grafische Captchas gibt es vorgefertigte Bots en masse, die fast alle die selbe Engine verwenden (Pwntcha).

Bei Text Captchas müsste sich jemand hinsetzen und sämtliche Fragen eintragen oder Stichwörter, was eine ganz schöne Arbeit ist.

Und wenn man das merkt, kann man einfach die alten Fragen rauswerfen und neue reinsetzen.

Und was solche Umfragen im Fernsehen angeht...

Frage 1000 Leute und du wirst fast immer 5-6 haben die eine doofe Antwort geben.

Nachtrag zu EvilO

Ist geändert, danke.
Ist eine große Umstellung, wenn man plötzlich nicht mehr nur noch von der eigenen Konfiguration ausgehen muss, sondern von vielen ;)

:offtopic:
Kann es eigentlich sein, dass man sich im AZ mal gesehen hat?
 
Zuletzt bearbeitet:
hrr jo, aus den 5-6 von 1000 Leuten, die du fürs fernsehn befragst kannste sicherlichdas doppelte, dreifache machen wennde im Inet fragst :D laufen ja sehr viele "Kiddies" im inet rum^^

Aber iss auch egal, sicher sind Text-Captchas da nich sooooo Anfällig denk ich mal, BIS man sie eventuell automatisch auslesen kann, denn man muss eigentlich nur die Position des Sicherheitsfeldes wissen, ein stück zurück gehen, HTML-Code rausfiltern, das Fragezeichen suchen (man gehe jetzt mal davon aus, dass eine Sicherheits"frage" immer mit nem Fragezeichen endet), dann den letzten Punkt vor dem Fragezeichen, und das speichert man dann eben ab. Okay, einer muss dann immer noch die Antwort zur Frage geben :D aber wenn das jemand macht, haste sicherlich bald nen umfangreichen Fragekatalog, und der iss ja nicht vergänglich^^ Und ich mein: Knackt des in der Tat jemand, und man hat auf der eigenen Seite einen Fragen/Antworten-Katalog auf der Website - man müsste den ganzen Katalog komplett austauschen, wenn man nicht die ID der Frage mit dem User--Eintrag abspeichert. Man kann sonst nicht nachvollziehen, zu welchem Spameintrag welche Frage gestellt wurde.

Ein weiteres Problem ist ja auch: Du brauchst hunderte von Fragen! wenn du wenige Sicherheitsfragen hast, wiederholen die sich zu schnell wieder. Ein Bot kann dann das <form>-Abschnitt aus dem HTML auslesen, abspeichern und miteinander vergleichen. Er nimmt dann nur den Text heraus, der sich ständig verändert und eventuellen weiteren Merkmalen entspricht. Dann haste ganz ganz fix einen riesigen (mehrsprachigen) Fragenkatalog zusammen, den eine Person auch recht schnell mit Antworten füllen kann. Mag zwar sein, dass das nervend ist, aber man kann denke ich ganz gezielt davon ausgehen, dass die Spamversender auch diese nervige Aufgabe meistern werden. Denn sie wollen ja Spam verbreiten^^ Und die Mehrsprachigkeit mag kein Hindernis sein, denn man weiss nicht, wie die Spamtypen organisiert sind, ich denke auch hier gibts ein gewisses internationales "schwarzes" Netzwerk...

Deswegen auch mein bedenken, ob sich Textcaptchas durchsetzen, sie sind sicherlich ärgerlich für Spambots, aber sicher nicht unumgänglich. Schon gar nicht, wenn die Webseitenbetreiber schlicht aus Faulheit keine eigenen Fragen generieren, sondern einen eventuell schon vorgefertigten Katalog nutzen, der mit dem CMS mitgeliefert wird. Und - wer denkt sich schon 300 eigene Fragen aus, damit Textcaptchas einigermaßen Sinn machen^^

Captchas sind meiner Meinung nach zwar ein ganz nettes Mittel Bots dran zu behindern Spam zu verbreiten, aber wie du schon sagst: Bildcaptchas sind knackbar, was für mich schon eine krasse Leistung ist. Man könnt beinah sagen, die haben meinen Respekt. Aber gleichzeitig heisst das auch: Text ist genauso umgehbar (ich denk mal nicht umsonst wurden Bildcaptchas eingeführt :D), wie z.B. auch Rechenaufgaben, die können von Bots auch schon umgangen werden, hab ich letztens erst gesehn^^


Ich denk mal, Spam kann man nur dann effektiv umgehen, wenn sich die Authorisierungstechniken grundlegend ändern, sprich es muss eine technik entwickelt werden, die einen Menschen von einem Bot unterscheiden können, aber des iss wohl noch ganz ganz weit wech :D
 
Selbst wenn sie sich wiederholen, es muss trotzdem jemand die Eingaben machen. Und die meisten werden sich davor sträuben.

Man siehe nur das phpBB. Ich habe zwei kleine Änderungen gemacht (eine Checkbox hinzugefügt, die eine Frage stellt und Ja/Nein zulässt) und eine minimale Passwörtstärke eingerichtet (min. 6 Chars und Alphanumerisch).

Seitdem gibt es bei mir keinen Spam mehr.

Die Frage ist natürlich, ob sich jemand dransetzt und es auf mein Forum anpasst, aber lohnt sich der Aufwand wirklich? Für eine kleine Community?
Nein, es bringt mehr den Bot 20 andere ungesicherte Seiten zuspammen zu lassen, als ihn für eine zu ändern.

Das würde sich natürlich ändern, wenn das System verbreiteter ist, allerdings selbst dann kann man es noch verschärfen, durch eine reine Audioausgabe, z. B.

Kampf gegen Spam ist mittlerweile genauso wie der Kampf gegen Sicherheitslücken. Er wird nie zu Ende sein ;)
 
Zurück