Completely Automated Public Turing Test to Tell Computers and Humans Apart“ "Test público de Turing completamente automatizado para mantener separados los ordenadores y las personas“. Ejemplos: http://www.eugenio-soler-galan.es/julio Trabajo de investigación II (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán Profesor: Julio Cesar Hernández Castro Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán INDICE 1. MOTIVACIÓN..................................................................................pág. 3 2. INTRODUCCIÓN.............................................................................pág. 4 3. CUANDO DEBE UTILIZARSE UN CAPTCHA ................................pág. 5 4. CLASIFICACIÓN DE LOS CAPTCHAs ...........................................pág. 7 5. ALGUNOS EJEMPLOS COMUNES.............................................pág. 10 6. CREACIÓN DE UN CAPTCHA PASO A PASO (PHP)..................pág. 11 7. CONCLUSIONES ..........................................................................pág. 12 8. EJEMPLOS ...................................................................................pág. 13 a. EJEMPLO1 .........................................................................pág. 14 b. EJEMPLO2 .........................................................................pág. 17 c. EJEMPLO3 .........................................................................pág. 20 d. EJEMPLO4 .........................................................................pág. 25 9. BIBLIOGRAFÍA..............................................................................pág. 31 Junio de 2007 Página 2 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán MOTIVACIÓN No solo podemos tener saturación en nuestro buzón de correo por culpa de esa correo basura que recibimos, y para el cual se buscan remedios tales como filtros, reglas,.. Sino que podemos sufrir saturación cuando una “maquina” envía formularios como si de un ser humana se tratara, por ejemplo para crear cuentas de correo electrónico. Afortunadamente, existe una protección contra esta molesta práctica los denominados CAPTCHA. Este sistema nació para proteger los servicios Web, de los usuarios abusivos. Los CAPTCHA más sencillos consisten en mostrar la imagen de un texto y pedir al visitante que teclee dicho texto en un campo de entrada. Cosa que en principio solo puede hacer un ser humano y no una máquina, pero basta crear una máquina que sea capaz de imitar el comportamiento humano en este aspecto concreto. Por tanto no parece que los CAPTCHAs puedan suponer por si solos una barrera contra este abuso ya que siempre podemos crear una máquina que resuelve el problema. Lo que verdaderamente no se podría crear en una máquina que resolviese cualquier CAPTCHA que un humano fuese capaz de pensar, por tanto si anidamos CAPTCHAs y mejor aún tenemos una gran colección de la cual cada vez hacemos pasar dos o o tres diferentes sería bastante difícil que una máquina fuese capaz de reconocerlos todos ellos, pero insisto solo es una barrera, para que verdaderamente fuese eficaz el test tendría que ser diferente cada vez. Junio de 2007 Página 3 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán INTRODUCCIÓN En los últimos años de la década de los noventa surgieron empresas de Internet que daban espacio gratuito, ya fuese Web, de correo u otros. Los spammers no son los únicos que abusan de los servicios de la red, también los webmasters maliciosos pueden aprovecharse de los servicios de terceros. Por ejemplo supongamos que se tiene un Web desde donde se ofrecen cotizaciones de bolsa. Un competidor podría hacer un programa que se conectara a sus páginas, extraería la información, y la presentaría en su Web como propia, y todo ello sin ningún coste. Para evitar que una máquina se hiciera pasar por una persona, en el años 2000, la Universidad de Carnige Mellon se puso a trabajar en una solución a este problema. Como resultado su equipo fue el que inventó los CAPTCHA (http://www.captcha.net), que son las siglas de "Completely Automated Public Turing Test to Tell Computers and Humans Apart“, palabras inglesas que traducidas literalmente significan: "Test público de Turing completamente automatizado para mantener separados los ordenadores y las personas“. La idea de la que partieron es sumamente simple: incluir en una página Web un test que un programa no sea capaz de solucionar, que solo lo pueda pasar un ser humano. La idea original de crear este tipo de tests la planteó Alan Turing, de ahí que su nombre aparezca en la definición de CAPTCHA. Su objetivo era poner a prueba los programas de inteligencia artificial, para determinar si eran realmente inteligentes. A la hora de diseñar un CAPTCHA hay que pensar en un tipo de problema que informáticamente sea imposible, o prácticamente imposible de solucionar, pero que para un ser humano resulte trivial o casi trivial. Junio de 2007 Página 4 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán CUÁNDO DEBE UTILIZARSE UN CAPTCHA En encuestas online: Son especialmente susceptibles a los robots. En la actualidad la mayoría de las encuestas realizadas por internet no tienen el menor rigor científico, pues se pueden contestar desde la misma IP tantas veces como se desee y además puedo tener robot que lo hagan, sin meternos para nada en el campo de la Estadística. En cuentas de correo gratuito: Algo parecido sucede con las cuentas de correo pero como puede verse en la sección algunos ejemplos comunes la mayoría de empresas incorporan CAPTCHA. Yahoo! fue la primera empresa en utilizar captcha. Para esconder información a los buscadores: Se trata de una aplicación muy reciente y consiste en privar a los buscadores (robots en definitiva) de determinadas informaciones que no se quieren exponer a la vista pública, mediante la interposición de un captcha. Contra los gusanos: Se están comenzando a desarrollar sistemas, conocidos como Test Captchatm, para evitar este tipo de virus que se difunde por correo electrónico. El método se basa en responder a la llegada de un email sospechoso con el envío de un captcha a su emisor, que forzosamente debe descifrar para que su mensaje sea aceptado. Es la manera de asegurarse de que hay un humano tras la máquina. Para prevenir ataques de diccionarios: Los robots pueden utilizar diccionarios online para generar palabras al azar y así acertar los captcha. El Test Captchatm está siendo utilizado por estos diccionarios para frenar este tipo de intromisiones. Junio de 2007 Página 5 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán ¿Son infalibles los captcha? Como todo sistema de seguridad los captcha no son infalibles, pero dan mucho trabajo a los que intentan romperlos mediante robots. Aún así, los piratas informáticos han desarrollado algunos trucos para engañar a un captcha. El más popular consiste en utilizar el captcha de un correo gratuito en otro sistema de registro para que un humano lo resuelva. Para ello, los robots utilizan una web a la que un usuario desee entrar (una web pornográfica generalmente) y que se llama web-anzuelo. Cuando el usuario de esta página inicia el proceso de registro se le impone el captcha del correo gratuito como requisito. Cuando lo resuelve, el robot se lleva el código descifrado a la página de correo gratuito de origen y entra en ella. Esto es, los usuarios del web-anzuelo son usados sin que tengan conocimiento de ello para resolver captchas de otras webs. La alternativa de Gmail Un método alternativo a los captcha es el que utiliza el correo de Google y consiste en crear una comunidad de usuarios formada exclusivamente por invitados. Se basa en que para obtener una cuenta de correo de Gmail es necesario ser invitado por un usuario ya dado de alta. Este cursa la invitación y el aspirante la recibe vía correo electrónico. Una vez abierto el mensaje, el aspirante se dirige a una página creada para él desde donde puede configurar su nueva cuenta. De este modo se evitaría la intromisión de robots. En algunas ocasiones Gmail también interpone captacha si detecta alguna irregularidad, como por ejemplo que se acceda al correo desde un puerto diferente al habitual. Junio de 2007 Página 6 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán CLASIFICACIÓN DE LOS CAPTCHAs Podríamos clasificarlos en lo siguientes tipos: 1.- Lectura de texto simple: Consiste en mostrar la imagen de un texto o una serie de números, adecuadamente deformada, para que un OCR no pueda leerla, y se pide al usuario que teclee dicha serie en un campo de entrada de datos. Actualmente, este es el único tipo que se usa de forma masiva, porque es el más sencillo tanto de programar como de resolver (resolver por parte de un humano, se entiende). El mayor problema de este tipo de CAPTCHA es que es fácil romperlos, sobre todo si se conoce el código de éstos. Actualmente, diversos equipos de investigadores han anunciado que han desarrollado programas que son capaces de leer estos CAPTCHAs. De todas formas, las tecnologías que utilizan son computacionalmente muy costosas, por lo que, a corto plazo, es poco probable que se incorporen a los programas para spammers. Imagen obtenida de www.eugenio-soler-galan.es/julio/c1/ 2.- Lectura de texto compleja: Se trata de una variante del anterior. En esta ocasión la imagen muestra varios textos, que además de deformados están superpuestos entre si, y el usuario debe identificarlos y teclearlos todos. Esta técnica también puede romperse utilizando los mismos procedimientos que en el caso ya visto, pero hacerlo requiere de una capacidad informática muchísimo mayor que la del punto 1, por lo que a un spammer le resultaría antieconómico romperla. Junio de 2007 Página 7 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán 3.- Completar una serie lógica: También un CAPTCHA visual, pero en esta ocasión la imagen muestra una serie lógica que el usuario debe completar. Su gran ventaja es que, para romperlo, no basta con identificar los objetos que aparecen en la imagen, es preciso además comprender su contenido. Para que este CAPTCHA sea efectivo es preciso hacer un programa que sea capaz de generar una gran cantidad de series lógicas diferentes, algo que es bastante más difícil de lo que puede parecer a primera vista. 4.- Imágenes múltiples: Se muestran al usuario varias fotografías, y él debe buscar un objeto que están presente en todas ellas, pero presente. Por ejemplo, se muestran al usuario cuatro fotos en contestos diferentes pero en las que aparece una sonrisa como elemento común. Este tipo de CAPTCHA puede ser bastante eficaz, por lo que es poco probable que se empiecen a utilizar antes de que los que son más simples hayan conseguido romperse. Junio de 2007 Página 8 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán 5.- Reconocimiento de audio: Es como los anteriores, pero el texto, en lugar de mostrarse en pantalla, se recita por el altavoz del ordenador. Actualmente la tecnología de reconocimiento de audio esta muy avanzada, de modo que, aunque no hay noticias de que se haya logrado romper este CAPTCHA, es de suponer que logrará en los próximos años. Junio de 2007 Página 9 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán ALGUNOS EJEMPLOS COMUNES 1.- www.hotmail.com al crearte una cuenta de correo gratuita 2.- www.terra.es al crearte una cuenta de correo gratuita 3.- www.yahoo.com al crearte una cuenta de correo gratuita Junio de 2007 Página 10 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán CREACIÓN DE UN CAPTCHA PASO A PASO (PHP) En general podemos decir que para crear un CAPTCHA son necesarios los siguientes elementos: 1. Aleatoriedad, a la hora de elegir letras, sucesiones o imágenes 2. Mostrar esos elementos através de una imagen 3. Paso de esos valores entre los diferentes elementos del programa sin que puedan ser vistos. 4. El formulario del que va a formar parte el CAPTCHA 5. El código que introduce el usuario 6. Y el programa que valida lós códigos (el que introduce el usuario y el almacenado) Normalmente se trabaja con tres ficheros: index.php, crear_imagen.php y verificar.php. Los elementos 1, 3, 4 y 5 pertenecen al documento llamado index.php El elemento 2 pertenece a documento crear_imagen.php El elemento 6 pertenece al documento verficar.php En el documento index.php tendremos el formulario en html, y en php elejiremos de forma aleatoria los caracteres, sucesiones o dibujo, y que se pasaran mediante el uso de sesiones al documento crear_imagen.php que representará esta información de forma gráfica en la pantalla, por último el documento verificar.php lo que hará será verificar que lo que el usuario ha introducido en index.php coincide con lo que se ha calculado de forma aleatoria. Mas adelante podrán observarse cuatro ejemplos en lo que se detalla con toda precisión cada linea del código. Estos ejemplos pueden verse y descargarse en: http://www.eugenio-soler-galan/julio Junio de 2007 Página 11 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán CONCLUSIONES El problema del SPAM ha alcanzado unos niveles de gravedad y generalización que resulta obligado tomar medidas; en este sentido los CAPTCHA son la única protección realmente eficaz para evitar el SPAM en los foros de debate y el uso abusivo de los servicios que requieren suscripción. La mejor prueba de ello es que los servicios más populares de la Red los tienen implementados desde hace años. De hecho, las aplicaciones más populares, como pueda ser el programa de foros phpBB (http//www.phpbb.com/community/) o el generador de portales phpnuke (http//www.phpnuke.org) ya incluyen la validación por CAPTCHA en sus formularios. Todas estas aplicaciones utilizan el sistema de lectura de texto simple, ya que aunque se sabe que es posible romperlo, todavía no se han desarrollado programas capaces de hacerlo, por lo que sigue siendo un procedimiento seguro. El SPAM ha dejado de ser un problema exclusivo del correo electrónico, y se ha propagando también a los foros de debate de las páginas web. Los CAPTCHA nacieron para proteger los servicios web de los usuarios Junio de 2007 Página 12 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán EJEMPLOS Se han realizado 4 ejemplos siguiendo la clasificación: Ejemplo1: Lectura de texto simple Ejemplo2: Lectura de texto compleja Ejemplo3: Completar una serie lógica Ejemplo4: Imágenes múltiples: Pueden verse estos ejemplos y descargarlos en el siguiente sitio web: http://www.eugenio-soler-galan.es/julio Junio de 2007 Página 13 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán EJEMPLO 1 Lo primero que necesitamos para mostrar un CAPTCHA es crear aleatoriamente la secuencia de caracteres que va aparecer en la imagen y guardarla en una variable de sesión ($_SESSION) para comprobarla luego con la ingresada por el usuario, eso se hace en el fichero: index.php <? //Esta es la parte escrita en PHP del formulario session_start();//Inicializamos una nueva sesión, si quisieramos saber el identificador de la sesión lo podríamos hacer con session_id(), nos devuelve un número de 16 byte y hasta que no cerremos la sesion este será nuestro identificador de sesion $captcha_texto = "";//Inicializamos la variable que va a contener 6 caracteres a vacio for ($i = 1; $i <= 6; $i++)//Introducimos 6 caracteres de forma aleatoria en dicha variable $captcha_texto .= caracter_aleatorio(); $HTTP_SESSION_VARS["captcha_texto_session"] = $captcha_texto;//pasamos por variable de sesión los 6 caracteres obtenidos //Función aleatoria con la que obtendremos los caracteres function caracter_aleatorio() { mt_srand((double)microtime()*1000000);//Genera una semilla a partir del tiempo actual de la maquina en segundos con decimales hasta las micra al multiplicarlo por 10E6 obtenemos un numero entero que sirve de semilla a mt_srand. $valor_aleatorio = mt_rand(1,3);//Ahora obtenemos un número entre 1 y 3. De esta forma es tan probable obtener un caracter en minúsculas como en mayúsculas o digitos del 0 al 9 switch ($valor_aleatorio) { case 1: $valor_aleatorio = mt_rand(97, 122); //Genera letras en minúsculas break; case 2: $valor_aleatorio = mt_rand(48, 57); //Genera digitos del 0 al 9 break; case 3: $valor_aleatorio = mt_rand(65, 90); //Genera letras en mayúsculas break; } return chr($valor_aleatorio);//El caracter que devuelve la llamada a dicha función aleatoria } //fin de la función aleatoria ?> <!-- A partir de aquí lo que tenemos es el formulario que visualizamos escrito en html --> <html> <head> <title>Captcha tipo 1: ejemplo 1</title> </head> Junio de 2007 Página 14 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán <body style="font-family: Verdana, Arial, Helvetica, sans-serif ; font-size: 12px"> <p>Captcha tipo 1: ejemplo 1</p> <hr size="1" width=250 align=left noshade="noshade" /> <!-- Hacemos la llamada a crear_imagen.php para que aparezca como imagen los 6 caracteres elejidos de forma aleatoria anteriormente --> <p align="left"><img src="crear_imagen.php?<?php echo SID; ?>" /></p> <!-- Un formulario cualquiera en html, donde solo aparece un campo tipo texto donde introducimos los caracteres que creemos están en la imagen --> <form action="verificar.php" method="POST"> <p>Por favor introduzca el codigo que ve en la imagen:</p> <p><input name="texto_ingresado" type="text" id="texto_ingresado" size="8" /> <input type="submit" name="Submit" value="OK" /></p> </form> <p><b>Nota:</b> El codigo diferencia mayuculas y minisculas</p> </body> </html> Otra parte importante es la creación de la imagen que se visualiza y que solo un ser humano debería ser capaz de interpretar. Debemos crear la imagen mostrando los caracteres creados anteriormente y guardados en la variable de sesion... Crear_imagen.php <? //1 definimos el tamaño de la imagen 150px de ancho por 40px de alto $captcha_imagen = imagecreate(150,40); //2 definimos el color negro que usaremos como fondo $color_negro = imagecolorallocate ($captcha_imagen, 0, 0, 0); //3 definimos el color blanco que usaremos como color del texto $color_blanco = imagecolorallocate ($captcha_imagen, 255, 255, 255); //4 rellena la imagen creada en el paso_1 del color definido en el paso_2, desde la posición (0,0) de dicha imagen imagefill($captcha_imagen, 0, 0, $color_negro); session_start();//Se reabre la sesión creada en index.php $captcha_texto = $HTTP_SESSION_VARS["captcha_texto_session"];//recupero los 6 caracteres generados aleatoriamente /*Dibuja el caracter transmitido mediante el array $captcha_texto en la imagen definida en el paso_1 con su esquina superior izquierda en 20, 13 y usando como fuente el tipo 4 y color de texto blanco*/ /*lo mismo para los otros 5 caracteres*/ imagechar($captcha_imagen, 4, 20, 13, $captcha_texto[0] ,$color_blanco); imagechar($captcha_imagen, 5, 40, 13, $captcha_texto[1] ,$color_blanco); imagechar($captcha_imagen, 3, 60, 13, $captcha_texto[2] ,$color_blanco); imagechar($captcha_imagen, 4, 80, 13, $captcha_texto[3] ,$color_blanco); imagechar($captcha_imagen, 5, 100, 13, $captcha_texto[4] ,$color_blanco); imagechar($captcha_imagen, 3, 120, 13, $captcha_texto[5] ,$color_blanco); header("Content-type: image/jpeg"); imagejpeg($captcha_imagen); ?> Junio de 2007 Página 15 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán Y por último la verificación, lo que nos queda por delante es verificar que el código ingresado por el usuario coincida con el CAPTCHA creado, esto lo hacemos en el archivo: verificar.php <? session_start();//Continua con la misma sesión abierta anteriormente en index.php $texto_ingresado = $HTTP_POST_VARS["texto_ingresado"];//valor mandado através del formulario por el usuario $captcha_texto = $HTTP_SESSION_VARS["captcha_texto_session"];//valor real que se manda através de las variables de sesión if ($texto_ingresado == $captcha_texto) {//Si ambos coinciden "Soy un ser humano" y si no "puedo ser una máquina intentando aparentar serlo" echo "El codigo es correcto."; } else { echo "No ha escrito correctamente el codigo. Por favor intentelo de nuevo!"; } session_unset();//Elimina todas las variables de sesión session_destroy();//Elimina la sesión ?> Junio de 2007 Página 16 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán EJEMPLO 2 Es similar al ejemplo 1, pero damos cierta aletoriedad tanto a la posición de los caracteres, como a su tamaño y color., eso se hace en el fichero: index.php <? //El formulario es identico al del ejemplo 1, solo varía el nombre session_start(); $captcha_texto = ""; for ($i = 1; $i <= 6; $i++) $captcha_texto .= caracter_aleatorio(); $HTTP_SESSION_VARS["captcha_texto_session"] = $captcha_texto; function caracter_aleatorio() { mt_srand((double)microtime()*1000000); $valor_aleatorio = mt_rand(1,3); switch ($valor_aleatorio) { case 1: $valor_aleatorio = mt_rand(97, 122); break; case 2: $valor_aleatorio = mt_rand(48, 57); break; case 3: $valor_aleatorio = mt_rand(65, 90); break; } return chr($valor_aleatorio); } ?> <html> <head> <title>Captcha tipo 2: ejemplo 1</title> </head> <body style="font-family: Verdana, Arial, Helvetica, sans-serif ; font-size: 12px"> <p>Captcha tipo 2: ejemplo 1</p> <hr size="1" width=250 align=left noshade="noshade" /> <p align="left"><img src="crear_imagen.php?<?php echo SID; ?>" /></p> <form action="verificar.php" method="POST"> <p>Por favor introduzca el codigo que ve en la imagen:</p> <p><input name="texto_ingresado" type="text" id="texto_ingresado" size="8" /> <input type="submit" name="Submit" value="OK" /></p> </form> <p><b>Nota:</b> El codigo diferencia mayuculas y minisculas</p> </body> </html> Junio de 2007 Página 17 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán crear_imagen <? //Se define esta función aleatorio ya que queremos dar mas aleatoriedad a la imagen y vamos a utilizar el código varias veces. su funcionamiento queda claramente descrito en el ejemplo1 function va($x,$y) { mt_srand((double)microtime()*1000000); $valor_aleatorio = mt_rand($x,$y); return ($valor_aleatorio); } //1 definimos el tamaño de la imagen 225px de ancho por 60px de alto $captcha_imagen=imagecreate(225,60); //2 definimos el color del fondo pero esta vez de forma aleatoria $x=va(128,255);//cantidad de rojo con una intensidad entre 128 y 255. $y=va(128,255);//cantidad de verde con una intensidad entre 128 y 255. $z=va(128,255);//cantidad de azul con una intensidad entre 128 y 255. $color_fondo = imagecolorallocate ($captcha_imagen,$x,$y,$z);//aquí es donde se crea el color del fondo //3 definimos el color del texto basandonos en el color del fondo para que haya contraste if ($x>127) $x=0; else $x=255; if ($y<=127) $y=$y+128; else $y=$y-128; if ($z<=127) $z=$z+128; else $z=$z-128; $color_texto = imagecolorallocate ($captcha_imagen,$x,$y,$z);//aquí es donde se crea el color del texto //4 rellena la imagen creada en el punto_1 con el color de fondo definido en el punto_2, desde la posición (0,0) de dicha imagen imagefill($captcha_imagen, 0, 0, $color_fondo); //5 creamos un rectangulo a una distancia del 10 puntos del borde para que quede mas difuso el texto imagerectangle ($captcha_imagen, 10, 10, 215, 50, $color_texto); //6 creamos un poligono irregular de 4 lados elegidos de forma aleatoria para que quede mas difuso el texto $esquinas=array(va(0,225),va(0,60),va(0,225),va(0,60),va(0,225),va(0,60),va(0,225),va(0,60),v a(0,225),va(0,60)); imagepolygon ($captcha_imagen, $esquinas, 4, $color_texto); //7 recuperamos la sesión que abrimos en index.php session_start(); Junio de 2007 Página 18 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán //8 recuperamos el texto que queremos representar en dicha imagen $captcha_texto = $HTTP_SESSION_VARS["captcha_texto_session"]; /*9 Situamos en la imagen, con un tamaño entre 15 y 22 puntos y una rotación de entre -30º y 30º en el intervalo [23,37] la primera letra en cuanto a la distancia horizontal y en el intervalo [25,45] en cuanto a la distancia vertical, con el color del texto previamente elejido, con la fuente /fuentes/11.ttf (que también cabría la posibilidad de que fuese elejida aleatoriamente. el caracter que hemos pasado atraves de la variable de sesión */ Imagettftext($captcha_imagen, va(15,22), va(-30,30), 30+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[0]); //10 Lo mismo se hace para el resto de los caracteres, lo único que varia es el intervalo horizontal. Imagettftext($captcha_imagen, va(15,22), va(-30,30), 60+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[1]); Imagettftext($captcha_imagen, va(15,22), va(-30,30), 90+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[2]); Imagettftext($captcha_imagen, va(15,22), va(-30,30), 120+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[3]); Imagettftext($captcha_imagen, va(15,22), va(-30,30), 150+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[4]); Imagettftext($captcha_imagen, va(15,22), va(-30,30), 180+va(-7,7), 35+va(-10,10), $color_texto,"./fuentes/11.ttf", $captcha_texto[5]); header("Content-type: image/jpeg"); imagejpeg($captcha_imagen); ?> Verificar <? //Es identico al ejemplo de captcha tipo 1. session_start(); $texto_ingresado = $HTTP_POST_VARS["texto_ingresado"]; $captcha_texto = $HTTP_SESSION_VARS["captcha_texto_session"]; if ($texto_ingresado == $captcha_texto) { echo "El codigo es correcto."; } else { echo "No ha escrito correctamente el codigo. Por favor intentelo de nuevo!"; } session_unset(); session_destroy(); ?> Junio de 2007 Página 19 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán EJEMPLO 3 En este ejemplo lo que vamos a utilizar son diferentes tipos de sucesiones, cuantos más tipos mejor, en este caso tenemos cuatro tipos, sucesiones aritméticas, geométricas, de días de la semana (aritméticas) y meses (aritméticas) index.php <? //Esta es la parte escrita en PHP del formulario session_start();//Inicializamos una nueva sesión, si quisieramos saber el identificador de la sesión lo podríamos hacer con session_id(), nos devuelve un número de 16 byte y hasta que no cerremos la sesion este será nuestro identificador de sesion function aleatorio($linferior,$lsuperior)//Función aleatoria con la que obtendremos que tipo de sucesión elejimos y los terminos de dicha sucesión. Los límites inferior y superior nos indican entre que valores se obtienen numeros aleatorios, ambos incluidos. { mt_srand((double)microtime()*1000000);//Genera una semilla a partir del tiempo actual de la maquina en segundos con decimales hasta las micra. Al multiplicarlo por 10E6 obtenemos un numero entero que sirve de semilla a mt_srand. $valor_aleatorio = mt_rand($linferior,$lsuperior);//Ahora obtenemos un número entre ese limite inferior y superior. return ($valor_aleatorio);//se devuelve dicho valor } //convierte un numero entre 0 y 6 en un día de la semana function convertirdia($numero) { switch ($numero) { case 0: return("lunes"); break; case 1: return("martes"); break; case 2: return("miércoles"); break; case 3: return("jueves"); break; case 4: return("viernes"); break; case 5: return("sábado"); break; case 6: return("domingo"); break; } } Junio de 2007 Página 20 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán //convierte un número entre 0 y 11 en un mes function convertirmes($numero) { switch ($numero) { case 0: return("enero"); break; case 1: return("febrero"); break; case 2: return("marzo"); break; case 3: return("abril"); break; case 4: return("mayo"); break; case 5: return("junio"); break; case 6: return("julio"); break; case 7: return("agosto"); break; case 8: return("septiembre"); break; case 9: return("octubre"); break; case 10: return("noviembre"); break; case 11: return("diciembre"); break; } } //tipo de secuencia lógica. Cuantas mas secuencias lógicas mas dificultad. switch (aleatorio(1,4)) { case 1: //lineal-El primer término está entre -79 y 79 y el incremento entre -10 y 10 $termino[0]=aleatorio(-79,79); $t[0]=strval($termino[0]); $incr=aleatorio(-10,10); for ($i = 1; $i <= 3; $i++) Junio de 2007 Página 21 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán { $termino[$i]=$termino[$i-1]+$incr; $t[$i]=strval($termino[$i]); } break; case 2: //geometrica-El primer término está entre -10 y 10 y la razon entre -4 y 4, excluyendo el 0 $termino[0]=aleatorio(-10,10); $t[0]=strval($termino[0]); $incr=aleatorio(1,4); if (aleatorio(0,1)==0) $incr=-$incr; for ($i = 1; $i <= 3; $i++) { $termino[$i]=$termino[$i-1]*$incr; $t[$i]=strval($termino[$i]); } break; case 3: //lineal z7(dias de la semana) Es un sucesión lineal cíclica. $termino[0]=aleatorio(0,6); $t[0]=convertirdia($termino[0]); $incr=aleatorio(0,6); for ($i = 1; $i <= 3; $i++) { $termino[$i]=($termino[$i-1]+$incr)%7; $t[$i]=convertirdia($termino[$i]); } break; case 4: //lineal z12(meses). Es una sucesión lineal cíclica. $termino[0]=aleatorio(0,11); $t[0]=convertirmes($termino[0]); $incr=aleatorio(0,11); for ($i = 1; $i <= 3; $i++) { $termino[$i]=($termino[$i-1]+$incr)%12; $t[$i]=convertirmes($termino[$i]); } break; } $HTTP_SESSION_VARS["captcha_texto_session"] = $t; ?> <!-- A partir de aquí lo que tenemos es el formulario que visualizamos escrito en html --> <!-- Para saber más, ver Captcha tipo 1: ejemplo 1 --> <html> <head> <title>Captcha tipo 3: ejemplo 1</title> </head> <body style="font-family: Verdana, Arial, Helvetica, sans-serif ; font-size: 12px"> <p>Captcha tipo 3: ejemplo 1</p> <hr size="1" width=250 align=left noshade="noshade" /> <p align="left"><img src="crear_imagen.php?<?php echo SID; ?>" /></p> <form action="verificar.php" method="POST"> Junio de 2007 Página 22 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán <p>Por favor introduzca el siguiente termino de la sucesión:</p> <p><input name="texto_ingresado" type="text" id="texto_ingresado" size="11" /> <input type="submit" name="Submit" value="OK" /></p> </form> </body> </html> crear_imagen <? //Se define esta función aleatorio ya que queremos dar mas aleatoriedad //a la imagen y vamos a utilizar el código varias veces. //su funcionamiento queda claramente descrito en el ejemplo1 function va($x,$y) { mt_srand((double)microtime()*1000000); $valor_aleatorio = mt_rand($x,$y); return ($valor_aleatorio); } //1 recuperamos la sesión que abrimos en index.php session_start(); //2 recuperamos el texto que queremos representar en dicha imagen $t = $HTTP_SESSION_VARS["captcha_texto_session"]; //3 definimos el tamaño de la imagen 300x70(tipo=1) para números y 600x140(tipo=2) para texto if (strlen($t[0])>4) $tipo=2; else $tipo=1; $captcha_imagen=imagecreate(300*$tipo,70*$tipo); //4 definimos el color que usaremos como fondo pero esta vez de forma aleatoria $x=va(128,255);//cantidad de rojo con una intensidad entre 128 y 255. $y=va(128,255);//cantidad de verde con una intensidad entre 128 y 255. $z=va(128,255);//cantidad de azul con una intensidad entre 128 y 255. $color_fondo = imagecolorallocate ($captcha_imagen,$x,$y,$z);//aquí es donde se crea el color del fondo //5 definimos el color del texto basandonos en el color del fondo para que haya contraste if ($x<=127) $x=0; else $x=255; /* $x=$x+128; else $x=$x-128;*/ if ($y<=127) $y=$y+128; else $y=$y-128; Junio de 2007 Página 23 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán if ($z<=127) $z=$z+128; else $z=$z-128; $color_texto = imagecolorallocate ($captcha_imagen,$x,$y,$z); //6 rellena la imagen creada en el punto_3 con el color de fondo definido en el punto_4, desde la posición (0,0) de dicha imagen imagefill($captcha_imagen, 0, 0, $color_fondo); /*7 Situamos en la imagen, con un tamaño entre 30 y 40 puntos y una rotación de entre 30º y 30º en un intervalo que va a depender del tipo y que lleva además un poco de aleatoriedad tanto en horizontal como en vertical, con el color del texto previamente elejido, con la fuente /fuentes/11.ttf (que también cabría la posibilidad de que fuese elejida aleatoriamente. el caracter que hemos pasado atraves de la variable de sesión */ Imagettftext($captcha_imagen, va(30,40), va(-30,30), 25+va(-10,10), 48*$tipo+va(-10,10), $color_texto,"./fuentes/11.ttf", trim(strval($t[0]))); //8 Lo mismo se hace para el resto, lo único que varia es el intervalo horizontal. Imagettftext($captcha_imagen, va(30,40), va(-30,30), 115*$tipo+va(-10,10), 48*$tipo+va(10,10), $color_texto,"./fuentes/11.ttf", trim(strval($t[1]))); Imagettftext($captcha_imagen, va(30,40), va(-30,30), 205*$tipo+va(-10,10), 48*$tipo+va(10,10), $color_texto,"./fuentes/11.ttf", trim(strval($t[2]))); header("Content-type: image/jpeg"); imagejpeg($captcha_imagen); ?> Verificar <? session_start();//Continua con la misma sesión abierta anteriormente en index.php $texto_ingresado = $HTTP_POST_VARS["texto_ingresado"];//valor mandado através del formulario por el usuario $t = $HTTP_SESSION_VARS["captcha_texto_session"];//valor real que se manda através de las variables de sesión if ($texto_ingresado == trim(strval($t[3]))) {//Si ambos coinciden "Soy un ser humano" y si no "puedo ser una máquina intentando aparentar serlo" echo "El codigo es correcto."; } else { echo "No ha escrito correctamente el codigo. Por favor intentelo de nuevo!"; } session_unset();//Elimina todas las variables de sesión session_destroy();//Elimina la sesión ?> Junio de 2007 Página 24 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán EJEMPLO 4 En este ejemplo se utilizan imágenes elejidas aleatoriamente pero con algo en común, primero se elije el tipo y luego las imágenes dentro de ese tipo. index.php <? //Esta es la parte escrita en PHP del formulario session_start();//Inicializamos una nueva sesión, si quisieramos saber el identificador de la sesión lo podríamos hacer con session_id(), nos devuelve un número de 16 byte y hasta que no cerremos la sesion este será nuestro identificador de sesion mt_srand((double)microtime()*1000000);//Genera una semilla a partir del tiempo actual de la maquina en segundos con decimales hasta las micra. Al multiplicarlo por 10E6 obtenemos un numero entero que sirve de semilla a mt_srand. $tipo=trim(strval(mt_rand(1,16)));//elejimos el tipo de foto al azar, entre 1 y 16. $imagen="";//inicializamos a vacio la variable imagen para ir guardando después las cuatro imagenes que se van a mostrar $i=1;//Vamos a seleccionar dentro de este tipo 4 fotos de entre las 8 posibles. while($i<=4) { $fotoaux=mt_rand(1,8); $contaaux=1; $existe=0; while (($contaaux<$i)&&($encontrado==0)) { if ($fotoaux==$foto[$contaaux]) $encontrado=1; else $contaaux=$contaaux+1; } if ($encontrado==0) { $foto[$i]=$fotoaux; $imagen.=str_pad($tipo,2,"0",STR_PAD_LEFT).str_pad(trim(strval($foto[$i])),2,"0",STR_PAD_LEFT); $i=$i+1; } else $encontrado=0; } //guardado en esta variable de sesión el nombre de los archivos que contienen la imagen $HTTP_SESSION_VARS["captcha_texto_session"] = $imagen; ?> <html> <head> <title>Captcha tipo 4: ejemplo 1</title> </head> <body style="font-family: Verdana, Arial, Helvetica, sans-serif ; font-size: 12px"> Junio de 2007 Página 25 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán <p>Captcha tipo 4: ejemplo 1</p> <hr size="1" width=250 align=left noshade="noshade" /> <!-- La única diferencia con los index de los ejemplos de tipo 1, 2 y 3. Es que en esta ocasión tenemos que crear cuatro imagenes diferentes por lo que hacemos cuatro llamadas diferentes, aunque el código de crear_imagenX.php es casi igual salvo en la imagen en la que se tienen que fijar en caqa caso. --> <table> <tr> <td><img src="crear_imagen1.php?<?php echo SID; ?>"></td> <td><img src="crear_imagen2.php?<?php echo SID; ?>"></td> </tr> <tr> <td><img src="crear_imagen3.php?<?php echo SID; ?>"></td> <td><img src="crear_imagen4.php?<?php echo SID; ?>"></td> </tr> </table> <form action="verificar.php" method="POST"> <!-- Aquí están los tipos de las imagenes que se pueden seleccionar --> <p>Por favor introduzca la palabra que representa las imagenes:</p> <p> <SELECT NAME="texto_ingresado"> <OPTION>amor <OPTION>arbol <OPTION>balon <OPTION>banco <OPTION>barco <OPTION>bota <OPTION>casa <OPTION>dinosaurios <OPTION>isla <OPTION>matematicas <OPTION>moneda <OPTION>oveja <OPTION>pajaro <OPTION>radio <OPTION>raqueta <OPTION>risa </SELECT> <input type="submit" name="submit" value="OK" /></p> </form> </body> </html> crear_imagen1 <? Header("Content-type: image/jpeg"); session_start();//continuamos la sesión abierta en index.php $fichero = $HTTP_SESSION_VARS["captcha_texto_session"];//recuperamos el nombre de las imagenes. Donde $fichero[0].$fichero[1] es el tipo y $fichero[2].$fichero[3] es la imagen dentro de ese tipo $nueva1=imagecreatefromjpeg("imagenes/".$fichero[0].$fichero[1].$fichero[2].$fichero[3].".jpg"); Junio de 2007 Página 26 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán imagejpeg($nueva1);//creamos una imagen jpg con una calidad del 75%(por defecto) y no se cree guarda en ningún archivo. Imagedestroy($nueva1);//se libera la memoría utilizada en la creación de la imagen. ?> crear_imagen2 <? Header("Content-type: image/jpeg"); session_start();//continuamos la sesión abierta en index.php $fichero = $HTTP_SESSION_VARS["captcha_texto_session"];//recuperamos el nombre de las imagenes. Donde $fichero[4].$fichero[5] es el tipo y $fichero[6].$fichero[7] es la imagen dentro de ese tipo $nueva1=imagecreatefromjpeg("imagenes/".$fichero[4].$fichero[5].$fichero[6].$fichero[7].".jpg"); imagejpeg($nueva1);//creamos una imagen jpg con una calidad del 75%(por defecto) y no se cree guarda en ningún archivo. Imagedestroy($nueva1);//se libera la memoría utilizada en la creación de la imagen. ?> crear_imagen3 <? Header("Content-type: image/jpeg"); session_start();//continuamos la sesión abierta en index.php $fichero = $HTTP_SESSION_VARS["captcha_texto_session"];//recuperamos el nombre de las imagenes. Donde $fichero[8].$fichero[9] es el tipo y $fichero[10].$fichero[11] es la imagen dentro de ese tipo $nueva1=imagecreatefromjpeg("imagenes/".$fichero[8].$fichero[9].$fichero[10].$fichero[11].".jpg"); imagejpeg($nueva1);//creamos una imagen jpg con una calidad del 75%(por defecto) y no se cree guarda en ningún archivo. Imagedestroy($nueva1);//se libera la memoría utilizada en la creación de la imagen. ?> crear_imagen4 <? Header("Content-type: image/jpeg"); session_start();//continuamos la sesión abierta en index.php $fichero = $HTTP_SESSION_VARS["captcha_texto_session"];//recuperamos el nombre de las imagenes. Donde $fichero[12].$fichero[13] es el tipo y $fichero[14].$fichero[15] es la imagen dentro de ese tipo $nueva1=imagecreatefromjpeg("imagenes/".$fichero[12].$fichero[13].$fichero[14].$fichero[15].".jpg"); imagejpeg($nueva1);//creamos una imagen jpg con una calidad del 75%(por defecto) y no se cree guarda en ningún archivo. Imagedestroy($nueva1);//se libera la memoría utilizada en la creación de la imagen. ?> Verificar <? session_start();//Continua con la misma sesión abierta anteriormente en index.php $texto_ingresado = $HTTP_POST_VARS["texto_ingresado"];//valor mandado através del Junio de 2007 Página 27 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán formulario por el usuario $captcha_texto = $HTTP_SESSION_VARS["captcha_texto_session"];//valor real que se manda através de las variables de sesión //en el siguiente switch cada case es un tipo, y luego solo comprobamos si coincide el valor mandado através del formulario con el valor real switch ((int)$captcha_texto[0].$captcha_texto[1]) { case 1://Si ambos coinciden "Se es un ser humano" y si no "puede ser una máquina intentando aparentar serlo" if ($texto_ingresado=="amor") $correcto=1; else { $correcto=0; } break; case 2: if ($texto_ingresado=="arbol") $correcto=1; else { $correcto=0; } break; case 3: if ($texto_ingresado=="balon") $correcto=1; else { $correcto=0; } break; case 4: if ($texto_ingresado=="banco") $correcto=1; else { $correcto=0; } break; case 5: if ($texto_ingresado=="barco") $correcto=1; else { $correcto=0; } break; case 6: if ($texto_ingresado=="bota") $correcto=1; else { $correcto=0; } break; case 7: if ($texto_ingresado=="casa") $correcto=1; else { Junio de 2007 Página 28 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán $correcto=0; } break; case 8: if ($texto_ingresado=="dinosaurios") $correcto=1; else { $correcto=0; } break; case 9: if ($texto_ingresado=="isla") $correcto=1; else { $correcto=0; } break; case 10: if ($texto_ingresado=="matematicas") $correcto=1; else { $correcto=0; } break; case 11: if ($texto_ingresado=="moneda") $correcto=1; else { $correcto=0; } break; case 12: if ($texto_ingresado=="oveja") $correcto=1; else { $correcto=0; } break; case 13: if ($texto_ingresado=="pajaro") $correcto=1; else { $correcto=0; } break; case 14: if ($texto_ingresado=="raqueta") $correcto=1; else { $correcto=0; } break; case 15: if ($texto_ingresado=="risa") $correcto=1; Junio de 2007 Página 29 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán else { $correcto=0; } break; case 16: if ($texto_ingresado=="radio") $correcto=1; else { $correcto=0; } break; } if ($correcto==1) echo "El codigo es correcto."; else { echo "No ha escrito correctamente el codigo. Por favor intentelo de nuevo!"; } session_unset();//Elimina todas las variables de sesión session_destroy();//Elimina la sesión ?> Junio de 2007 Página 30 de 31 Trabajo de investigación Trabajo de investigación II CAPTCHA (Especialización Sistemas Distribuidos, Multimedia y Seguros) Autor: Eugenio Soler Galán BIBLIOGRAFÍA Los Captchas: prevención de los abusos en Internet Autor: Francisco Monteagudo (Servitec.com) http://www.camaravalencia.com/colecciondirectivos/leerArticulo.asp?intArticulo=1870 Captcha net http://www.captcha.net El gurú del programador http://www.elguruprogramador.com.ar/articulos/captcha-diferenciandoautomaticamente-humanos-de-maquinas-con-php.htm Wikipedia http://es.wikipedia.org/wiki/Captcha Junio de 2007 Página 31 de 31