domingo, 15 de julio de 2012

Mamá, me han robado un millón de contraseñas

En los últimos días, hemos tenido noticias de al menos cuatro robos de información en diferentes webs:  FormspringYahoo, AndroidforumsBillabong y Nvidia.  En todos ellos, los asaltantes tuvieron acceso a la lista de nombres de usuario y contraseñas de un gran número de usuarios (desde 35.000 en el caso de Billabong hasta el millón de Androidforums). En seguida surgen las preguntas: ¿cómo han podido efectuar esos robos?  ¿Por qué los administradores de sistema no han podido evitarlo?  ¿Cómo evitar que suceda?

Da la casualidad de que este verano estoy escribiendo un libro sobre fallos en criptografía.  Tema hay, os lo aseguro.  Mientras escribía el tema sobre contraseñas débiles, estos casos me tuvieron tarumba, no acababa de hablar de uno cuando salía otro.  La ventaja es que, gracias a ello, he aprendido un montón.  Con vuestro permiso (y teniendo en cuenta que apenas tengo el tema en borrador), voy a intentar aclararos el asunto.


¿CÓMO ES POSIBLE QUE OCURRAN ESTOS ROBOS?

Cuando hay un sistema de acceso para múltiples usuarios, como en los casos anteriormente mencionados, la web tiene que guardar los nombres de usuario y la contraseñas en una gran base de datos, un objetivo que por eso resulta muy valioso.  La creencia popular dice que los hackers consiguen acceso a la base de datos, la copian y salen corriendo a estilo Indiana Jones.  Nada más lejos de la realidad.  Lo habitual es realizar técnicas como la llamada "Inyección SQL," que pasa por "inyectar" información que el sistema interpeta como órdenes.  Es algo así como si un guardia de seguridad me interceptase a la puerta de un banco.  El guardia me pregunta por mi nombre, y yo respondo diciendo "mi nombre es 'Arturo Dametucartera' "  El guardia cree que el apellido es una orden ... y me entrega su cartera. Un ejemplo real, tomado de la Wikipedia, nos ayudará a entenderlo.  Tenemos una web que nos pide el nombre de usuario.  El código SQL que usó el programador en la web es:

consulta := "SELECT * FROM usuarios WHERE nombre = '" + nombreUsuario + "';"

En esta consulta, el sistema seleccionará los registros para los que nombre coincida con la entrada del usuario (nombreUsuario).  Si éste teclea la palabra Alicia, la orden que recibe el sistema es:

SELECT * FROM usuarios WHERE nombre = 'Alicia';

Esa orden hará que la base de datos busque todos los registros con nombre Alicia.  Hasta aquí todo normal.  Pero supongamos que el atacante teclea esto:

Alicia'; DROP TABLE usuarios; SELECT * FROM datos WHERE nombre LIKE '%

En ese caso, esto es lo que entenderá el sistema:

SELECT * FROM usuarios WHERE nombre = 'Alicia';
DROP TABLE usuarios;
SELECT * FROM datos WHERE nombre LIKE '%';

Ahora en lugar de una línea de instrucciones, tenemos tres.  Las dos últimas han sido “inyectadas” en el sistema, que ahora hará esto:
- Seleccionar los registros con nombre Alicia
- Borrar la tabla de usuarios
- Seleccionar toda la tabla de datos (que en condiciones normales no debería estar accesible al usuario)


¿CÓMO PODEMOS REMEDIAR EL PROBLEMA?

Una solución al problema de tener un archivo de contraseñas consiste en no tener un archivo de contraseñas.  En su lugar, se guardan los valores hash de las contraseñas. Un hash es una función unidireccional que toma la contraseña C y la convierte en una ristra alfanumérica h=H(C). Una empresa con conciencia de seguridad tomaría todas las contraseñas de los usuarios, sometería cada una a la función hash, y guardaría el resultado.  Cuando el usuario entra una contraseña C, el sistema usa una función hash H y determina su valor para ese caso, digamos h. A continuación, el sistema consulta la base de datos de hashes. Si el correspondiente al usuario coincide con h, eso significa que el usuario ha usado una contraseña válida. De este modo, el sistema ha comprobado la validez de una contraseña sin siquiera saber qué vale. En teoría, un ladrón que se llevase la base de datos de hashes no podría obtener ninguna información sobre las contraseñas, porque conocido h no se puede conocer el valor de C que cumple h=H(C).  Por supuesto, no debe usarse MD5, una función hash muy utilizada en el pasado pero que en la actualidad se considera rota y vulnerable.

Uno de los ejemplos más dramáticos lo tenemos el caso de PlayStation Network. El 20 de abril de 2011, la red de juegos de Sony tuvo que ser desconectada durante casi un mes tras el descubrimiento que los datos personales de sus usuarios habían sido robados.  El número de clientes afectados, más de 77 millones, lo convirtió en uno de los mayores casos sobre robo de información de usuarios. Sony afirmó que las contraseñas estaban protegidas con una función hash, y aunque no dio más detalles el hecho es que, hasta donde yo sé, las contraseñas nunca fueron filtradas públicamente. Por desgracia, Sony no se aplicó su propia medicina en otros casos. En junio de 2011, la web de Sony Pictures fue asaltada por el grupo hacker LulzSec y robó la información privada de más de un millón de personas, incluyendo direcciones de email y contraseñas en texto llano, es decir, sin protección hash alguna.

Aunque el uso de hashes en lugar de contraseñas aumenta la seguridad de un sistema, tiene diversos fallos explotables por un atacante con recursos.  El primero sigue siendo el hecho de que las contraseñas habituales son, como hemos visto antes, sencillas.  Un atacante podría tomar su “diccionario” de contraseñas y aplicar la función hash H a cada una de ellas.  Digamos que la contraseña password tiene con hash la cadena alfanumérica 1c29A, esto es, H(password)=1c24A.  Eso significa que, si en la base de datos de funciones hash que acabamos de robar, aparece un hash igual a 1c24A, ya sabemos que la contraseña correspondiente es password. Hay herramientas informáticas capaces de comprobar miles de hashes por segundo, como el programa John the Ripper, usado habitualmente por los administradores de sistemas para comprobar la fortaleza de las contraseñas de usuario ... y por los hackers para intentar reventarla.

El defensor puede aumentar el nivel de seguridad añadiendo “sal” al sistema.  Como en las aplicaciones culinarias, la sal da sabor al guiso.  En este caso, lo que se denomina “sal” es una pequeña cadena de bits que se añaden a la contraseña.  De este modo, lo que guarda el sistema no es H(password) sino H(password+sal).  Ahora el contrincante lo tiene más difícil, ya que a cada elemento de su diccionario tendrá que añadirle muchos valores de sal hasta encontrar el correcto.

Incluso en el caso de usar funciones hash fuertes y sal, un usuario que utilice una contraseña débil es vulnerable.  Por ejemplo, el 10 de julio de 2012 la red social Formspring reconoció el robo de 420.000 hashes correspondientes a contraseñas de sus usuarios.  La función hash utilizada era la SHA-256, y también empleaban sal, lo que significa que Formspring hizo bien sus deberes (salvo por el detalle de dejarse robar información).  Aun así, el usuario de una contraseña débil está en peligro.  Armados con una lista de contraseñas de uso común, los atacantes no tienen más que probarlas combinándolas con todos los valores posibles de sal para obtener acceso a al menos algunas de las cuentas.  La única defensa eficaz contra una intrusión de este tipo es deshabilitar todas las contraseñas, una medida que requiere valor porque significa molestar a millones de usuarios y enviarles el mensaje de que el sistema es inseguro (Formspring hizo exactamente eso, y hay que aplaudirles por ello); y, en segundo lugar, implementar en el sistema un comprobador que rechace las contraseñas cortas o débiles.


¿CÓMO PROTEGÍAN SUS CONTRASEÑAS LOS ATACADOS?

En los cinco casos que mencioné al principio, hay de todo.  Las técnicas que hemos visto (hash, sal) se deben combinar con una rápida respuesta y un aviso pronto a los usuarios para que cambien las contraseñas.  Si hay que deshabilitar todas las contraseñas y empezar de cero, se hace.

Hay un caso de texto de lo que NO se debe hacer. En diciembre de 2009, un sufrió un ataque cuyo resultado fue el robo de la información (usuario y contraseña en texto llano) de más de 32 millones de usuarios.  Los responsables de RockYou fueron duramente criticados por las circunstancias que se combinaron en ese caso:

- A pesar de que la empresa de seguridad Imperva había avisado del ataque el día 4, la web no advirtió a sus usuarios hasta diez días después
- La cantidad de contraseñas custodiadas en texto llano, sin ningún tipo de protección, era enorme, lo que lo convierte en uno de los mayores robos de contraseñas en texto llano de la historia.
- Las normas de seguridad de RockYou permitían crear contraseñas de tan sólo cinco caracteres, y recomendaba no utilizar “caracteres especiales” (es decir, no alfanuméricos), que en realidad hubieran incrementado la seguridad
- La web de RockYou permitía a sus clientes acceder a sus perfiles de otras redes sociales como Myspace, Hi5, Orkut o Facebook.  Para ello, el cliente introducía las contraseñas de su perfil en dichas redes, y RockYou guardaba una copia.  Sí, ha leído bien: RockYou guardaba contraseñas de otras redes sociales … y lo hacía en texto llano.

Así que vamos a ver cómo se las apañaron nuestro cinco magníficos:

- Androidforums. 1.000.000 contraseñas robadas.  Usaron hash y sal.
- Billabong. 35.000 contraseñas robadas en texto llano.
- Formspring.  420.000 contraseñas robadas.  Usaron hash y sal.
- Nvidia. 390.000 contraseñas robadas.  Usaron hash y sal.
- Yahoo. 450.000 contraseñas robadas en texto llano, sin hash.

Como puede verse, algunas webs atacadas habían hecho sus deberes correctamente (salvo por el detalle de dejarse robar la información).  En el polo opuesto, Billabong y Yahoo la cagaron.  Yahoo se apresuró a arreglar el fallo, que atribuyó a un archivo viejo.  Aun así, el hecho de guardar contraseñas en texto llano le vale un FAIL como una casa.  En cuanto a Billabong, no sólo no ha avisado a sus usuarios sino que ni siquiera ha reconocido todavía el problema, lo que le hace merecedor de un EPIC FAIL.

Pero recordad, usuarios: incluso la mejor protección posible falla si escogéis una contraseña mala.  Huid de contraseñas cortas, fáciles de adivinar (nombres de parientes, fechas de nacimiento, palabras con un "1" al final o con la O sustituyendo a un cero), y os haréis a vosotros mismos un gran favor. En esto, Sheldon Cooper tiene más razón que un santo: 1234 no es una contraseña segura.  Y eso va también por tí, Kal-El, digo Leonard.