Erwin.Ried.cl / Desarrollos / Desarrollo Web /
Crea un captcha exclusivo para tu sitio

Los problemas de seguridad siempre comienzan en un grado directamente proporcional a lo popular y conocido que es ese algo en cuestión. En este documento aprende a crear un simple captcha para tu sitio que tiene la particularidad de demostrarte cómo funciona este mecanismo y de paso asegurarte de que tu creación será universalmente única (09/11/2009 07:38 PM)


La introducción de este artículo es básicamente el documento ¿Usted es realmente un humano? en donde demuestro una forma de romper programáticamente un captcha.

El problema es cuando utilizas un captcha popular (que claramente se integró fácilmente a la plantilla de tu sitio) el cual generalmente tiene algún método conocido para vencerlo. Así se pierde el objetivo original que te impulsó colocar este mecanismo de protección frente a los robots de publicidad masiva que seguirán escribiendo comentarios sobre comprar viagra y otros temas que ya nuestro ojo está casi entrenado para obviarlos pero que aún así irritan a cualquiera por sólo el hecho de ser indeseados.



1. Diseño del fondo


Un captcha debe ser lo bastante sencillo para que una persona lo reconozca fácilmente y a la vez lo bastante sofisticado para dificultar la creación de un programa que lo decodifique.

Primero, comencemos con un fondo:



¿Blanco?, claro que no, con la experiencia del decodificador de captcha que hice hace un tiempo utilizaremos pequeñas modificaciones que dificulten el proceso, ahora el color de fondo será:

Código:
color = RGB(azar,azar,azar);


En donde azar será un número entre 240 y 255, así como el color blanco es RGB(255,255,255) obtendremos colores claros:





2. Un poco de distorsión


Seguiremos con un poco de distorsión creada apilando varias letras y números de un color al azar y suave. Algunos ejemplos obtenidos al azar de esta etapa se pueden apreciar a continuación:





Aún creo que le falta aderezo a ese fondo, podría tener algo de colorido con píxeles de color y posición aleatorios:



Listo. Ahora coloquemos las letras y números principales, aunque la idea es que el usuario pueda elegir si desea utilizar sólo letras, números, o ambos y además en qué cantidad.

Las letras serán de colores alternantes, leves giros al azar y pequeñas alteraciones en sus posiciones ideales:





3. Algo más


Aunque los caracteres podrían tener un pequeño efecto de giro en el fondo:



Ese pequeño efecto se añade simplemente repitiendo el mismo carácter con diferentes ángulos de giro, aunque al ver las imágenes (queremos evitar robots, pero no personas) lo ideal será que no difieran en más de un par de grados para evitar efectos extraños, básicamente:

Código:
para n=1 hasta largo_captcha
{
 color = RGB(azar,azar,azar)

 angulo = azar2-20
 imprime_caracter(captcha[n],angulo)

 angulo2 = azar3-5
 imprime_caracter(captcha[n],angulo+angulo2)

 angulo3 = azar3-5
 imprime_caracter(captcha[n],angulo+angulo3)
}


En donde azar es un número entre 0 y 150 pues RGB(0,0,0) es negro y RGB(150,150,150) es un color gris. Así obtenemos cualquier color dentro de esos rangos con variaciones de rojo, verde y azul. Luego azar2 es un valor entre 0 y 40 (se le resta la mitad para obtener un ángulo de giro desde izquierda a derecha) y azar3 es un valor entre 0 y 10 que adiciona un giro adicional a angulo, en angulo2 y angulo3.

Así el efecto es mucho más sutil:



Ahora finalizando nuestro captcha, un último condimento:



Consideración
Como están documentados todos los valores de coloración, existe una forma muy simple de "limpiar" la imagen, como se vio en el documento ¿Usted es realmente un humano? se podría aplicar un filtro por píxeles y sólo dejar los colores dentro del rango utilizado para las letras relevantes.

Es cierto que de esta forma este captcha sería sumamente débil, pero el as bajo la manga en este caso puede ser las posibilidades de creación de cualquier tipo y estilo de captcha, y no utilizar directamente y sin modificar el código actual.




4. Utilizando el captcha


Nota
Estas instrucciones se aplican para el código php que genera el captcha de ejemplo, disponible más abajo para su descarga


Para mantener el objetivo principal de evitar ingresos automatizados de información, la imagen ni el método de utilización de la misma pueden tener relación con el código "secreto" que un humano podría descubrir sólo por su "habilidad" de ser humano.

Entonces primero debemos solicitar un nuevo captcha al servicio que vamos a crear:

Código:
// Solicitar un nuevo código
$t = fopen("http://servicios.ried.cl/captcha/?modo=nuevo", "r");


Aunque podríamos usar algunos parámetros opcionales que agregué al captcha para añadir versatilidad:

Código:
// Solicitar un nuevo código
$t = fopen("http://servicios.ried.cl/captcha/?modo=nuevo&largo=4&letras=1",
"r");


En el último código estoy obligando al servicio a preparar un captcha con cuatro letras (sólo letras, no números)

Luego simplemente leemos el código interno que generó:

Código:
$c = fgets($t); // Leer el código interno
fclose($t); // Cerrar


Nota
Pueden existir diversas maneras de trabajar con el servicio, por ejemplo utilizar otras funciones de lectura adicionales a usar fopen y fgets, trabajar con otros componentes dentro de otros lenguajes, entre otras, pero la idea es ejemplificar el proceso de la forma más simple para posteriormente poder aplicarlo a cualquier necesidad


Es importante considerar que el código interno que genera el servicio nunca tiene relación con el captcha. El código interno es una cadena de letras minúsculas de un largo predeterminado (10 letras para el código de ejemplo) que se relaciona con el código real del captcha pero de forma interna:



Ahora para obtener la imagen simplemente utilizamos nuestro código interno a manera de identificador, así el servicio consulta internamente a cual código secreto (código del captcha) corresponde ese código y nos retorna el código secreto, pero dibujado dentro de una imagen:

Código:
http://servicios.ried.cl/captcha/?modo=imagen&codigo=<?php echo $c ?>


La variable $c corresponde al código interno que nos entregó anteriormente el servicio de captcha.



De una forma trivial hacemos una interfaz apropiada para este ejemplo:

Código:
<form method="post" action="">
       <p>Escriba las cuatro letras de la imagen en el recuadro inferior:</p>
       <p><img src="http://servicios.ried.cl/captcha/?modo=imagen&codigo=<?php
echo $c ?>" border="1" /></p>
       <p><input name="captcha" type="text" size="10"
maxlength="4" />
       <input name="code" type="hidden" id="code"
value="<?php echo $c ?>" />
  <input name="check" type="submit" id="check"
value="Comprobar" /></p>
</form>


Formulario que tiene el siguiente aspecto:





6. Comprobando la entrada del usuario


Luego de que el usuario escribe el código que "cree" ver, debemos comprobarlo. Naturalmente necesitamos ese código interno que identifica toda la operación, pero que no tiene una relación directa con el código real secreto del captcha ("matemáticamente" me refiero a que uno no es función del otro):



El diagrama se traduce a una línea de código:

Código:
// Comprobar si es correcto
$t =
fopen("http://servicios.ried.cl/captcha/?modo=verificar&usuario=$captcha&codigo=$codigo",
"r");


Ahora, de la misma forma en que está representado usando colores en el diagrama anterior, recibimos un resultado:

Código:
$c = fgets($t);
fclose($t);

$output = intval($c);


Asimismo en un pseudobinario 1 significa que el código introducido por el usuario, basándose en lo que vio en la imagen del código secreto coincide con el código secreto relacionado con el código interno que identificó la operación, un 0 significa que no corresponde y un -1 significa que la operación de comprobación es incorrecta (el código interno que proporcionamos no tenía un código secreto asociado).



7. ¡Ajá! y cómo funciona el "código interno"


Hay muchas pistas en los puntos anteriores, claramente todo se almacena en una tabla en la base de datos:





8. Código y ejemplo


Código fuente para PHP4 o superior: (Actualizado 09-04-2007)
files/articles/captcha_php_001/captcha_src_2007_04_09.zip


Ejemplo funcional:


Enlace externo:
http://servicios.ried.cl/captcha/test.php


9. Más allá del captcha


Probablemente seas una persona que deteste los captchas, muchas veces tienes que introducir una palabra en la que estas cien por ciento seguro de que es la correcta y el maldito sistema te la rechaza, entonces no quieres por ningún motivo que los usuarios tengan la misma experiencia con tu propio sitio, en ese escenario: ¿Qué otros procedimientos pueden utilizarse en vez de un captcha para proteger tu sitio?

A) Comprobaciones varias

En el formulario se pueden añadir algunos campos ocultos activos para mejorar la seguridad del mismo pues la mayoría de los robots analizan el envío de variables (probablemente utilizando POST) y así pueden simular aquellas consultas, colocando información no deseada.

Todos los lenguajes activos para desarrollar sitios web permiten conocer la dirección de referencia de un usuario en particular. Si alguien copiara la información que se le envía al servidor al momento de realizar un comentario, sólo podría utilizarlo desde esa dirección IP, lo que evitaría el envío desde diversos equipos.

Así mismo se podría incluir una etiqueta de hora y fecha (algo codificada) que valide el comentario sólo por algunos minutos desde que se generó la página que contiene el formulario. Así restringiremos el envío de comentarios sólo para acciones directas en nuestra página y no consultas simuladas.


B) Un formulario truculento

Bajo capas u algún otro artilugio gráfico invisible (o también visible, avisando a nuestras visitas) se puede colocar uno o varios campos en el formulario para el comentario los cuales pueden tener ciertas restricciones para que el comentario mismo sea válido, por ejemplo no modificar su contenido original o no escribir nada ahí, un robot tradicionalmente intentará llenar todos los campos disponibles y sus comentarios serán rechazados.

C) Un uso ingenioso de un captcha

Un captcha no sólo debe ser una imagen de un código distorsionado, podrían también ser una colección de imágenes con preguntas relacionadas de respuesta muy fácil (aunque a la vez extremadamente complicadas para un sistema automatizado)

D) El nunca bien ponderado: "aprobación por el administrador"

Añadir la aprobación de cada comentario puede ser uno de los recursos más poderosos para evitar comentarios incorrectos, el gran problema es que la moderación veda un tanto la sensación de libertad del lector.

Al mismo tiempo añade un trabajo adicional para el administrador y especialmente en los sitios en donde los comentarios no buscan una respuesta directa y son simplemente opiniones. Para mermar un poco esta última complicación se pueden crear listas de condiciones (por ejemplo ciertas palabras) que exijan la aprobación del administrador sólo para algunos comentarios.

En mi sitio los comentarios deben ser aprobados, aunque generalmente necesitan una réplica por lo que la aprobación no es un gran trabajo extra pensando en que igual debo revisarlos.



10. Conclusiones

Un captcha nunca será la técnica más efectiva, pero creando uno personal podemos lograr una increíble efectividad. La razón es que la mayoría de las técnicas para romper esta protección está basada en una solución muy particular, que exactamente no será la nuestra.

Incluso podemos mejorar el algoritmo al añadir capacidades de seleccionar una fuente para la palabra secreta o cada letra en particular diferente o ingeniárnosla para aplicar distorsiones y otros efectos más avanzados, pero en base la idea es poder dar un punto de partida para todos esos proyectos.

Otra forma, más avanzada y profesional, es utilizando una solución comercial como la ofrecida por la empresa Lanapsoft, con su producto BotDetect Captcha el cual puede probarse directamente en la demostración en línea de BotDetect Captcha.

Haga clic sobre una de las estrellas para calificar este artículo.

Opiniones y comentarios (Escribir un nuevo comentario)
claro eso es claro, un ataque dirigido por un humano rompe instantaneamente mi sugerencia, pero tambien un humano instantaneamente supera cualquier sistema captcha. esto es basicamente para evitar a los robots, que andan paseandose por la web buscando formularios te ataquen ya que nunca los ven,
Escrito por vipjonathan (08/10/2009 04:11 AM)
Lo malo es que ningún cliente portátil como iPhone o un Windows Mobile device podría ver esos botones flash. El detalle está en que un captcha es una prueba de "compresión", mientras el flash en este caso sería una especie de dificultad de acceso (si un humano quisiera automatizar ambos, el de captcha siempre sigue presentando el problema de la inexistencia de un PC "comprendiendo")
Escrito por Erwin Ried (08/10/2009 01:07 PM)
YO tenia muchisimos problemas con robots, pero encontre una solucion sencilla pero muy practica. Los links que dirijo hacia las paginas con formularios, los hago atravez de botones en flash, por lo cual hasta el momento ningun robot ha podido superarlo. funciona tanto para sitios dinamicos como sencillos en html, ya que puedes trabajar la variable en los dinamicos directamente en el php, y solo dejas el valor de relleno el nombre del boton, algo de mod_rewri termina el trabajo :P aqui lo tengo mejor explicado, espero les sirva de algo: http://www.google.com/support/forum/p/webmasters/thread?tid=0513214de1ed832d&hl=es
Escrito por vipjonathan (08/10/2009 01:25 AM)
Alguien con malas intenciones quiebra instantáneamente tu seguridad basada en botones flash
Escrito por Erwin Ried (08/10/2009 02:11 AM)
Bastante bueno tu articulo. En lo personal, hace unos meses hice un captcha, pero lo basé en el tiempo unix, le pasé md5 y corté pasando a mayúsculas. Bastante simple, pero funciona bien hasta el momento. Lo que si, creo que son bastante incómodos para los visitantes, si estas pensando utilizarlo en un sitio web, aunque tengas variados beneficios. Pienso que es mejor validar de buena forma los formularios, utilizar bien las matrices en el caso de php, y no utilizar get para procesar. Saludos, y felicitaciones no había encontrado un sitio tan sencillo, pero con tan buen contenido.
Escrito por Diego Tapia R. (28/11/2007 08:14 PM)
todo esta perfecto, no lo puedo creer
Escrito por dino (05/10/2007 04:06 PM)
Fantástico artículo, muy didáctico y anteponiendo el conocimiento al copiar-pegar de código. Enhorabuena.
Escrito por Pau (24/08/2007 03:49 PM)
Buenisimo Erwin!Muy agradecido! Tengo que pedir un gran favor, será que puedes indicar como debemos hacer para poder usar tu captcha en la plataforma de foros phpBB2? Te paso un link que encontré, pero indica como personalizar para otro script de captcha libre (freecap), tal vez te facilite el análisis. http://www.pdaexpertos.com/visitar.php?url=http://www.matthewleverton.com/howto/phpBB2-captcha.html El phpBB es usado por muchas personas con poco conocimiento de programación, scripts o php, por lo que podrías lanzar esto como un "mod" y facilitar la lucha contra el spam a muchos admins de phpBB. Saludos
Escrito por DHCP (12/04/2007 02:42 PM)
Gracias, pero la idea no es hacer un "mod", es que cada persona se haga uno. No tendría sentido colocar este captcha como viene (por lo sencillo) sin hacer algunos retoques y adaptarlo de forma exclusivo sólo para tí con el fin de evitar el spam que se enfoca en ciertas soluciones populares. Intenta modificarlo e integrarlo y pregúntame las dudas que puedas tener en ese proceso
Escrito por Erwin Ried (12/04/2007 05:07 PM)
Hola... se ve hasta más sencillo que el captcha de blogger.com XD Saludos!!!
Escrito por Alejandro (09/04/2007 11:27 AM)

Copyright © 2013 por Erwin Ried.