Tema 5
Las contraseñas siguen siendo uno de los mecanismos de autenticación más usados, pero también uno de los más atacados. La diferencia entre un sistema razonablemente seguro y uno expuesto suele estar menos en el formulario de login que en cómo se generan, protegen, verifican y almacenan las credenciales.
En la mayoría de los sistemas, el usuario percibe la contraseña como un simple dato que se escribe para ingresar. Desde el punto de vista de seguridad, en cambio, la contraseña es un secreto de alto valor que puede abrir la puerta a datos, operaciones sensibles y movimientos laterales hacia otros servicios.
Por eso el problema no se limita a pedir una clave “fuerte”. Un diseño serio debe contemplar cómo se crea, cómo se transmite, cómo se verifica, cómo se almacena, cómo se resetea y qué ocurre si la base de datos es comprometida.
Este tema se centra en una idea fundamental: un sistema no debería guardar contraseñas de forma recuperable. Debe guardar evidencia verificable derivada de ellas, usando algoritmos adecuados y parámetros resistentes al hardware moderno.
Las contraseñas son populares porque son simples de entender, baratas de implementar y compatibles con casi cualquier dispositivo. Sin embargo, presentan debilidades estructurales:
Eso no significa que haya que abandonarlas automáticamente en todos los contextos, pero sí tratarlas con extremo cuidado y complementarlas cuando el riesgo lo justifique.
Hablar de “contraseña segura” no implica solo longitud o símbolos extraños. Una contraseña es más segura cuando tiene suficiente entropía práctica y no puede adivinarse fácilmente por patrones comunes, información personal o reutilización.
En términos generales, una buena contraseña o frase de paso debería:
En muchos entornos modernos se favorecen contraseñas largas y recordables o frases de paso, antes que reglas artificiales que empujan a los usuarios a usar variantes débiles de una misma clave.
Durante años fue común exigir una mezcla rígida de mayúsculas, minúsculas, números y símbolos, junto con cambios frecuentes obligatorios. Hoy ese enfoque se revisa críticamente porque muchas veces produce malos resultados.
Cuando las reglas son muy artificiales, los usuarios suelen responder con patrones previsibles: reemplazos triviales, sufijos incrementales o reutilización de fórmulas fáciles de recordar. Eso da una ilusión de seguridad, pero no necesariamente mejora la resistencia real frente a ataques.
Por eso muchas recomendaciones actuales priorizan:
Hay errores que siguen apareciendo y son inaceptables en un sistema moderno:
Conviene distinguir tres enfoques muy diferentes:
| Método | Cómo funciona | ¿Es adecuado para contraseñas? |
|---|---|---|
| Texto plano | Se guarda exactamente la contraseña | No, es gravemente inseguro |
| Cifrado reversible | Se puede recuperar la contraseña con una clave | No como almacenamiento principal de password |
| Hash | Se guarda un derivado unidireccional verificable | Sí, si se usa un algoritmo adecuado |
El objetivo del hash es que, al momento del login, el sistema pueda recalcular el derivado de la contraseña ingresada y compararlo con el valor almacenado, sin necesidad de conocer la contraseña original.
Un hash es el resultado de aplicar una función unidireccional a una entrada. En el caso de contraseñas, el sistema toma la contraseña provista por el usuario, le aplica un algoritmo de derivación y almacena el resultado.
Luego, cuando el usuario intenta autenticarse, el sistema repite el proceso con la contraseña ingresada y compara ambos resultados. Si coinciden, se considera válida.
La idea clave es que el hash no debería permitir reconstruir directamente la contraseña original. Pero eso por sí solo no alcanza. Para contraseñas no basta con “cualquier hash”; hace falta un hash pensado específicamente para resistir ataques de fuerza bruta offline.
Funciones como MD5, SHA-1 o incluso SHA-256 son útiles para integridad, firmas o checksums en ciertos contextos, pero no son apropiadas como mecanismo principal para almacenar contraseñas.
El problema no es que sean “hash” y por eso alcancen, sino que son demasiado rápidas. Un atacante con acceso a una base filtrada puede probar enormes cantidades de combinaciones por segundo usando hardware especializado. Cuanto más rápido sea el algoritmo, más viable resulta el ataque offline.
Para contraseñas se necesitan algoritmos deliberadamente costosos en tiempo y, preferentemente, también en memoria. Esa lentitud controlada protege al defensor porque encarece el ataque masivo.
Los algoritmos recomendados para almacenamiento de contraseñas son aquellos diseñados específicamente para este problema. Los más citados hoy son:
La elección concreta depende del entorno, las bibliotecas disponibles y los requisitos operativos, pero la idea es la misma: usar un algoritmo lento, parametrizable y pensado para contraseñas, no una función hash genérica.
Un salt es un valor aleatorio único que se combina con la contraseña antes de derivar el hash. Su propósito principal es evitar que dos usuarios con la misma contraseña terminen con el mismo valor almacenado y dificultar ataques basados en tablas precalculadas.
Si no existiera salt, una base comprometida mostraría patrones peligrosos:
El salt no necesita ser secreto, pero sí único por credencial y generado con suficiente aleatoriedad.
Además del salt, a veces se utiliza un pepper: un secreto adicional no almacenado junto a la base de datos de usuarios, sino en un entorno separado y protegido, como un servicio de secretos o un módulo seguro.
La idea es agregar una capa extra para que una filtración de la base por sí sola no alcance para verificar masivamente contraseñas. Sin embargo, el pepper no reemplaza ni al salt ni al uso de algoritmos adecuados. Es una medida complementaria.
También introduce complejidad operativa: rotación, disponibilidad y gestión segura del secreto. Por eso debe usarse con criterio y no como sustituto de prácticas básicas bien implementadas.
Los algoritmos de password hashing modernos permiten ajustar parámetros para controlar su costo. Ese ajuste es crítico. Un algoritmo correcto con parámetros demasiado débiles puede terminar siendo insuficiente frente al hardware actual.
En general, el objetivo es que la verificación legítima siga siendo aceptable para el sistema y el usuario, pero que un ataque masivo offline resulte costoso. No existe un número universal: debe calibrarse según la infraestructura, el volumen de autenticaciones y la evolución tecnológica.
Esto implica revisar periódicamente los parámetros. La seguridad de hoy puede quedar desactualizada mañana si la capacidad de cómputo cambia o si el sistema lleva muchos años sin ajuste.
Un flujo básico seguro para contraseñas debería verse así:
En ningún punto del flujo el sistema necesita almacenar ni recuperar la contraseña en texto original.
Uno de los objetivos del almacenamiento correcto es reducir el daño si la base de usuarios se filtra. Si las contraseñas están en texto plano o cifradas reversiblemente, la brecha es catastrófica e inmediata. Si están protegidas con algoritmos adecuados y buenos parámetros, el atacante todavía enfrenta un trabajo costoso para romper cada credencial.
Eso no elimina el incidente, pero cambia radicalmente el escenario. Da tiempo para revocar sesiones, forzar reseteos, investigar y contener impacto antes de que una gran cantidad de cuentas queden efectivamente comprometidas.
Un sistema puede tener hashing impecable y aun así ser débil si el proceso de recuperación de cuenta es inseguro. Muchas brechas evitan el login normal y atacan directamente el reseteo.
Buenas prácticas en esta área incluyen:
Una contraseña puede ser robusta en abstracto y aun así estar comprometida si ya apareció en filtraciones previas. Por eso muchos sistemas modernos validan nuevas contraseñas contra listas de secretos conocidos como expuestos o demasiado comunes.
Esta práctica es más útil que imponer reglas arbitrarias de símbolos si permite bloquear claves previsibles o recicladas masivamente. También es importante educar al usuario para no reutilizar la misma contraseña entre servicios, especialmente si no utiliza un gestor de contraseñas.
La presencia de MFA mejora mucho el panorama, pero no autoriza a descuidar las contraseñas. Si el factor principal es débil, el sistema sigue expuesto a múltiples formas de abuso: phishing parcial, password spraying, soporte fraudulento, takeover de cuentas con segundo factor comprometido o flujos alternativos mal resueltos.
La contraseña debe seguir tratándose como un secreto de alto valor, aunque luego exista MFA. La defensa en profundidad exige proteger ambos niveles, no confiar en que uno compensa totalmente la fragilidad del otro.
Las contraseñas siguen presentes en gran parte de los sistemas, pero su seguridad no depende de slogans sobre complejidad. Depende de decisiones concretas: qué algoritmos se usan, cómo se parametrizan, cómo se almacenan los derivados, cómo se gestionan los resets y cómo se reduce el impacto de una eventual filtración.
En el próximo tema veremos autenticación multifactor con más detalle: sus variantes, sus beneficios reales y los criterios para implementarla sin caer en una falsa sensación de seguridad.