salt_pepper

Aliñando contraseñas en base de datos, ¿desarrollas o enriqueces?

En el anterior post hablamos de contraseñas desde el punto de vista de un usuario, de la importancia que tiene tener una buena política para evitar que sean sencillas de descubrir tanto a nivel de imaginación como de procesamiento mediante fuerza bruta.

En esta entrada vamos a centrarnos en las formas que hay para tratarlas y almacenarlas poniéndonos en la piel del desarrollador de aplicaciones.

La prehistoria… ¿o no?

Hace años, las aplicaciones que necesitaban gestión de usuarios se creaban implementando acceso a una base de datos en la que se guardaba la habitual pareja “usuario – contraseña”. Cuando se realizaba el proceso de login en el que el usuario indicaba sus credenciales (<user, <password>), bastaba con preguntar algo del tipo:

select user from users where user = <user> and password = <password>

Si obteníamos respuesta, entonces el usuario era quien decía ser, así de sencillo.

Esto, que debería ser algo totalmente obsoleto, todavía lo podemos encontrar en muchas más aplicaciones webs y de escritorio de las que creeríamos…

A modo de ejemplo, el dump de una base de datos MySql de una conocida marca de… (la llamaremos “Acuario” para no dar su verdadero nombre) almacena las credenciales de sus usuarios en un sistema vulnerable a ataques SQL Injection tal que así:

mysql_dump

Dump MySQL con información privada en texto plano

No hace falta decir que almacenar nombre, apellidos, usuario y contraseña de esta forma no es lo correcto, el desarrollador no ha hecho bien los deberes.

Almacenamiento de hashes

El siguiente paso fue dejar de almacenar los dos valores para almacenar el usuario y “algo” relacionado con la contraseña. Ese algo es un hash.

Un hash es el equivalente a una huella digital. Se consigue realizando un proceso matemático que da un valor de salida determinado a un objeto de entrada (podemos hablar de un fichero, un texto, un número…). Es importante tener en cuenta que un proceso de hashing debe ser irreversible, lo que quiere decir que no debemos ser capaces de calcular el objeto de entrada a partir del objeto de salida (ahí reside su fuerza como algoritmo).

Aunque no vamos a entrar en ellos, los algoritmos de hashing habituales son SHA (Secure Hash Algorith) y MD5 (Message-Digest Algorithm 5).

El sentido de todo esto es almacenar hashes en lugar de contraseñas. Así, si alguien ve nuestro hash, no le servirá de nada ya que no podrá deshacerlo.

En este caso, se ha dado un paso más para complicarle la vida a un atacante. Suponiendo que ha conseguido el dump de nuestra base de datos de usuarios, ya no lo tendrá tan sencillo como antes (recordemos que solamente tenía que saber leer para conseguir las credenciales). Ahora tendrá que realizar un ataque de fuerza bruta para generar hashes e ir comparando hasta dar con el objeto de entrada que genera el hash de salida almacenado en la tabla.

Aquí enlazamos con la importancia de tener una buena política de contraseñas, ya que existe lo que se conoce como “tablas rainbow” que son tablas con hashes ya calculados para grandes cantidades de posibles contraseñas.

Cuanto más sencilla sea nuestra contraseña, más probabilidad habrá de que se encuentre en una de estas tablas y que el atacante consiga las credenciales.

El funcionamiento desde el punto de vista del desarrollo es sencillo, cuando ingresemos nuestras credenciales <user> y <password>, se calcula el hash de la contraseña introducida y se compara con el que hay en base de datos, algo como:

select user from users where user = <user> and hash = hash(<password>)

En este ejemplo podemos ver una base de datos de prueba en la que se han obtenido los nombres de usuario y los hashes. Mediante un ataque de fuerza bruta con diccionario incluso se han podido sacar algunas contraseñas en claro.

hash_mysql

Dump MySQL con información privada hasheada y algunos valores obtenidos mediante fuerza bruta.

La práctica actual, “aliñando” el problema

Para atajar el problema de las tablas rainbow se ha optado por dar un paso más en complicar la vida al atacante. Surgen entonces los planteamientos con «salt & pepper» (sal y pimienta), que consisten en utilizar cadenas que se concatenan con la contraseña de usuario para convertir cualquier password débil en una password fuerte.

Imaginemos que tu contraseña es algo como “123456” (sólo números y longitud 6). El hash de esta contraseña va a estar en tablas rainbow, por lo que el atacante conseguiría credenciales casi al instante.

La aplicación podría añadirle el salt “f0Et%%kS*yJ@” y convertir tu pass en “123456_f0Et%%kS*yJ@”. Con este sencillo paso, tu clave débil se ha convertido en una clave fuerte, hemos conseguido una buena defensa frente a ese atacante.

Normalmente ese salt se almacena en la propia base de datos y se utiliza para realizar la consulta, que sería del tipo:

select user from users where user = <user> and hash = hash(<password>+salt)

Como alternativa o paso más, podríamos utilizar el pepper que es igual que salt, pero almacenado fuera de la base de datos.

hash_salt

Dump MySQL con hash y salt almacenados en la misma tabla

¿ Con esto ya estamos seguros?

La seguridad absoluta es una quimera, en nuestro caso (recordad que tenemos puesto el casco de desarrollador ahora mismo) nuestra intención es que los datos que almacenamos sean lo más complejos de obtener en el caso hipotético de que un usuario malicioso haya llegado a ellos.

Debemos poner medidas externas para evitar que se pueda acceder a la base de datos, pero tomar este tipo de controles es una buena práctica que todo desarrollador debe tener en cuenta.

Pensad siempre que si alguien quiere entrar, es posible que lo consiga. Cuantas más piedras le pongamos en el camino, más probabilidad tendremos de aburrirle en su tarea y de que decida cambiar por otro objetivo más sencillo.

Pero sobre todo, a nivel de imagen, no podemos permitirnos que los datos personales de nuestros clientes sean publicados, es nuestro deber aplicar medidas preventivas como estas, sobre todo cuando son tan sencillas de implementar.

 

Espero haberte ayudado con esta visión de seguridad en contraseñas desde los perfiles de usuario y desarrollador. En cualquier caso, si ves algún error, no estás de acuerdo con lo que cuento o quieres hacer alguna aportación, no dudes en pasarte por los comentarios.

¡Feliz semana!
Exfiltración del IMEI

Exfiltración del IMEI en aplicaciones móviles

Hoy en día, la exfiltración del IMEI es una práctica que los desarrolladores están llevando a cabo. Se desconoce si lo utilizan para identificar de forma única al usuario dentro de la aplicación, o bien con otras intenciones. En cualquier caso, la fuga de esta información pone en riesgo la privacidad del usuario.

Leer más

Evitando HSTS, ¿una cuestión de tiempo?

Como vimos en el artículo anterior http://securityinside.info/hsts-una-defensa-mitm-sslstrip/ , HSTS fue creado para que los navegadores rechazasen conexiones HTTP a ciertos lugares y, de este modo evitar ataques de interceptación tipo mitm o sslstrip. Para ello, se introduce la nueva cabecera Strict-Transport-Security en el protocolo HTTP, que establece unos parámetros para indicar al navegador una política de como manejar las conexiones SSL para un sitio web en concreto. Los navegadores que implementan HSTS mantienen además una lista «precargada» de dominios  con lo cual se  evitaría el posible ataque al visitar por primera vez que se visita un sitio y no conocer que implementa HSTS. El ataque en esas circunstancias de primera visita, de no existir las listas precargadas podría ser efectivo. Es lo que se denomina ataque bootstrap.  

Más información sobre las listas precargadas puede encontrarse en el sitio web del proyecto Chromium, uno de los precursores principales de las listas precargadas HSTS.

Ataques a HSTS

A pesar de las listas precargadas, aún existen algunas oportunidades para esquivar este mecanismo de protección, entre ellos:

  • Ataques DNS. Mediante la manipulación de las resoluciones DNS de la víctima podemos evitar que el dominio a atacar sea encontrado en las políticas HSTS manipulando la respuesta DNS que recibe la víctima. Así, y mediante un ataque mitm e interceptando las resoluciones de nombre,  se obligaría a la víctima a conectarse, por ejemplo a «cuentas.google.com» cuando se pretendía conectar a «accounts.google.com» . La manipulación de la resolución DNS engañaría al navegador al no encontrar ese nombre entre sus registros HSTS. Esta aproximación ha sido implementada y presentada en la Blackhat Asia 2014 por Leonardo NVE
  • Ataques basados en tiempo. Esta estrategia consiste en conseguir que la política HSTS caduque con lo cual el navegador, hasta que no renueve recibiendo el parámetro «max-age» visitando de nuevo el sitio, ignorará la obligación de establecer conexión HTTPS. Este el el tipo de ataque es el que vamos a describir aquí, y que fue demostrado por  José Selvi presentando en la BlackHat Europa 2014 su estudio y la correspondiente demostración.

HSTS, listas precargadas y registros dinámicos

Como hemos dicho, si conseguimos de algún modo hacer caducar los registros HSTS que mantiene el navegador, éste ignorará la política correspondiente y no forzará la conexión HTTPS hasta haber actualizado la política. Como podemos ver en las listas precargadas antes referidas, son multitud de sitios los que ya se encuentran enumerados. Observando las cabeceras en una solicitud HTTP podemos encontrar en la respuesta del servidor si éste incorpora HSTS:

 

Cabeceras HSTS

Cabeceras HSTS

En la siguiente imagen observamos como por ejemplo el sitio www.icloud.com no muestra el parámetro «preload» , cosa que sí aparece en facebook.com. De esta sencilla consulta podemos inferir que, presumiblemente www.icloud.com no se encuentra entre los registros precargados del navegador, y por tanto sería vulnerable en una primera visita a un ataque bootsrap.

Efectivamente, comprobamos en el navegador (chrome) que no existe el registro:

icloud hsts

No existe el registro HSTS de www.icloud.com precargado

 

Sin embargo tras visitar https://www.icloud.com:

Registro HSTS de www.icloud.com tras visitar el sitio

Registro HSTS de www.icloud.com tras visitar el sitio

Con estos ejemplos comprobamos que cualquier sitio que incorpore HSTS y que no esté precargado se registrará al visitar por primera vez el sitio HTTPS correspondiente, y quedará dinámicamente almacenado en las políticas del navegador hasta que expire (max-age) o sea eliminado. Las entradas precargadas no se pueden eliminar manualmente

NOTA: El modo en que se administran los registros HSTS depende en última instancia de la implementación propia del navegador en sí, con lo que este comportamiento puede variar entre los distintos navegadores existentes y debe ser comprobado en cada caso.

Hasta ahora mucha teoría, pero… ¿como podemos burlar hsts?

Regreso al futuro, engañando HSTS con ataques NTP

Como se menciona al comienzo del artículo, uno de los posibles métodos para evitar la protección HSTS pasa por hacer creer al navegador que la política ha caducado y de ese modo la ignore. Para ello, y dado que el navegador comprueba el tiempo basándose en la máquina donde corre, si conseguimos modificar el reloj de la máquina víctima a través de un ataque de red, estaremos en condiciones de burlar al navegador (o al menos, intentarlo) y evitar que fuerce una conexión HTTPS. A partir de ese momento, un ataque mitm con sslstrip sería efectivo.

NTP spoofing: Delorean, y directos al futuro

En la pasada BlackHat, el conocido investigador José Selvi (http://www.pentester.es) presentó una herramienta escrita en python como prueba de concepto para sortear HSTS. La herramienta se llama Delorean y hace las veces de servidor NTP el cual podemos configurar para mantenerse a la escucha de solicitudes ntp y responder con los parámetros deseados, en este caso llevar hacia adelante el reloj de la víctima.

Utilizando Delorean, iptables, sslstrip y mitm es posible llevar a cabo un ataque man in the middle y conseguir interceptar el  tráfico HTTPS a pesar de HSTS.

En el siguiente vídeo realizamos una demostración:

Conclusión

A pesar de que en los últimos años se ha avanzado mucho en la seguridad de las comunicaciones, son tan numerosas las variables que intervienen en las mismas, que hacen muy difícil definir un protocolo de comunicación que sea estándar e integrable y que a su vez proporcione una seguridad inquebrantable. HSTS en sí mismo es una muy buena protección pero como hemos visto, factores externos (en este caso un ataque NTP) abren una brecha en su diseño. De la misma forma, este mismo ataque que hemos demostrado aquí, con Ubuntu y Firefox puede no resultar efectivo en otro entorno,  dependiendo del sistema operativo, del mecanismo de sincronización, del sitio a atacar, del navegador, etc. Sin embargo, la posiblidad ahí está.