Skriptke.ltn.net/hv/  Human Verification Perl Script - Captcha script en Perl

  Español - English


Download:
Versión 0.1 hv.01.gz

(Licencia GNU/GPL)

¿Qué es y para qué sirve?

Es un script en Perl que dificulta que los robots rellenen formularios (Captcha). Sistema similar al que se emplea en los registros de usuarios de correo Web gratuito, y en los formularios de login para impedir el acceso a robots que intentan robar contraseñas. También se usa en registros de foros, libros de visita, etc. para impedir el acceso a robots de spam. Ejemplo:

Teclea el código de seguridad:

¿En qué se basa?

El sistema está basado en que el ojo humano es capaz de ver mejor que un OCR (Optical Character Recognition / Reconocimiento óptico de caracteres). La imagen que se muestra se distorsiona hasta el punto que el ojo humano pueda verla y un OCR no. 

Encontrar el punto de compromiso donde un humano puede ver la imagen y un ORC no, es complicado, aun así, en el futuro muy posiblemente los OCR sean capaces de ver tan bien o mejor que el ojo humano. Por lo tanto el sistema no es 100% seguro, sin embargo la cantidad de recursos y tiempo que un robot debe emplear para decodificar la imagen hace el sistema suficientemente eficaz. Para proteger un libro de visitas es más que suficiente, otra cosa sería el acceso a la Web de un banco, tal vez en este último caso los recursos y tiempo empleados por el robot compensen.

Un método alternativo más seguro es el que requiere interpretación, de lo que están más lejos las maquinas que de un simple reconocimiento óptico. Por ejemplo podíamos mostrar la imagen de un gato y preguntar al usuario de que animal se trata. Podemos configurar el script para una aproximación de este sistema:

Teclea EN NÚMEROS el siguiente código de seguridad:

Ejemplo:

Puedes ver un ejemplo real en amigar

¿Cómo funciona?

El script genera una imagen junto a un identificador de sesión y un valor hash md5. El script que recibe el POST/GET comprueba el código y las variables que genera el script:

Ejemplo:

Usuario: Contraseña:
Código de seguridad: igual a:
En el formulario:
<form method="POST" action="test.cgi">
Usuario: <input type="text" name="user" size="14">
Contaseña: <input type="password" name="pass" size="14"> <br>
Código de seguridad: <input type="text" name="code" size="6"> 
igual a: <script src="http://skriptke.ltn.net/hv/demo3/hv.cgi?4"></script>
<input type="submit" value="Ok">
</form>

Hemos añadido la línea:

<script src="http://skriptke.ltn.net/hv/demo3/hv.cgi?4"></script>

Que muestra la imagen con 4 dígitos. Además al cargar el script se generarán automáticamente, visibles sólo en tiempo de ejecución, las siguientes:

<input type="Hidden" name="hv_hash" value="VALORhv_hash">
<input type="Hidden" name="hv_sess" value="VALORhv_sess">

Que definen las variables hv_hash y hv_sess que deberán ser comprobadas en test.cgi

Al script se le puede llamar para que muestre un número determinado de dígitos, hv.cgi?6 mostrará la imagen con seis dígitos, sin parámetros muestra un número aleatorio de entre 4 y 6 dígitos.


En test.cgi:
...
use CGI;
$q = new CGI;

use Digest::MD5 qw(md5_hex);
my $skey = 'ChangeIt'; # secret key
my $code = $q->param('code'); # user put code
my $session = $q->param('hv_sess');
my $hash = $q->param('hv_hash');
my $expire = 60*2; # seconds expire session

if (time - $session > $expire) { 
print "Location: http://skriptke.ltn.net/hv/error_expire.es.htm\n\n";
exit;
}
if ($hash ne md5_hex($code,$skey,$session) ) { 
print "Location: http://skriptke.ltn.net/hv/error.es.htm\n\n";
exit;
}

print "Location: http://skriptke.ltn.net/hv/ok.es.htm\n\n";
...

La línea "$q = new CGI" recoge en la variable $q los valores pasados desde el formulario, en casos particulares tal vez se use un método alternativo al modulo CGI para recoger los parámetros.

$skey contiene la clave privada, este valor debe ser el mismo en en la configuración de hv.cgi. 

$code contiene el código de seguridad tecleado por el usuario.

$session contiene el valor de hv_sess que es el valor de la función "time" cuando se ejecutó el script que genera la imagen.

$hash contiene el valor de hv_hash.

Hemos definido la variable $expire con un valor de 120 segundos, que será nuestra primera comprobación en la línea "if (time - $session > $expire)" De esta forma evitamos que una clave pueda ser usada indefinidamente. Se puede configurar esta variable según las necesidades, si el formulario es largo, no cave esperar que el usuario sólo tarde 2 minutos en rellenarlo.

Por último comprobamos que el código de seguridad es correcto con la línea "if ($hash ne md5_hex($code,$skey,$session) )" los parámetros de la función "md5_hex" deben ser los mismos y en el mismo orden que en hv.cgi. 

En este ejemplo, el formulario sería el equivalente al formulario donde se quisiera implementar la utilidad, y test.cgi el equivalente al script a proteger, libro de visitas, registro de usuarios, login, etc.

 

Instalación

...

Se puede cambiar, si es necesario, la extensión del script hv.cgi por hv.pl, haciendo los cambio pertinentes en la variable $cgi_url de la configuración.

Configuración

El script "hv.cgi" contiene una sección etiquetada como "-- CONFIGURATION --" con las siguientes variables:

* Nota sobre el uso de caché:

Existen problemas (como no) con los caché, en algunas pruebas los resultados han sido pintorescos y caprichosos, dependiendo del navegador utilizado. Pese a que a simple vista pueda ser evidente no usar caché en una utilidad como esta, en este caso parece mejor idea hacer uso de el (nos referimos al caché del navegador, no a otro tipo de proxys, transparentes, etc. que suelen dar más problemas aún, la configuración del caché es "Private" lo que en teoría evita por defecto este tipo de proxys). Existen dos posibilidades, una que el navegador hace caso omiso de nuestra configuración de caché, y dos el navegador la respeta. En el primer caso no podemos hacer nada, sea cual sea nuestra configuración obtendremos resultados imprevisibles, no referimos al segundo caso. Para entender mejor el problema conviene saber como funciona este script, la utilidad en un primer paso genera contenido "JavaScript":

La llamada:
<script language="JavaScript" src="http://skriptke.ltn.net/hv/hv.cgi"></script>

Genera el código JavaScript:
document.write('<input type="Hidden" name="hv_hash" value="6eea498acabba9e41a7383cbf2d5abbd"><input type="Hidden" name="hv_sess" value="1081021782"><img border="0" align="absmiddle" src="http://skriptke.ltn.net/hv/hv.cgi?0-6eea498acabba9e41a7383cbf2d5abbd">');

En el segundo paso el navegador ejecuta el JavaScript y muestra la imagen (
http://skriptke.ltn.net/hv/hv.cgi?0-6eea498acabba9e41a7383cbf2d5abbd). Pues bien, en la mayoría de las pruebas el navegador ha mantenido en caché el JavaScript y la imagen no, con la consiguiente inconsistencia de datos, dado que los valores de los parámetros del formulario ya no correspondía a la imagen. (La utilidad impide que una misma imagen pueda ser cargada dos veces sin generar una nueva hash, por ejemplo, si se hace reload sobre
la URL de la imagen da un error).

Por lo tanto si se observan problemas de este tipo, hay que incrementar el valor de la variable $max_age hasta el máximo del valor que se utilice en el propio script en la variable $expire como en el ejemplo de más arriba.

 


 

 


...

LTN

...