Detección de contraseñas expuestas mediante Have I Been Pwned y la integración con KV Store de Fastly
Por desgracia, la fuga de datos y el robo de credenciales están a la orden del día desde hace unos años. Debido a la práctica habitual (pero nada aconsejable) de reutilizar credenciales, los ciberdelincuentes pueden llevar a cabo ataques de apropiación de cuentas (ATO)</u> con aquellas que acaban en su poder. Para ello, suelen acudir al relleno de credenciales, técnica que consiste en pasar por todas las credenciales de una lista hasta dar con una que permita acceder sin autorización a la cuenta de un cliente.
La parte buena es que nosotros también podemos acceder a las credenciales expuestas mediante los hashes de contraseñas para detectar estos ataques y ponerles fin. Los hashes de contraseñas existen gracias a Have I Been Pwned</u> (HIBP), un servicio que mantiene una base de datos de contraseñas expuestas y ofrece una API para comprobar si una contraseña lo está, todo de una manera respetuosa con la privacidad. En este artículo hablamos de un método eficaz y de baja latencia para detectar estos ataques almacenando los hashes de contraseñas en dos lugares: un KV Store y Compute, en el edge de Fastly.
Un problema que afecta a miles de millones de credenciales
De acuerdo con Have I Been Pwned</u>, el número de cuentas expuestas ha alcanzado los 12 940 millones</u> en febrero de 2024. Este es el total de cuentas filtradas de muchos sitios web afectados. En algunos casos, una misma credencial (es decir, una combinación de nombre de usuario y contraseña) se utiliza en distintos sitios web. Esta es la reutilización que mencionamos anteriormente; por ejemplo, cuando se emplean las mismas credenciales para acceder a Google y Yahoo. También hay quienes utilizan las mismas contraseñas para distintos nombres de usuario, de ahí que el número de contraseñas esté muy por debajo de los 12 940 millones de cuentas que hemos mencionado anteriormente.
Según nuestro análisis del conjunto de datos de HIBP, el servicio aloja 931 millones de contraseñas diferentes. Este conjunto de datos también incluye la frecuencia</u> con la que se usa cada contraseña y dichos datos se corresponden con 6930 millones de credenciales, por lo que podemos deducir que, de media, el mismo par de credenciales se utiliza para dos cuentas o, dicho de otro modo, dos sitios web.
Algunas contraseñas son más comunes que otras. Por ejemplo, 123456 está presente en 42 millones de credenciales, mientras que hunter2 solo aparece en 24 000. La gráfica de abajo muestra el número total de credenciales y contraseñas, además de la frecuencia con la que se utiliza cada una. Curiosamente, solo se utilizan 34 millones de contraseñas (el 3,6 % de aquellas que están expuestas) en el 60 % de las credenciales expuestas, buena muestra de lo extendida que está la reutilización. Esto se debe a que hay usuarios que acceden a varios sitios web con las mismas credenciales y personas con distintos nombres de usuario que usan las mismas contraseñas pese a no conocerse de nada.
Figura 1: número de credenciales y contraseñas según el conjunto de datos con hashes de contraseñas de Have I Been Pwned
Por otra parte, 532 millones de contraseñas (el 57 % de aquellas que están expuestas) se utilizan en el 94 % de las credenciales expuestas. El crecimiento lineal a partir de este punto nos indica que los otros 400 millones de contraseñas son diferentes entre sí, seguramente porque se han generado mediante gestores de contraseñas y, por tanto, no sirven para llevar a cabo ataques de relleno de credenciales. Las contraseñas generadas mediante gestores solo representan un 6 %. Eso significa que el 94 % tienen papeletas de utilizarse en ataques de relleno de credenciales, que se dice pronto.
Cómo detectar ataques de relleno de credenciales
El uso de gestores para generar contraseñas únicas y autenticarse con ellas en sitios web imposibilita los ataques de relleno de credenciales. Aunque la gráfica de arriba muestra las credenciales expuestas, el conjunto de datos es lo suficientemente grande como para representar también aquellas que no lo están. Como se puede ver, los gestores de contraseñas tienen una adopción muy baja y solo se utilizan para generar un 6 % de las mismas.
La autenticación multifactor con procedimientos de registro y restablecimiento adecuados también resulta eficaz para mitigar el relleno de credenciales y otros ataques de apropiación de cuentas. Luego están las llaves de acceso</u>, un nuevo mecanismo</u> más cómodo y seguro para iniciar sesión que sustituye por completo a las contraseñas. Las llaves de acceso todavía están en una fase de adopción temprana, pero recomendamos utilizarlas allá donde se ofrezcan</u>.
Si ninguno de estos métodos está disponible, resulta fundamental detectar los ataques de manera proactiva para detenerlos. En lo relativo a los «secretos memorizados», el Instituto Nacional de Estándares y Tecnología de Estados Unidos (NIST) recomienda</u> comparar las contraseñas con otras obtenidas de registros de fugas anteriores durante el registro, el inicio de sesión y el restablecimiento.
En una entrada anterior</u> explicamos cómo utilizar la API de HIBP</u> en Compute de Fastly para detectar las contraseñas expuestas que albergan las peticiones. Hoy vamos a describir una nueva estrategia de detección que se desarrolla íntegramente en el edge y que no recurre a la API para cada petición, sino a una versión muy comprimida de los hashes de contraseñas almacenados en el edge. Además de ser mucho más ágil, este nuevo enfoque evita la dependencia de servicios de terceros.
Contraseñas expuestas en el edge
Para poder acceder al conjunto de datos de HIBP con una baja latencia, los hashes de contraseñas se almacenan en un KV Store</u> de Fastly. Un KV Store es un tipo de contenedor que permite almacenar datos como pares clave-valor para su uso en lecturas y escrituras con un gran rendimiento en el edge. Estos contenedores admiten un número ilimitado de claves con un tamaño máximo de 1024 bytes en formato UTF-8. Los valores pueden ser de texto o binarios y tener un tamaño máximo de 25 MB.
Lamentablemente, el conjunto de datos de contraseñas de HIBP contiene una lista descomunal de hashes SHA1 relacionados con contraseñas expuestas y ocupa unos 40 GB en forma de texto sin comprimir, cifra que irá aumentando.
Una mayor optimización con filtros y particiones
Insistimos en el uso del conjunto de datos de HIBP como estructura de datos con filtros en lugar del texto sin comprimir para reducir el consumo de recursos (KV Store y memoria de Compute) y así facilitar el acceso con baja latencia desde Compute de Fastly. Los filtros son estructuras de datos probabilísticos que emplean funciones hash para aleatorizar y representar una serie de elementos de una forma resumida. La principal ventaja de los filtros es que pueden dar falsos positivos, pero no falsos negativos. En otras palabras, existe una pequeñísima posibilidad de identificar una contraseña segura como una contraseña expuesta, pero las contraseñas expuestas siempre se identifican como tales. Al representar los hashes en una estructura de datos con filtros, el tamaño del conjunto pasa de 40 a 1,08 GB, lo que supone una reducción del 97 %.
Figura 2: Compute intercepta las peticiones para comprobar si albergan contraseñas expuestas
Para que el consumo de recursos sea todavía más bajo, los hashes de contraseñas se agrupan mediante prefijos de tres caracteres con un filtro concreto para cada prefijo. Estos filtros se almacenan como valores en el KV Store con el prefijo hash de tres caracteres a modo de clave. En Compute solo se cargan los filtros de los prefijos que hacen falta para comprobar una contraseña determinada, y cada uno ocupa aproximadamente 266 KB.
Cuando se envía una petición que alberga una contraseña, Compute genera un hash SHA1 para ella y utiliza los tres primeros caracteres para obtener el objeto de filtro correspondiente del KV Store. A continuación, se analiza el hash de la contraseña en el filtro para determinar si la contraseña está expuesta, se añade un encabezado «Fastly-Compromised-Password» con los resultados a la petición y esta se envía al origen del backend. De esta forma, el backend puede adaptar su comportamiento en función del estado de la contraseña. Si está expuesta, el backend puede rechazarla (al registrarse), dirigir al usuario a una página en la que puede restablecerla (al iniciar sesión), enviar una señal al detector de relleno de credenciales o tomar otras medidas que considere oportunas.
Hemos experimentado con distintos algoritmos de filtrado (entre ellos los de Cuckoo</u>, XOR</u> y BinaryFuse8</u>) y prefijos hash de longitudes variables para realizar la partición de los datos en el KV Store. Tras estudiar el rendimiento de las búsquedas, el tamaño de los filtros generados, la forma en que el tamaño de los filtros se ve afectado por el de los datos y la velocidad de deserialización de los filtros, llegamos a la conclusión de que los prefijos de tres caracteres con filtros de BinaryFuse8 y huellas digitales de 9 bits ofrecían el equilibrio perfecto. Gracias al tamaño de estas huellas y los factores relativos a la carga de este conjunto de datos, la proporción de falsos positivos del filtro es de aproximadamente un 0,3 %.
Demostración y código fuente
Hemos añadido una demostración</u> de esta estrategia en la sección correspondiente del Developer Hub de Fastly. Te animamos a probarla por tu cuenta y fijarte en el visualizador de registros en tiempo real para familiarizarte con la secuencia de ejecución en Compute. Las figuras 2 y 3 que aparecen abajo muestran un ejemplo de la demo al utilizar una contraseña no segura, que en este caso es «hunter2».
Figura 3: la demostración acepta credenciales en formato de texto no cifrado
Figura 4: la petición enviada al backend se amplía con el encabezado «Fastly-Compromised-Password»
Esta demostración es de código abierto</u>, así que puedes integrar la detección de contraseñas expuestas en tu sitio web. El repositorio también incluye código con el que crear filtros para los hashes y subirlos al KV Store. Aconsejamos regenerar los filtros cada trimestre para mantenerlos al día.