Crackear captchas sencillos

Los captchas (Completely Automated Public Turing test to tell Computers and Humans Apart) están ampliamente extendidos hoy en día. Cualquier aplicación web con cierto nivel de seguridad que permita entrada de datos a usuarios no autentificados debería contar con un captcha para dificultar ataques de fuerza bruta. La mayoría de los captchas suelen ser visuales, en ellos se ha de escribir en un campo de texto los caracteres mostrados en una imagen. Pero el hecho de tener un captcha en una aplicación no significa que automáticamente estemos a salvo de ataques de fuerza bruta.

Un captcha visual débil resulta sencillo de romper gracias a programas de reconocimiento óptico de caracteres (OCR). Un captcha visual que resulte difícil de crackear debe contar con diferentes fuentes tipográficas, tamaños, colores, caracteres distorsionados y ruido en el fondo.

Ejemplo de un buen captcha

Ejemplo de un buen captcha

En esta entrada me gustaría mostrar lo sencillo que resulta el crackeo de un captcha débil. Para ello voy a exponer un caso real, omitiendo la dirección de la página web en cuestión. Se trata de una página que permite a sus usuarios hacer pública cierta información en forma de código. Este proceso se realiza anonimamente y sin ningún tipo de autentificación,  tan sólo cuenta con el siguiente captcha:

captcha debil que romperemos

captcha debil que romperemos

A simple vista se aprecia que el captcha no aporta gran seguridad gracias a sus caracteres perfectamente definidos.

Ejemplo práctico de crackeo de captcha débil

Para crackearlo usaremos el programa GOCR, el cual es open souce y en Linux se puede instalar desde las fuentes habituales.

Este programa requiere un «entrenamiento» previo para reconocer los caracteres, por lo que será lo que hemos de hacer en primer lugar:

mkdir ocrdb
gocr -d 2 -p ./ocrdb/ -m 256 -m 130 captcha.png

La ruta ./ocrdb/ será en dónde se guardarán los datos que genere gocr a partir de su «entrenamiento», este directorio lo tenemos que crear manualmente. ‘captcha.png’ es el captcha que crackearemos. Al ejecutar este comando, nos encontraremos con lo siguiente:

Entrenamiento de gocr

Entrenamiento de gocr

En esta captura vemos como gocr nos pregunta por la primera letra, en este caso una «V». La letra por la que nos pregunte en cada momento estará pintada con corchetes ‘#’, las demás con ‘O’. Al introducir la letra «V» continuará con las siguientes letras del captcha. Este proceso lo tendremos que repetir cuantas más veces mejor, hasta que gocr sea capaz de entender el captcha sin nuestra ayuda. Por lo que tendremos que ejecutar el comando bastantes veces, para agilizar el proceso podemos usar el siguiente script:

#!/bin/bash
while [ 1 ]; do
        wget -O captcha.png http:/servidor-ejemplo.com/captcha_gen.php ;
        gocr -d 2 -p ./ocrdb/ -m 256 -m 130 captcha.png ;
done

Cuando gocr sea capaz de descifrar la mayoría de captchas por si mismo pulsamos ctrl+c para detener el script. Lo siguiente sería poner a prueba el programa:

gocr -p ./ocrdb/ -m 256 -m 2 captcha.png

Este sería el método general para usar gocr, pero en el ejemplo que he propuesto es poco útil. Vamos a crear un script que se encargue del crackeo del captcha y del envío de nuestros códigos a la página con wget:

#!/bin/bash
# este será el código que se le enviará a la web
miCodigo='XPEYWZA-002'

# urls de la página. La general y la que recibe los datos por POST
url='http:/servidor-ejemplo.com'
postUrl='http:/servidor-ejemplo.com/add-code.php'

# rutas temporales de trabajo
dirActual=`pwd`
dirTrabajo='/tmp/captcha'

# si existe el directorio temporal lo borramos
if [ -d "$dirTrabajo" ]; then
        rm -Rf $dirTrabajo
fi
mkdir $dirTrabajo
cd $dirTrabajo

# hacemos una primera petición a la web guardando cookies
wget --save-cookies $dirTrabajo/cookies.txt --keep-session-cookies \
        -r $url

# renombrarmos el captcha, realizamos el OCR y eliminamos los espacios en blanco
mv captcha.php captcha.png
captchaResuelto=`gocr -p $dirActual/ocrdb/ -m 256 -m 2 captcha.png`
captchaResuelto=${captchaResuelto/ /}
echo 'CAPTCHA RESUELTO:' $captchaResuelto

# envíamos por POST el código a añadir y el resultado del captcha,
# teniendo en cuenta las cookies y datos de sesión
wget --post-data="add=$miCodigo&captcha_code=$captchaResuelto" \
                --keep-session-cookies --load-cookies $dirTrabajo/cookies.txt \
                $postUrl
cd $dirActual

Este script lo guardaremos el el mismo directorio en el que tenemos «ocrdb/». Le podríamos añadir algunas comprobaciones de respuesta de la web, algún bucle para repetir el envío, ejecutarlo cada X tiempo vía crontab, etc. Pero eso se sale de las pretensiones de esta entrada.

Nota: Las urls de los scripts están mal formadas intencionadamente (http:/) para que el resaltador de código no las incluya como enlaces.

Waiting for Xdebug session en Eclipse

Tras la instalación y configuración de Xdebug  para el IDE Eclipse PDT, me encontré que a la hora de lanzar el debug de una aplicación PHP el debug no se llevaba a cabo. El proceso permanecía en el 57% con el mensaje «Waiting for Xdebug session«.

Dicho error es producido por la configuración por defecto de java en Debian. Al comprobar los servicios a la escucha, el puerto 9000 (eclipse) está escuchando sobre ipv6:

netstat -anp -t tcp | grep 9000
la salida de netstat nos devuelve:

tcp6 0 0 :::9000 :::*  LISTEN  4390/java

Para solucionar dicho problema será necesario  modificar el siguiente archivo:

/etc/sysctl.d/bindv6only.conf

Localizar la siguiente línea:

net.ipv6.bindv6only = 1

sustituirla por esta que sigue:

net.ipv6.bindv6only = 0

a continuación ejecutar:

sysctl -p /etc/sysctl.d/bindv6only.conf

por último reiniciar Eclipse.

Windows no aparece en Grub2 de Debian

Tal y como comentaba en la anterior entrada, hace poco que realicé una instalación de Debian con su posterior actualización a la rama Inestable «Sid«. Tras esto se instaló como gestor de arranque grub2, trayendo consigo la sorpresa de que no había detectado la instalación de Windows 7 que tengo en otra partición del disco duro.

Para que grub2 nos detecte la partición de Windows (sea windows xp, vista ó windows 7) sencillamente hemos de hacer lo siguiente:

Abrimos una consola y como super-usuario hacemos lo siguiente:

# apt-get install os-prober
# update-grub2

os-prober se encargará de generar un archivo «/etc/grub.d/30_os-probe» mediante el cual se detectarán los sitemas operativos y que usará grub para su menu de arranque.

Sólo faltaría reiniciar el sistema y comprobar que grub ha añadido automáticamente nuestra partición de windows al menú de arranque.

Refusing to mount device en KDE 4.3.4

He sido usuario de Kubuntu durante varios años, lo he tenido como sistema operativo de uso diario en mi portátil. Con la llegada de Kubuntu 9.10 me encontré con que KDE4 funcionaba inexplicablemente lento, el simple hecho de cambiar de ventana se le hacía cuesta arriba. A raíz de ello estuve usando GNOME durante un par de meses, resultando una experiencia agradable en cuanto a rendimiento general del sistema, pero seguía echando de menos la comodidad que da KDE en determinadas situaciones.

Antes de ser usuario de Ubuntu lo era de Debian, de la rama SID en concreto, así que decidí a volver a ella. La instalación es sencilla con algún problema sin demasiada repercusión al actualizar a inestable. El mayor problema con el que me encontré fue que el navegador de archivos de KDE, Dolphin, no era capaz de montar las unidades internas NTFS con un usuario estándar (no root). Al hacer click en el icono de uno de los discos duros daba el siguiente error:

Se produjo un error mientras se accedía a "almacén", el sistema respondió: org.freedesktop.Hal.Device.Volume.PermissionDenied: Refusing to mount device /dev/sda1 for uid=1000.

Después de rebuscar durante un buen rato en google, encontré que el problema es que es enecesario pasar al servicio HAL los parámetros que acepta ntfs-3g, en concreto necesita la opción "locale=". Una forma de añadir este parámetro a la configuración de HAL sería editando el archivo "/usr/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi" y añadir en el apartado de NTFS lo siguiente: <append key="volume.mount.valid_options" type="strlist">locale=</append>. Pero se puede hacer de una manera más visual:

  • Abrir una consola de super usuario e instalar ntfs-3g en caso de que no lo tengamos ya: # apt-get install ntfs-3g
  • Instalar ntfs-config: # apt-get install ntfs-config
  • Ejecutar ntfs-config como root vía alt+F2: kdesu ntfs-config
  • Marcar las opciones de soporte de escritura en los dispositivos externos e internos, cerrar dicha ventana.
  • Después de estos sencillos pasos es recomendable reiniciar el sistema y tendremos las unidades internas de nuestro PC habilitadas para ser montadas por un usuario sin privilegios de administrador desde Dolphin.

    Referencias:

    Reparar partición ntfs desde linux

    Recientemente he reinstalado los sistemas operativos de mi portátil, tanto Windows como Linux. Aproveché a su vez para reorganizar las particiones de disco. Tiempo atrás había tenido algunos problemas con una partición ntfs pero se habían subsanado en mayor o menor medida. A raiz de esto, a la hora de particionar con gparted el programa no detectaba la estructura del disco. Finalmente pude reparticionar con el Acronis incluído en Hiren’s Boot.

    Una vez reinstalados los sistemas operativos, me encuentro con que no podía acceder desde Linux a la partición ntfs mencionada anteriormente. Después de una búsqueda en los repositorios, encontré el paquete ntfsprogs, que entre otras utilidades incluye una para reparar particiones.

    # apt-cache show ntfsprogs
    Herramientas para realizar cosas interesantes en particiones NTFS desde Linux
    El proyecto Linux-NTFS (http://www.linux-ntfs.org/) intenta conseguir
    poder usar completamente el sistema de archivos NTFS desde el sistema
    operativo Linux.

    Concretamente me interesa la utilidad ntfsfix:

    ntfsfixArregla errores comunes en el sistema de archivos y fuerza a Windows a comprobar NTFS

    La forma de utilizarlo es de lo más sencillo:

    # ntfsfix /dev/sda1

    Proxy socks vía tunel SSH para navegar seguro

    Hoy en día no es raro que nos conectemos a Internet desde redes no seguras: cafeterías, universidades, etc. Esto puede conllevar que nuestros datos sean interceptados fácilmente por terceras personas. Un espía podría atacarnos desde varios frentes; por un lado, estando en nuestra red local y ejecutando un sniffer apoyado en un ataque man in the middle; y por otro lado podría estar fuera de nuestra red local capturando el tráfico wifi cifrado para a posteriori descifrarlo con la clave adecuada.

    Ante estos dos ataques contra la privacidad se puede utilizar un proxy con cifrado para que nuestros datos viajen através de la red local no segura de forma segura. Una de las formas más rápidas de conseguir esto es utilizando conexiones SSH. Tan sólo deberemos tener un cuenta SSH en un servidor de confianza y lanzar la conexión de la siguiente manera:

    ssh -N -C -D 9999 NOMBRE_USUARIO@IP_SERVIDODR_SSH -p PUERTO

    donde:

    -N no iniciar sesión de shell

    -C habilitar compresión

    -D puerto local para crear el tunel

    -p puerto remoto del servidor ssh (si no se indica este modificador asume el 22)

    Después de realizar la conexión la dejaremos abierta mientras estemos usando el proxy. Sólo faltaría configurar en nuestro navegador web el proxy SOCKS como «localhost» por el puerto 9999.

    Distinguir una sesión local de una remota en Linux

    Me he encontrado con la necesidad de programar un pequeño script en bash para el servidor Linux de un cliente. Dicho script estaba funcionando correctemente en la máquina local pero no así cuando se realizaba una conexión remota.

    Ante esto era preciso encontrar alguna manera de discernir entre las conexiones locales y remontas para realizar configuraciones diferentes para cada una.

    La solución, sencilla y un tanto ingeniosa, pasó por utilizar variables de entorno para hacer la distinción entre conexión local y remota:

    if [[ -z "$REMOTEHOST" &&  -z  "$SSH_CLIENT"  ]]; then
    echo "Cliente conectado en local";
    else
    echo "Cliente conectado en remoto";
    fi

    Se comprueba que no existan las variables de entorno $REMOTEHOST ni $SSH_CLIENT, la primera está presente en conexiones telnet y la segunda en conexiones SSH. Si no existe ninguna de ellas la conexión es local, si existe alguna de ellas la conexión es remota.

    Presentando Paprica.es

    Ya está online la nueva página web del Restaurante Paprica de Lugo, desarrollada por mi compañero Alberto Montes y yo. Alberto se encargó del diseño gráfico y yo de la programación. Por un lado buscamos que fuese sencilla al uso y elegante a la vista; y por otro lado que contase con una administración a medida.

    Para ello echamos mano de XHTML (tableless)+CSS para lo visual y PHP+MySQL para la gestión de los contenidos. Siempre teniendo presentes los estándars y compatibilidad con navegadores.

    Restaurante Paprica

    Espero que nuestro proyecto actual resulte igual de satisfactorio que paprica.es tanto personal como profesionalmente.

    Ocultar versión de apache

    Si bien la segurdiad por seguridad por oscuridad debe tratarse como un añadido secundario a otros métodos más básicos, puede resultar una buena práctica para poner las cósas un poco más difíciles a un posible atacante.

    Para ocultar la versión de un servidor web apache haremos lo siguiente:

    Editamos el archivo de configuración de apache

    vi /etc/apache2/apache2.conf

    Modificamos las siguientes directivas ó en caso de no contar con ellas las añadiremos

    ServerTokens ProductOnly
    ServerSignature Off

    Después de guardar los cambios en el archivo se debe reiniciar apache

    /etc/init.d/apache2 restart

    A continuación se incluyen dos capturas de pantalla del antes y el después de hacer este cambio.

    Esta captura muestra la información que ofrece apache con su configuración por defecto. Facilita información tal como: sistema operativo, versión de apache y versión de PHP. Toda esta información es totalmente innecesaria en un servidor en producción.

    version-apache011

    La siguiente captura muestra la información facilitada tras realizar los camibios expuestos anteriormente. Tan sólo muestra que el servidor es «Apache» sin más detalles.

    version-apache02