La importancia de una contraseña robusta.

Las empresas alrededor del mundo almacenan sus contraseñas dentro de bases de datos en diversos formatos y codificaciones, principalmente en forma de hash. Toda contraseña puede ser descifrada, existen finitas permutaciones de hash y lo único que podemos hacer es retrasar al atacante lo máximo que podamos.
En este artículo abordaremos la teoría y la matemática detrás del manejo de contraseñas seguras, además de las técnicas utilizadas para acelerar el descifrado.

Qué es un hash

Una función hash es un algoritmo que permite transformar un arreglo de bytes en una cadena de tamaño fijo, además el resultado debe ser siempre el mismo. Algunos ejemplos para la frase “el tractor amarillo que anda por la verde pradera”.

La seguridad de estos algoritmos se mide por la posibilidad de realizar ataques de colisión, en el siguiente ejemplo podemos ver que dos archivos binarios generan el mismo hash MD5:

Protegiendo la contraseña

Dentro de los leaks de contraseñas más populares de los últimos años ha quedado evidenciado que los usuarios tienden a ocupar contraseñas tan simples como: 123456, 123456789, picture1, password, 12345678, 111111, 123123, 12345, 1234567890, senha, amor. Esto demuestra una clara falta de controles y reglamentación en la creación de contraseñas. A continuación, vamos a evaluar técnicas para proteger las contraseñas contra los atacantes, incluso después de haber sido robadas, estas no podrán ser fácilmente descifradas.

Salting

El concepto de salting es concatenar una clave secreta con la clave del usuario para crear un hash, esto permite que una simple contraseña “contraseña123” se transforme en algo como “S3cr37P4zzw0rdcontraseña123”, aumentando considerablemente los esfuerzos necesarios para descifrar esta contraseña.
En el caso de que el atacante haya logrado obtener el código fuente es posible que este obtenga la clave de “salt”, por lo tanto, se deben aplicar controles adicionales a las contraseñas para reforzar la seguridad.

Passphrase

A veces es mejor utilizar una contraseña larga en vez de una contraseña muy compleja. Los ejemplos a continuación solo se podrían calcular mediante colisión, ya que matemáticamente tardaríamos siglos en calcular las permutaciones necesarias:

  • La lógica es el inicio de la sabiduría, no el final
  • No puedo cambiar las leyes de la física
  • Es posible no cometer ningún error y aun así fallar

Algoritmos “caseros”

En unos cuantos proyectos me ha tocado ver patrones de contraseña irregulares, que no se parecen a ningún algoritmo convencional en estructura. Al analizar cientos de muestras de este tipo de implementaciones y aprovechando herramientas como Burp Suite Sequencer, podemos inferir que es un algoritmo débil y probablemente de sustitución:

“Por este motivo, utilizar algoritmos propios que no cumpla con estándares internacionales es una vulnerabilidad.”

Grupos de caracteres

Al solicitar la creación de contraseñas podemos reforzar a nivel de servidor el uso de grupos de caracteres que nos parezcan apropiados, a continuación, listamos algunos grupos de caracteres comúnmente utilizados:

Es posible crear estándares de contraseña exigiendo múltiples elementos de la tabla anterior, esto finalmente aumenta el universo de opciones y fuerza el uso de contraseñas con un mayor grado de seguridad, es decir, poco adivinable.

Reglas comunes

Muchas implementaciones de protección de contraseñas refuerzan validaciones adicionales como las que listamos a continuación.

  • Secuencias de caracteres (123, abc, 456, etc)
  • Datos personales (Fecha de nacimiento, nombres, apellidos)
  • No utilizar contraseñas anteriores
  • El número no puede estar al final
  • La mayúscula no puede ser la primera letra
  • El último carácter no puede ser un símbolo

Las matemáticas y costos del cracking

Existen cuatro formas de “descifrar” una contraseña que ha sido propiamente “hasheada”:

  • Encontrarla en un rainbow table
  • Encontrarla mediante un ataque de diccionario
  • Encontrarla mediante un ataque de fuerza bruta
  • Colisión de hash (No afecta a sha256 hasta hoy)

A continuación, vamos a ver ejercicios de fuerza bruta mediante la generación programática de permutaciones con la herramienta Hashcat para hashes sha256. La herramienta hashcat se puede configurar junto con conjuntos de reglas tales como el universo de caracteres, que comience con mayúscula, que termine con un símbolo, etc.

Para este ejercicio vamos a medir la cantidad de hash por segundo en Mh/s, la cual representa N millones de hash por segundo.
El entorno de pruebas es una máquina de Amazon AWS p3.16xlarge, con un costo por hora de funcionamiento de 24,48usd. Este servidor tiene la capacidad de producir aproximadamente 59971.8Mh/s de sha256.
Es importante notar que los distintos algoritmos generan distintas velocidades en MH/s, por ejempo, bcrypt con sha256 permite crear hashes a una velocidad de 0,43Mh/s, 140.000x más lento que sha256 solo.
Al conocer nuestro universo y cantidad de caracteres, podemos automatizar la herramienta hashcat para realizar todas las permutaciones necesarias hasta dar con la contraseña. La siguiente tabla contiene el universo, la cantidad de permutaciones, un ejemplo, el tiempo de descifrado y el costo en USD.

Estas pruebas se pueden paralelizar, es decir, es posible ejecutar las 7264 horas en un día al distribuir la carga entre 302 servidores. Manteniendo el costo de $177.822 USD

Recomendaciones

Existen múltiples bases de datos de contraseñas y servicios (como haveibeenpwned.com), los cuales permiten conocer el estado de seguridad de alguna contraseña o incluso una cuenta. Pese a que no recomendamos compartir con nadie las contraseñas de sus usuarios, es bueno saber si las contraseñas que ellos utilizan comúnmente en sus plataformas son públicamente explotadas y parte de diccionarios de contraseñas.

  • Utilizar password salting.
  • Utilizar algoritmos de hashing seguros como sha256 y sha512.
  • Utilizar implementaciones seguras de hashing como bcrypt con sha512, la cual fuerza el uso de salts y crea hashes que no se repetirán.
  • Limitar la cantidad de intentos de inicio de sesión.
  • Expirar las contraseñas cada cierto tiempo.
  • Segundo factor de autenticación mediante alguna aplicación de autenticador, hoy en día se duda de la seguridad de los SMS y las llamadas como 2FA.
  • Permitir el uso de caracteres especiales (Unicode) en las contraseñas, incluyendo emojis.

Referencias

(1) https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines
(2) https://pages.nist.gov/800-63-3/sp800-63b.html
(3) https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/04-Authentication_Testing/07-Testing_for_Weak_Password_Policy