Archivo de la etiqueta: hash

Podcast – 38 – Ataques a contraseñas hasheadas

Fuente imagen: Sifi Feefer

Recientemente recibí un correo electrónico de un proveedor avisándome de que debido a un acceso no autorizado a sus servidores un atacante se había hecho con la información de mi usuario y su correspondiente contraseña hasheada. En ese mismo correo aseguraban que la contraseña estaba protegida por la función de hash por lo que el atacante no podía descubrirla, pero aún así me obligaban a cambiarla… ¿No es esto una incongruencia? ¿Si está a salvo por qué me obligan a cambiarla?

Dejando de lado el dicho de que ‘más vale prevenir que curar’, la verdad es que una contraseña bien hasheada está bien protegida, pero no perfectamente protegida… y los crackers tienen técnicas para realizar ataques a contraseñas hasheadas y averiguarlas. Veamos las tres principales.

Aunque hablé más a fondo sobre cómo almacenar contraseñas de forma segura en el capítulo 11, podemos resumir la operativa de almacenamiento sería aplicar una función hash sobre la contraseña recibida y almacenar únicamente el resultado de la función hash. NUNCA deberíamos guardar la contraseña sino únicamente el resultado de la función hash. Sabemos que una función hash es un sistema de un solo sentido de tal forma que una misma cadena de entrada siempre devuelva el mismo resultado, pero que sea “computacionalmente imposible” obtener la cadena de entrada (es decir, la contraseña) teniendo únicamente la salida.

Ataques a contraseñas hasheadas

  1. La primera opción sería un ataque de fuerza bruta para conseguir encontrar qué contraseña genera un hash como el obtenido. Así el atacante tan sólo debe probar todas y cada una de las posibles combinaciones de caracteres para ver si el resultado de aplicarle una función hash es igual al de nuestra contraseña. Como entenderás se trata de un proceso que requiere de una capacidad de computación importante, sobre todo si usamos contraseñas largas e incluimos caracteres no alfanuméricos. Aunque es un proceso que con el tiempo será efectivo (en algún momento probará nuestra contraseña) no es muy eficiente en tiempo (pueden pasar años o siglos para localizar una password compleja), por lo que no es muy común su uso (salvo que sepamos a ciencia cierta que la contraseña es corta).
  2. Otra opción es aplicar la función de hash a un grupo concreto de contraseñas que tengamos almacenadas y ver si alguna coincide con el hash que queremos descubrir. Se suele denominar diccionario al listado de claves que queremos comprobar. Existen multitud de diccionarios con las contraseñas más utilizadas; combinaciones de palabras y números comunes; expresiones de uso común en casi cualquier idioma; etc… con lo que se puede sacar una lista de contraseñas probables. Entonces se cogen todas estas claves posibles (los listados puedes ser miles o millones de combinaciones) y se aplica la función de hash a cada una de ellas comparándola con la de la contraseña que queremos romper. Los ataques de diccionario son muy útiles cuando el atacante ha conseguido un gran listado de hashes sobre los que comparar. Pensad en las noticias de filtraciones de grandes empresas con miles o millones de usuarios: es muy probable que dentro de esos millones de usuarios haya centenares o miles de ellos que utilicen como contraseña una de las incluidas dentro del diccionario inicial. Así pues, los ataques de diccionarios son un sistema eficiente de encontrar alguna contraseña en un listado grande de víctimas, aunque no tanto cuando se busca una contraseña en concreto (aunque cómo son rápidos de ejecutar, es probablemente el primero que un atacante intente).
  3. La tercera estrategia que se encuentra en un punto intermedio, computacionalmente hablando, entre las dos anteriores los las denominadas rainbow table (aunque en español se llamarían «tablas arcoíris«, la verdad es que nunca las he oído llamar así). Se trata de tablas de hash precompiladas, específicas para cada protocolo, que relacionan distintas contraseñas con sus correspondientes hashes, aunque la relación no es uno-uno como sería el caso de los ataques por diccionario, sino que incluyen una serie de pasos intermedios que no son almacenados pero que son accesibles con los datos de la tabla. Así tenemos un sistema que implica una mayor necesidad de computación que los ataques de diccionario, pero muchísimo menos espacio de almacenamiento. A grandes rasgos podemos decir que una rainbow table aplica dos funciones (la de hash y otra denominada de reducción) varias veces de tal forma que el resultado de una función sirve como entrada de la siguiente ronda. Finalmente, tras las rondas correspondientes se almacena únicamente la entrada inicial y el resultado final, pero no los resultados intermedios. En el momento de querer sacar una contraseña se aplican las funciones de hash y reducción según el algoritmo de la tabla de reducción, permitiendo la detección de la contraseña correcta no sólo por las dos columnas almacenadas, sino también por los resultados intermedios que son calculados al vuelo. El procedimiento y las funciones utilizadas dependen de cada ‘tabla arcoíris’.

Como ves, los atacantes tienen estrategias para conseguir sacar la contraseña real del hash obtenido, y es por ello que las empresas afectadas por este tipo de filtraciones solicitan, u obligan, a sus usuarios a cambiar su contraseña de acceso: porque el atacante no tiene ahora mismo la contraseña pero puede llegar a tenerla (sobre todo si usamos claves cortas o que usen palabras/combinaciones comunes).

Descarga directa.

Podcast – 11 – Almacenar contraseñas de forma segura

Tras varias noticias sobre robo de contraseñas en diferentes sistemas (Yahoo, Dropbox, LinkedIn, etc.), en el capítulo de hoy veremos cómo se almacenan estas contraseñas en un sistema seguro.

Salt and Pepper

Fuente: PotteryBarn

La idea es almacenar una forma de identificarnos de tal manera que aunque alguien consiga obtener esa información no sea capaz de obtener la contraseña inicial. Para esto se recurre a las funciones matemáticas de resumen (hash en inglés). Estas funciones tienen una serie de características que nos aseguran que es computacionalmente inviable obtener la contraseña inicial aunque se tenga el resultado final.

De igual forma explico las funcionalidades ‘Salt’ y ‘Peeper’ y cómo estas técnicas ayudan a mejorar la seguridad de nuestras contraseñas frente a ataques mediante tablas de resultados precalculadas.

Descarga directa.

Micropíldora – Sistema autenticación en GNU/Linux

Autenticación en Linux

Autenticación en Linux
Fuente imagen: AcercaDeUbuntu

En esta micropíldora explicaré el funcionamiento tradicional, y su evolución actual, del sistema de autenticación en local de los sistemas basados en GNU/Linux (Debia, RedHat, IOS, etc.). Aunque hoy en día existen múltiples posibilidades de autenticación remota (LDAP, Kerberos, etc.), la autenticación local sigue operativa en la gran mayoría de instalaciones. No profundizaré en los diferentes algoritmos utilizados, cosa que da para un artículo más extenso, sino en las estrategias elegidas así como sus motivaciones para elegirlas.

Aunque es un artículo básico se presupone un mínimo conocimiento de la estructura  del sistema operativo GNU/Linux.

Sistema de autenticación tradicional

Desde su definición el sistema GNU/Linux ha sido desarrollado teniendo en mente un sistema multiusuario, cosa no muy extendida en la época, por lo que desde el principio contaba con un sistema de autenticación de los diferentes usuarios que podían utilizar el sistema. Así pues se creó un fichero de sistema (/etc/passwd) en el cual se almacena la información del usuario que es necesaria para que el sistema pueda trabajar con normalidad.

Veamos un ejemplo de una línea de este fichero público:

andreu:S1p7e8INZ512o:1011:1000:Andres Adrover:/home/andreu:/bin/sh

Donde separados por el símbolo de dos puntos (:) podemos ver los siguientes valores:

  1. andreu: El nombre de usuario al que hace referencia esta información.
  2. S1p7e8INZ512o: Información para validar la contraseña. Por norma se trata del resultado obtenido al pasar la contraseña real por una función hash. Permite pues comparar que la contraseña introducida sea la misma (si da el mismo resultado) que la elegida anteriormente.
  3. 1011: Identificador numérico de usuario. Debe ser único en el equipo y es utilizado por el sistema de forma interna (control de permisos de acceso, gestión de procesos lanzados, etc.)
  4. 1000: Identificado numérico del grupo al que pertenece el usuario. Al igual que el campo anterior es utilizado por el sistema operativo.
  5. Andres Adrover: Este campo es de libre escritura aunque se definió para indicar los datos completos del usuario, dirección, teléfono, etc.
  6. /home/andreu: Identifica el directorio raíz de ese usuario
  7. /bin/sh: Indica qué programa debe ejecutarse nada más autenticarse el usuario. Para usuarios humanos siempre será un intérprete de comandos (sh, bash, ksh…)

Como se puede observar no se guarda la contraseña en claro en este fichero, sino el resultado de aplicarle una función hash, por lo que en su momento se consideró que era un sistema suficientemente seguro. La idea es que, aunque el fichero /etc/passwd es de acceso libre y cualquiera puede obtener el valor hash de las contraseñas de todos los usuarios no sería factible obtener las contraseñas de dichos valores.

Sistema actual de autenticación en Linux

Estas apreciaciones de seguridad fueron válidas durante décadas, pero la aparición de debilidades en las funciones hash usadas (MD5, SHA1, Blowfish…) hizo que la obtención de contraseñas válidas a partir de los valores almacenados en el fichero /etc/passwd pasara a ser factible.

Así se generó una nueva estrategia:

  • Se mantiene el fichero público /etc/passwd con toda la información útil del usuario pero en el campo contraseña (el segundo) sólo habrá el valor ‘x’.
  • Se crea un nuevo fichero /etc/shadow sólo visible por el usuario root para gestionar la información de contraseña

El mero hecho de separar la gestión de credenciales y llevarla a un fichero no público ya es una importante mejora, pero además se añadieron nuevas funcionalidades criptográficas para dificultar, aún más, la obtención de contraseñas válidas aunque se obtuviera el acceso al nuevo fichero.

El formato de este neuvo fichero podría ser el siguiente:

andreu:$1$S1p7e8INZ512o:13054:0:365:7:10:99999:

Donde:

  1. andreu: el nombre de usuario
  2. $1$S1p7e8INZ512o: Resultado de la función hash de la contraseña
  3. 13054: El días, contado desde 1 de enero de 1970, en el que se cambió la contraseña por última vez
  4. 0: Mínimo número de días que deben pasar entre cambios de contraseña
  5. 365: Número máximo de días en el que una contraseña es válida
  6. 7: Número de días antes de que caduque en el que nos avisa el sistema
  7. 10: Número de días en el que la cuenta se expirará una vez caducada la contraseña
  8. 99999: Fecha, contada desde el 1 de enero de 1970, en el que la cuenta caducará

Como se puede observar este nuevo fichero abre un mayor abanico de posibilidades para la gestión de usuarios y contraseñas en los sistemas basados en Linux.

Otro punto importante es la elección de las funciones hash posibles y el uso, obligatorio, de expresiones «Salt» que dificultan en gran medida los posibles ataques por diccionario.


Obviamente mi contraseña no tiene ese hash 😉