Bases de datos, passwords, seguridad y otras yerbas

Hoy por la madrugada paso algo bastante fuerte: hackearon geelbe.com

Para los que no lo saben geelbe es un “club privado de compras”, un modelo distinto a sitios como Mercado Libre o De Remate donde cualquiera puede participar. La idea es lograr tener una red de confianza entre la gente que participa ya que solamente se entra por invitación.

Al margen de como funciona el sitio, esta madrugada se publico en Internet una lista de usuarios con su respectivo password. ¿Como es esto posible? Facil, los passwords estaban guardados en la base de datos en texto plano.

Existen varias formas en las que uno puede elegir guardar el password de sus usuarios en la base de datos, a saber: en texto plano, encriptadas, encriptadas con salt. Cada una tiene sus pro y sus contras, y de hecho dependiendo del tipo de aplicación que estemos desarrollando existen leyes al respecto.

Texto plano

Guardar las claves en texto plano es lo mas simple. Uno tiene registro del password de cada usuario y cuando este intenta ingresar al sistema se compara el password que nos provee contra el que tenemos en la base de datos, si es igual, lo dejamos pasar, si no es igual, impedimos que acceda.

Encriptada

Cuando uno encripta passwords utiliza algún tipo de hash, esto es, un algoritmo que da por resultado una cadena de texto que no se puede revertir al dato que se ingreso originalmente (el password).

Ejemplos de estos algoritmos son md5 y sha1, los mas utilizados en las aplicaciones WEB por cierto.

Encriptada con salt

Para entender la encriptacion con salt primero hay que ver una gran falencia en la encriptacion a secas: Si uno asume que su aplicación puede, por alguna falla de seguridad, llegar a dejar expuesta la base de datos, y por consiguiente tener acceso a los passwords encriptados, estos pueden llegar a ser revertidos.

¿Pero como? Si recién dije que se utilizan algoritmos por los cuales no se puede llegar al password partiendo del resultado del algoritmo, bien, existen lo que se conoce como rainbow tables, que son listas de los passwords ya encriptados y su correspondiente password en texto plano. De esta forma cuando uno tiene un password encriptado, puede ir a una rainbow table pre generada con millones de passwords y ver si lo encuentra ahí, de ser así, tiene la versión en texto plano del mismo. Obviamente también existe la “fuerza bruta”, esto es, teniendo el hash empezar a probar encriptar todas las combinaciones de letras, números, etc hasta llegar a algún hash que coincida, y ahí obtenemos el password original (o también se puede utilizar una lista de los passwords mas comunes para probar).

¿Como evitamos que alguien venga y compruebe los passwords guardados en la base de datos contra una rainbow table y obtenga el password original? Bueno, podemos, en lugar de guardar el hash del password, agregarle una pequeña cadena de texto “random” al password original, y después guardarnos el hash resultante de encriptar eso y también guardarnos la cadena. Esta es la practica mas extendida hoy en día y frameworks como Django ya lo hacen desde el vamos, también el cookbook de Ruby on Rails nos recomienda hacerlo. Es mucho menos probable que existan rainbow con el password mas una cadena al azar de que si existen rainbow tables con el password solamente.

Viendo estas tres opciones tenemos que decir que el caso de Geelbe coincida con el primero, ellos no encriptan los passwords guardados en la base de datos lo cual no seria problema si nadie pudiera acceder a la base de datos.

Puedo asumir que como quien tuvo acceso a los passwords los publico en la web, que no accedio al servidor, ya que su intencion era la de hacer algun daño a la imagen de Geelbe y de haber tenido acceso al servidor seguramente hubiera defaceado (ie: cambiado la pagina por algo tipo “hackeado por pepito”) y no solamente publicado los passwords. Seguramente el acceso se dio por algún SQL Injection como el que Patricio descubrió hace unas semanas en Infobae.

Otro detalle a tener en cuenta, y esta practica no esta tan extendida, es la elección del algoritmo para encriptar/hashear los passwords. Si bien las practicas comunes nos dicen que usemos md5 y sha1, lo cierto es que esos algoritmos no fueron diseñados para esa tarea, son efectivos, si, pero tienen un problema: son rápidos.

¿Que tiene de malo que sean rápidos? Cuando uno controla a un usuario que accede a su sitio por lo general guarda una cookie que. Esta cookie guarda solamente un identificador de sesión el cual en el servidor terminamos asociando con el usuario, esto quiere decir que solamente la primer ves que accede el usuario al sitio se comprueba su password. Así que no necesitamos que sea rápido. ¿Donde si es útil la velocidad del algoritmo de hasheo? Cuando uno trata de hacer brute force. Si vos tenes un hash y queres ir probando todas las palabras posibles contra ese hash, y cada intento te toma milésimas de segundo, vas a llegar mucho mas rápido a destino que si te toma 1 segundo cada intento. Es por eso que es recomendable utilizar algún algoritmo como bcrypt que si están diseñados para guardar passwords de usuarios (¡Es lento apropósito!).

Si la aplicación por otro lado tiene que manejar datos como tarjetas de crédito y cobros (PayPal, Google checkout, etc), recomiendo leer las guiás de PCI y los blogs de la gente que desarrolla los estándares de seguridad para ese tipo de aplicaciones (por suerte hasta ahora no me toco desarrollar ninguna así de critica).

Una nota al margen del objetivo del post (concientizar del sano storage de passwords): La gente de Geelbe esta haciendo un laburo groso, un SQL Injection no es un bug tan raro y el error grave que tuvieron (tener los passwords en pseudo texto plano) es corregible 100%, no seamos botones y pasemos la lista de usuarios afectados y sus passwords por ahí.

9 Responses to “Bases de datos, passwords, seguridad y otras yerbas”

  1. Julio Says:

    Angel muy buen post.

    Despues de ver tantos y tan diferentes problemas en todos lados, uno puede afirmar ese dicho “Existen dos clases de sistemas, los hackeados y los que van a ser hackeados”.


  2. Eric Londaits Says:

    Agradezco que hayas puesto este post para educar al público general y también a la gente comercial de Geelbe que quizás no sabía estas cosas y fue “embaucada” por programadores incompetentes.

    Sin embargo quisiera hacer un par de salvedades a lo que decís:

    1) Guardar las passwords en texto plano es completa y absolutamente inaceptable por varias razones:

    a) Guardarlas encriptadas no es esfuerzo alguno

    b) Nunca se puede saber si no serán vistas. Es imposible asumir que el sitio es inhackeable.

    c) Aún si nunca son hackeadas están a la vista de los empleados de Geelbe (el dba, por ej). Nadie de Geelbe (ni el presidente ni sus empleados) deberían tener almacenados datos críticos del usuario que no necesitan para operar (i.e. la password en texto plano). Encriptar las contraseñas es primero que nada una muestra de respeto básica a los usuarios.

    2) Es verdad que un SQL Injection es un error recontra común… pero a la vez es muy sencillo de evitar usando prácticas o frameworks adecuados. Es un ataque que se puede evitar con una revisión metódica de todas las instancias de tratamiento de datos de entrada. Para una empresa ser vulnerable a este tipo de ataques hoy día es completa, total y absolutamente inaceptable. Hay ataques más complejos como los de XSS y CSRF que son mucho más difíciles de tapar, con los que estaría un poco más dispuesto a hacer concesiones… pero no inyección SQL.

    Nota al margen:

    La verdadera bolilla negra acá va para las empresas de tarjeta de crédito, que en vez de exigir huevadas varias respecto a la seguridad deberían mirar lo mínimo y básico de la seguridad del sitio (como la forma de almacenar las contraseñas)… porque aunque los números de tarjeta no queden expuestos hay un problema de seguridad grosísimo inherente en difundir contraseñas y mails de los usuarios que te dieron su número de tarjeta… alcanzan para contactar a esos usuarios con una historia de terror (”un error en el sistema de autorizaciones, necesitamos revertirle un cargo para que no aparezca en su próxima liquidación”) y sacarles los datos de tarjeta por métodos varios (”por seguridad no nos mande el número, haga un scan de la tarjeta y mándela por mail…” o “mándenos el número por fax a.. (locutorio)” o “llame a este número de teléfono y deje su nombre y número de tarjeta en el contestador (celular con chip)”).


  3. qwerty Says:

    @Eric Londaits: Estoy de acuerdo, SQL Injection no es aceptable ni remotamente, solamente queria aclarar que era comun por si alguien no-tecnico leia el articulo (despues de todo es el item #2 en la lista de los errores mas comunes cuando uno programa: http://www.sans.org/top25-programming-errors/).

    Considero que sitios como Geelbe, que manejan transacciones comerciales de una u otra forma deberian ser scaneados regularmente con herramientas como Peach Fuzzer, scapy y w3af. Eso y tener programadores que sean concientes de lo que hacen.


  4. alejolp Says:

    Hace poco me crucé con esto, Un paso mas allá de las salted passwords

    How to safely store a password:
    http://codahale.com/how-to-safely-store-a-password/

    Saludos!


  5. alejolp Says:

    eehh, no habia leido todo lo que escribiste. el link que te dejé ya lo tenías ahi… :)

    el problema con las salted es que podés armarte una rainbow con esa salt, y estás en la misma que usando md5/sha1.


  6. Ezequiel Says:

    Un dato de color. Habiendo visto algunas contraseñas me parece que no solo las encodearon con base64… también las saltearon??? Si desencriptas las contraseñas terminan todas igual…

    Estoy en lo correcto o hay algo que me estoy perdiendo?


  7. Matiu Says:

    Excelente post! Gracias.

    Guardar password en texto plano es inaceptable. O de vago o de ignorante.

    Lo lamento profundamente por Geelbe.


  8. qwerty Says:

    @Ezequiel: efectivamente, las saltearon, como esta dando vueltas en twitter un rt de algo que dije por chat: “Quizás pensaron que base64 es 59 veces más groso que md5″


  9. Gustavo Says:

    Creo que repercutió negativamente porque un emprendimiento que cuenta con 3.2 millones de U$S de inversiòn, esté basado en un sistema hecho por freelancers. Cuando lo empezaron a desarrollar internamente, no lo reescribieron desde cero, además de no contratar gente calificada por los niveles de sueldo que pagan.
    Espero que hayan aprendido la lección: programadores bien pagos e idóneos y sistemas en base a frameworks bien conocidos (ej.: Symfony o Zend Framework)


Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>