Tema representativo de entrevista

Entrevista de Backend: ¿Cómo almacenar contraseñas de forma segura y migrar hashes heredados?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Un producto SaaS con 10,000,000 de cuentas almacena una mezcla de registros de contraseñas en bcrypt, PBKDF2 y SHA-256 sin sal (unsalted). Diseñe su migración a Argon2id. Cubra el formato del registro, la medición de parámetros, la verificación de inicio de sesión y actualizaciones concurrentes, cuentas inactivas por mucho tiempo, peppers, respuesta a filtraciones, defensas contra la enumeración de cuentas y agotamiento de recursos, y criterios verificables de despliegue y finalización.

Pregunta y alcance

Un producto SaaS con 10,000,000 de cuentas está rediseñando la autenticación por contraseña. Alrededor de 7,000,000 de registros de la base de datos utilizan bcrypt con costo 10, 2,000,000 usan PBKDF2-HMAC-SHA256 con 210000 iteraciones y 1,000,000 usan SHA-256 sin una sal por registro. Los formatos existentes son inconsistentes y algunas filas no identifican directamente su algoritmo y parámetros. En el pico de carga, el servicio de autenticación debe manejar 1500 verificaciones de contraseña por segundo. Cada instancia permite como máximo 24 hashes costosos concurrentes.

Diseñe una migración completa a Argon2id. Explique el modelo de amenazas, la selección de parámetros y la medición de capacidad, el formato de almacenamiento evolutivo, la verificación de algoritmos mixtos, la actualización en el momento del inicio de sesión, los cambios de contraseña concurrentes, las cuentas inactivas por mucho tiempo, la gestión de pepper, la respuesta ante la exposición de la base de datos o de claves, las defensas contra enumeración de cuentas y agotamiento de recursos, y los criterios de despliegue y finalización. La cantidad de cuentas, la mezcla de algoritmos, los parámetros heredados y el límite de concurrencia son restricciones de la entrevista, no umbrales de seguridad universales.

Esta es una pregunta de seguridad de backend e ingeniería de autenticación. El verificador de credenciales y la máquina de estados de migración son el foco principal. Un diseño completo de registro, recuperación de contraseñas, MFA o sesiones queda fuera del alcance, excepto donde esos flujos afecten la migración de credenciales o la respuesta a filtraciones.

Qué está evaluando el entrevistador

Primero, ¿puede el candidato distinguir la adivinación en línea (online guessing) del descifrado fuera de línea (offline cracking)? Los límites de tasa (rate limits) restringen un endpoint de inicio de sesión, pero no restringen a un atacante que ha obtenido la base de datos de hashes. Las contraseñas son secretos humanos de baja entropía. Un resumen rápido como SHA-256 permite a un atacante enumerar candidatos rápidamente; un hash específico para contraseñas eleva el costo de cada intento mediante una sal por registro, cómputo ajustable y costo de memoria.

Segundo, ¿comprende el candidato que los parámetros deben medirse contra la capacidad real? “Usar Argon2id” elige un algoritmo pero no concluye el diseño. Una respuesta completa selecciona la memoria m, las iteraciones t, el paralelismo p, la longitud de la sal y la longitud de la salida, y luego calcula cómo la verificación concurrente afecta la memoria, la CPU, la latencia y la exposición a la denegación de servicio. Parámetros más altos no son automáticamente más seguros. Si el tráfico de ataque agota la memoria del servicio, la disponibilidad de la autenticación falla primero.

Tercero, ¿puede el candidato migrar datos irreversibles? El sistema no conoce la contraseña en texto plano de cada usuario, por lo que no puede descifrar los resultados de bcrypt fuera de línea y convertirlos a Argon2id. El camino habitual es verificar un registro heredado con éxito y usar el texto plano suministrado en esa solicitud para crear un registro actual. Las cuentas inactivas durante mucho tiempo requieren un verificador heredado controlado, un envoltorio temporal (wrapping) o un restablecimiento, según el riesgo del algoritmo heredado y el historial de exposición.

Finalmente, una respuesta sólida maneja las condiciones de carrera (race conditions) y los límites operativos. Una actualización en el inicio de sesión no debe sobrescribir un restablecimiento de contraseña concurrente. Un pepper no debe residir junto a la base de datos de hashes. Las versiones de los algoritmos, los parámetros y el estado de la migración necesitan observabilidad, pero los registros (logs) no deben contener contraseñas, hashes completos ni peppers. “El nuevo código está desplegado” no es un criterio de finalización.

Aclaraciones antes de responder

  • ¿Se puede identificar de forma confiable cada formato existente? Establezca el algoritmo, los parámetros, la codificación de caracteres, la ubicación de la sal y la versión histórica de la biblioteca. No adivine un formato ni pruebe varios verificadores para una fila no identificable.
  • ¿Cómo manejaba el bcrypt heredado las entradas de más de 72 bytes? Reproduzca la codificación y la semántica de truncamiento de la implementación histórica para que la migración no cambie silenciosamente la credencial efectiva del usuario.
  • ¿Se ha expuesto alguna vez la base de datos, una copia de seguridad o un conjunto de hashes heredados? Envolver la base de datos actual no puede revertir un resumen rápido sin sal que ya fue expuesto. Pueden ser necesarios restablecimientos forzados y acciones sobre las sesiones.
  • ¿Cuál es el presupuesto real de recursos de la instancia de autenticación? Obtenga la memoria base, la cuota de CPU, el límite de concurrencia de hashes, la velocidad de escalado automático, la latencia objetivo p95 y p99, y la tasa de fallas aceptable.
  • ¿Aplican restricciones de FIPS u otras normativas de cumplimiento? Pueden restringir algoritmos e implementaciones, pero una etiqueta de cumplimiento no reemplaza la medición de parámetros ni el diseño de la migración.
  • ¿Existe ya un pepper? Confirme su almacenamiento, dependencia de llamadas, versiones, capacidad de rotación, límite de auditoría y comportamiento cuando el servicio de claves no está disponible.
  • ¿Cuáles son los límites de transacción para los cambios de contraseña y la emisión de sesiones? El orden de la migración, el restablecimiento concurrente y la emisión de sesiones debe ser explícito, o una contraseña antigua podría obtener una nueva sesión después de un restablecimiento.
  • ¿Cómo deben dividir el valor comercial y el riesgo a las cuentas inactivas por mucho tiempo? Las cuentas privilegiadas, las activas recientemente y las inactivas durante años pueden tener diferentes plazos y requisitos de reverificación.

Marco de respuesta en 30 segundos

“Definiría el objetivo principal como la resistencia a la adivinación fuera de línea tras una filtración de la base de datos de hashes y protegería la capacidad de autenticación en línea por separado. Las nuevas contraseñas utilizan Argon2id con una sal aleatoria independiente. El registro lleva el algoritmo, la versión, m/t/p, la sal y la salida. Si usamos un pepper, este reside en un sistema de claves fuera de la base de datos. Utilizaría el mínimo actual de OWASP como punto de partida candidato, y luego realizaría pruebas de carga en instancias equivalentes a producción para memoria concurrente, CPU y latencia p99 en lugar de copiar un solo valor.

Al iniciar sesión, la versión declarada en el registro selecciona exactamente un verificador heredado. Tras una verificación exitosa, calculo el registro actual de Argon2id y realizo un compare-and-swap contra el hash antiguo. Si un cambio concurrente hace que eso falle, recargo y verifico el registro más reciente en lugar de sobrescribir un restablecimiento de contraseña. Las contraseñas nuevas y restablecidas utilizan el formato actual de inmediato. Las cuentas con SHA-256 sin sal reciben un plazo de migración más corto; cuando no se disponga de un envoltorio seguro o haya ocurrido una exposición, deben restablecerse.

El endpoint utiliza errores uniformes, un hash simulado (dummy) actual, límites de tasa independientes por cuenta y origen, y concurrencia de hash acotada para resistir la enumeración y el agotamiento de memoria. Después del lanzamiento, rastreo la migración por versión de algoritmo, latencia, memoria, fallas, conflictos de CAS y finalización de restablecimientos. Declaro la finalización solo después de que los formatos heredados de alto riesgo lleguen a cero, se superen las pruebas de condiciones de carrera y carga máxima, y un ejercicio de rotación de claves sea exitoso.”

Explicación paso a paso

Paso 1: Separar las superficies de ataque en línea y fuera de línea

El inicio de sesión normal es la ruta en línea. El rendimiento del endpoint, los controles por cuenta, los controles por origen, los sistemas de riesgo y el monitoreo restringen al atacante. Adivinar después de una filtración de la base de datos es la ruta fuera de línea: el atacante ejecuta el verificador en sus propias GPU, ASIC o instancias en la nube sin los límites de tasa de la aplicación. El almacenamiento de contraseñas eleva principalmente el costo de cada intento candidato en esa segunda ruta.

SHA-256 sin sal tiene dos problemas. Es rápido, y la misma contraseña produce el mismo resumen, por lo que un atacante puede reutilizar trabajo precalculado e identificar grupos que reutilizan una contraseña. Una sal aleatoria independiente para cada registro hace que contraseñas iguales produzcan salidas diferentes y fuerza el trabajo por registro. La sal puede almacenarse con el hash y no necesita ser secreta. Una sal no convierte a SHA-256 rápido en un hash de contraseñas adecuado; la resistencia significativa proviene de un algoritmo dedicado, ajustable y preferiblemente duro en memoria (memory-hard).

Un pepper es un control independiente. Es un secreto del lado del servidor compartido entre registros o gestionado por versión, y debe separarse de la base de datos de contraseñas, típicamente en un servicio de gestión de claves, HSM o entorno de ejecución protegido. Puede reducir el impacto de una filtración exclusiva de la base de datos, pero no reemplaza ni las sales por registro ni el hashing lento. Si la base de datos y el pepper quedan expuestos, el procesamiento por lotes en la base de datos no puede volver a generar claves de forma segura para los registros afectados porque el servicio no posee las contraseñas en texto plano de los usuarios.

Paso 2: Seleccionar parámetros y calcular la capacidad de autenticación

Para registros nuevos, utilice una implementación mantenida de Argon2id. Un candidato mínimo actual de OWASP es m=19456 KiB, t=2 y p=1. El RFC 9106 ofrece recomendaciones generales de mayor memoria, incluyendo 64 MiB, tres pasadas y cuatro carriles (lanes) para una opción con restricciones de memoria. Los documentos apuntan a diferentes restricciones operativas, por lo que ninguna tupla es una constante universal para servicios web.

Un proceso de selección más defendible es:

  1. Partir de un candidato revisado en la misma CPU, límite de memoria y entorno de ejecución utilizados en producción.
  2. Medir la mediana, p95, p99 de verificación individual, la memoria residente real y el tiempo de CPU.
  3. Probar la carga con una mezcla de tráfico pico normal, ráfagas de inicio de sesión, contraseñas incorrectas y cuentas inexistentes.
  4. Acotar la concurrencia y observar el tiempo en cola, los errores de OOM del contenedor, el estrangulamiento de CPU (CPU throttling) y los tiempos de espera agotados aguas arriba.
  5. Elegir el costo para el atacante más alto que sea sostenible dentro del presupuesto de disponibilidad, y registrar el hardware, la versión de la biblioteca y la fecha de medición.

A 19 MiB, la memoria de trabajo teórica de hash para 24 operaciones simultáneas ya es de 456 MiB, antes del uso base del proceso, la sobrecarga de la biblioteca, los objetos de solicitud y el margen de seguridad. Si una verificación toma 250 milisegundos en la instancia de destino, su máximo aproximado es de unas 96 finalizaciones por segundo. Atender 1500 por segundo requiere al menos unas 16 instancias equivalentes disponibles continuamente, con margen adicional para latencia de cola, fallas y retraso del escalado automático. Estos cálculos exponen el orden de magnitud de la capacidad; las pruebas de carga determinan los valores finales.

Utilice una sal aleatoria nueva e independiente de 128 bits por registro y, por ejemplo, una salida de 256 bits. Deje que una biblioteca madura genere y analice la codificación estándar en lugar de ensamblar los campos criptográficos manualmente. La entrada de la contraseña necesita una codificación de bytes estable y documentada antes del hashing. Si se acepta Unicode, defina la normalización y aplíquela consistentemente durante el registro, inicio de sesión y migración.

Paso 3: Hacer que los registros de credenciales sean autodescriptivos y evolutivos

El registro debe llevar la información no secreta necesaria para la verificación. Una codificación de Argon2 puede verse así:

text
$argon2id$v=19$m=19456,t=2,p=1$SALT_BASE64$TAG_BASE64

Los formatos heredados también necesitan mapeos deterministas como {bcrypt}, {pbkdf2-sha256} y {sha256-legacy}. Una etiqueta es un protocolo de análisis sintáctico, no un respaldo de seguridad. Rechace una etiqueta desconocida, un campo faltante, un valor en Base64 inválido o un parámetro fuera de política y envíe la cuenta a una cola de recuperación controlada. No pruebe algoritmos en secuencia hasta que uno coincida por casualidad.

El análisis de parámetros necesita límites superiores. Si un atacante pudiera alterar un registro, podría establecer valores extremos de memoria o iteraciones y consumir recursos del servicio mediante una solicitud de inicio de sesión. El verificador acepta solo algoritmos desplegados y rangos de parámetros permitidos. Un registro fuera de rango produce un evento de seguridad sin datos confidenciales y requiere la recuperación de la cuenta.

La tabla de credenciales necesita al menos la codificación actual, el momento de actualización de la credencial y el estado de disposición de seguridad. Los reportes de migración pueden agregarse a partir del prefijo de codificación o de un scheme_id de baja cardinalidad. Nunca coloque un hash completo, sal, contraseña candidata, secreto de pepper o intermedio de verificación en registros, etiquetas de métricas o sistemas de analítica.

Paso 4: Actualizar de forma segura tras un inicio de sesión exitoso

La función de migración analiza el registro e invoca el único verificador coincidente. Solo después de que una credencial heredada tiene éxito, el servicio dispone del texto plano correcto de esta solicitud y puede calcular un registro Argon2id actual. Mantenga el trabajo costoso fuera de la transacción corta de base de datos y condicione la escritura al registro antiguo:

text
record = loadCredential(userId)
ok = verifyByDeclaredScheme(record.hash, submittedPassword)
if !ok: rejectWithGenericError()

if needsRehash(record.hash):
  upgraded = hashWithCurrentPolicy(submittedPassword)
  changed = compareAndSwap(userId, expected=record.hash, replacement=upgraded)
  if !changed:
    latest = loadCredential(userId)
    if !verifyByDeclaredScheme(latest.hash, submittedPassword):
      rejectAndAskForFreshLogin()

issueSessionAfterCredentialStateIsConfirmed()

El compare-and-swap evita que una actualización en el inicio de sesión sobrescriba un restablecimiento de contraseña concurrente. Una actualización condicional fallida puede significar que otro inicio de sesión completó la misma migración o que el usuario acaba de seleccionar una contraseña diferente. Recargue y verifique la entrada actual contra el registro más reciente; no emita una sesión simplemente porque el registro antiguo coincidió alguna vez. El registro, los cambios voluntarios de contraseña y la recuperación de contraseñas escriben el formato actual directamente y nunca crean otro registro heredado.

La política de riesgo determina si el inicio de sesión puede continuar cuando falla la escritura de actualización. Un error reintentable de base de datos puede dejar temporalmente un registro heredado aceptable y emitir un evento de falla de migración. Un formato de alto riesgo puede requerir una actualización exitosa antes de la emisión de la sesión. En cualquier caso, limite los reintentos para que un inicio de sesión no ejecute varios hashes costosos indefinidamente.

Paso 5: Tratar los formatos heredados aceptables y de alto riesgo de manera diferente

Bcrypt y un PBKDF2 suficientemente fuerte pueden conservar la verificación de solo lectura durante un período de migración controlado y actualizarse tras un inicio de sesión exitoso. Minimice la exposición de los verificadores heredados: solo sirven a registros existentes y no pueden crear nuevas credenciales. Rastree las cuentas restantes, la actividad y la velocidad de migración para cada formato. Antes de eliminar un verificador en su fecha límite, resuelva cada cuenta que aún dependa de él.

SHA-256 sin sal presenta un riesgo mayor. Si no ha ocurrido ninguna exposición y un restablecimiento universal inmediato es inviable, el servicio puede tratar el resumen existente como entrada para un algoritmo externo lento con sal nueva como endurecimiento temporal de la base de datos. La verificación primero reproduce la operación histórica de SHA-256 y luego verifica la capa externa. Tras un inicio de sesión exitoso, el servicio todavía lo reemplaza con un registro Argon2id estándar calculado a partir de la contraseña enviada.

Ese envoltorio no equivale a Argon2id(password). No puede revertir un resumen interno que ya se haya filtrado, y no repara problemas históricos de codificación, truncamiento o contraseñas débiles. Si se expuso un hash heredado o una copia de seguridad, la cuenta es privilegiada o la semántica del formato es incierta, exija un restablecimiento, revoque las sesiones relevantes y recupere mediante un flujo de verificación independiente. A las cuentas ordinarias inactivas durante años también se les puede congelar el inicio de sesión por contraseña en la fecha límite y usar la recuperación al regresar en lugar de mantener el verificador más débil para siempre.

Paso 6: Diseñar versiones de pepper y respuesta a filtraciones

Si se utiliza un pepper, un paso de preprocesamiento con clave revisado puede preceder al hash de la contraseña, o un HMAC puede proteger su salida. Una construcción madura y una revisión de seguridad deben decidir la composición exacta. La base de datos almacena solo un identificador de versión de pepper no secreto; la clave real permanece fuera de la base de datos y de sus copias de seguridad. El servicio de autenticación utiliza acceso de mínimo privilegio, con un tiempo de vida en caché explícito y comportamiento definido durante fallas del servicio de claves.

La rotación rutinaria puede mantener brevemente las claves actual y anterior. Tras una verificación exitosa con la versión antigua, recalcule el registro completo a partir del texto plano enviado y el pepper actual. Las claves antiguas no pueden permanecer indefinidamente. Un plan de rotación cuenta las cuentas en la versión anterior y asigna una ruta de restablecimiento o congelamiento a aquellas que no migren.

Estratifique la respuesta a filtraciones según la evidencia:

  • Solo base de datos: preserve la evidencia, cierre el punto de entrada, aumente el monitoreo y decida los restablecimientos tras evaluar los algoritmos y parámetros. Un pepper secreto aporta defensa adicional pero no hace seguras las contraseñas débiles.
  • Solo pepper: rote la clave, investigue los registros de acceso y determine si el atacante también pudo haber obtenido la base de datos de hashes.
  • Base de datos y pepper coincidente: maneje esto como una exposición de hashes de contraseñas, fuerce a las cuentas afectadas a restablecerse, revoque o acorte las sesiones relevantes y advierta a los usuarios que cambien contraseñas reutilizadas.

Una rotación exitosa no borra la exposición histórica. El registro del incidente debe cubrir las versiones afectadas, el alcance de cuentas, copias de seguridad, sesiones, notificación, porcentaje de finalización y excepciones residuales.

Paso 7: Resistir la enumeración y el agotamiento de recursos conjuntamente

Las cuentas inexistentes, contraseñas incorrectas, cuentas deshabilitadas y fallas de migración devuelven la misma semántica de error externo, incluyendo estado y forma de respuesta consistentes. Para una cuenta inexistente, ejecute un hash simulado controlado bajo la política actual para reducir la brecha evidente entre un retorno inmediato y una verificación costosa. Los algoritmos heredados mixtos aún pueden presentar diferencias de tiempo. La migración, el endurecimiento en tiempo de ejecución y la medición estadística deben reducir las diferencias explotables; no prometa que cada respuesta de red sea perfectamente de tiempo constante.

El hashing costoso en sí mismo crea una superficie de denegación de servicio. Antes de la cola de hash, realice una limitación de tasa gruesa por origen y comprobaciones de validez de solicitud que no revelen si una cuenta existe. Para el trabajo admitido, aplique cuotas independientes por cuenta y origen, una cola global acotada y 24 permisos de concurrencia por instancia. Un solo bucket indexado por un par de IP y nombre de usuario permite a un atacante cambiar una dimensión repetidamente y eludir los límites agregados.

Cuando la cola esté llena, falle rápido con una respuesta temporal uniforme en lugar de acumular trabajo sin límite. Las señales de escalado deben incluir tiempo en cola, hashes activos, margen de memoria y estrangulamiento de CPU, no solo el recuento de solicitudes. Los registros contienen un identificador de cuenta interno irreversible, una versión de esquema de baja cardinalidad, clase de resultado, dimensión de limitación y rango de latencia. No contienen ninguna contraseña enviada, registro de credencial completo ni material de claves.

Paso 8: Desplegar en etapas y aceptar con evidencia

Comience con un inventario de solo lectura. Confirme que cada registro heredado se analice correctamente y verifique las implementaciones históricas con vectores de prueba conocidos en un entorno aislado. Luego, despliegue código que pueda leer todos los formatos heredados admitidos pero que escriba solo el formato actual. Haga que los nuevos registros y cambios de contraseña escriban en Argon2id primero. Habilite las actualizaciones en el inicio de sesión para una pequeña cohorte, observe los conflictos de CAS, fallas de verificación y curvas de recursos, y expanda gradualmente.

Antes del lanzamiento total, verifique al menos:

  • Comportamiento con contraseña correcta, contraseña incorrecta, longitud límite, Unicode y registros malformados para cada formato histórico.
  • Condiciones de carrera entre la actualización de inicio de sesión y el restablecimiento de contraseña concurrente, demostrando que un inicio de sesión antiguo no puede sobrescribir la nueva contraseña ni emitir una sesión inválida.
  • Ejercicios de rotación y falla para versiones de pepper actuales, anteriores y desconocidas.
  • Latencia, memoria, CPU, puesta en cola y escalado a las 1500 verificaciones por segundo objetivo con tráfico de ataque mixto.
  • Distribuciones de mensajes, estado, tamaño y latencia para cuentas inexistentes y cada clase de falla.
  • Escaneos de campos confidenciales en la base de datos, copias de seguridad, registros, métricas y rastreo de errores.

El panel de control de migración agrupa por algoritmo y nivel de riesgo: recuento total, recuento activo recientemente, actualizaciones diarias exitosas, motivos de falla, finalización de restablecimiento obligatorio y fecha límite. La finalización técnica significa que cada nueva escritura utiliza la política actual; SHA-256 sin sal y las versiones expuestas están en cero; los verificadores heredados innecesarios se eliminan; los formatos heredados aceptables restantes tienen excepciones documentadas; las pruebas de carga máxima y condiciones de carrera son satisfactorias; los ejercicios de rotación de pepper y recuperación cuentan con evidencia; y el SLO de autenticación se mantiene dentro del acuerdo.

Respuesta de ejemplo de alta calidad

“Primero separaría las dos superficies de ataque. Los controles de endpoint restringen los ataques en línea; no restringen los ataques fuera de línea tras una filtración de la base de datos de hashes. Por lo tanto, las contraseñas necesitan un hash dedicado y duro en memoria con una sal aleatoria independiente y costo ajustable. Los registros nuevos utilizan una implementación madura de Argon2id y describen por sí mismos la versión del algoritmo, m/t/p, la sal y la salida. Si se habilitan, los peppers se versionan en un sistema de claves fuera de la base de datos y sus copias de seguridad.

No copiaría parámetros directamente de un blog. Utilizaría el 19 MiB, t=2, p=1 actual de OWASP como un candidato mínimo y mediría p50, p95, p99 individual y concurrente, CPU y memoria real en instancias equivalentes a producción, para luego probar la carga con picos normales y tráfico de ataque. Diecinueve MiB multiplicados por 24 operaciones concurrentes ya son 456 MiB de memoria de trabajo, por lo que el servicio necesita una cola acotada, permisos de concurrencia y suficiente margen en la instancia. Una biblioteca madura genera una sal aleatoria por registro, y el registro conserva los parámetros para futuras actualizaciones.

Al iniciar sesión, el formato declarado selecciona exactamente un verificador. Después de que una contraseña heredada tiene éxito, calculo el registro Argon2id actual fuera de la transacción de base de datos y actualizo solo si el hash antiguo todavía coincide. Si CAS falla, recargo la credencial más reciente y verifico esta entrada nuevamente. Los inicios de sesión concurrentes pueden entonces converger, mientras que un inicio de sesión antiguo no puede sobrescribir un restablecimiento de contraseña concurrente. Emito una sesión solo después de confirmar el estado actual de la credencial. El registro, el cambio voluntario y la recuperación escriben solo el nuevo formato desde el primer día.

Bcrypt y PBKDF2 aún aceptable obtienen un período de migración definido con soporte exclusivo para verificación. SHA-256 sin sal entra en una cola de mayor riesgo. Si nunca se ha filtrado, un envoltorio externo lento con sal nueva puede proporcionar contención a corto plazo, pero no reemplaza el re-hasheo de la contraseña real. Las cuentas expuestas, privilegiadas y con mucho tiempo inactivas se restablecen o congelan antes de la fecha límite. Los verificadores heredados no permanecen para siempre.

El endpoint utiliza errores uniformes y un hash simulado actual para reducir las diferencias de enumeración de cuentas, además de límites independientes de origen y cuenta, una cola global y límites de concurrencia de memoria para resistir la denegación de servicio por amplificación de hash. La evidencia de finalización incluye distribución de versiones, cero registros heredados de alto riesgo, fallas de migración y conflictos de CAS, pruebas de carga máxima y condiciones de carrera, escaneos de registros confidenciales, rotación de pepper y ejercicios de filtración. Declararía la finalización solo después de que esas comprobaciones pasen y los verificadores heredados planificados sean retirados.”

Errores comunes y mejoras

  • Almacenar contraseñas como SHA-256 con sal → la sal previene la reutilización de trabajo entre cuentas, pero no la adivinación rápida de un registro → utilice un hash de contraseñas dedicado, ajustable y duro en memoria.
  • Afirmar que los hashes no pueden ser descifrados → la adivinación de candidatos todavía encuentra contraseñas débiles → plantee el objetivo como elevar el costo fuera de línea, junto con el bloqueo de contraseñas comprometidas y MFA.
  • Tratar los parámetros de OWASP como permanentemente óptimos → el hardware, las bibliotecas, los recursos de la instancia y el tráfico cambian → registre el entorno de referencia, vuelva a medir y actualice por versión.
  • Convertir cada registro de bcrypt a Argon2id fuera de línea → no se puede derivar un hash nuevo estándar sin el texto plano → vuelva a aplicar el hash tras una verificación exitosa y envuelva, restablezca o congele el resto según el riesgo.
  • Actualizar la migración sin una condición sobre el valor antiguo → el inicio de sesión puede sobrescribir un restablecimiento de contraseña completado → utilice compare-and-swap, luego recargue y vuelva a verificar tras una falla.
  • Mantener un bloqueo en la fila del usuario durante el hashing → el trabajo costoso amplifica la duración del bloqueo y la ocupación del pool → calcule fuera de la transacción y realice una escritura condicional corta.
  • Guardar el pepper en la misma tabla de configuración de la base de datos → una sola filtración de base de datos obtiene ambas capas → almacene la clave en un sistema protegido independientemente y audite por versión.
  • Rotar un pepper cambiando una sola variable de entorno → los registros antiguos no pueden verificarse directamente con la nueva clave → mantenga dos versiones brevemente, luego recalcule tras un inicio de sesión exitoso o exija un restablecimiento.
  • Responder de inmediato para una cuenta inexistente → el tiempo de respuesta revela la existencia de la cuenta → utilice errores uniformes, un hash simulado y pruebas empíricas de distribución de latencia.
  • Ejecutar Argon2id sin un límite de concurrencia → un atacante puede amplificar el consumo de memoria y CPU → aplique límites bidimensionales, luego una cola acotada y permisos de concurrencia.
  • Ignorar el límite de entrada de bcrypt → el comportamiento histórico con 72 bytes puede cambiar la credencial efectiva durante la migración → reproduzca el verificador heredado y exija un cambio explícito de contraseña para las cuentas afectadas.
  • Verificar solo que los nuevos registros usen Argon2id → los registros heredados activos o de alto riesgo permanecen expuestos → rastree el inventario por algoritmo, riesgo y actividad, con criterios de cero y excepciones.

Preguntas de seguimiento

Pregunta de seguimiento 1: ¿Por qué una sal puede almacenarse en texto plano mientras que un pepper debe permanecer en secreto?

Una sal hace que la entrada de cada registro sea única, evitando que contraseñas iguales compartan salidas y trabajo precalculado. Un atacante que conoce la sal todavía debe adivinar cada registro por separado. Un pepper agrega valor porque un atacante que solo tiene la base de datos carece de un secreto del lado del servidor, por lo que debe permanecer separado de la base de datos de hashes. Los controles tienen funciones diferentes; un pepper no reemplaza una sal independiente por registro.

Pregunta de seguimiento 2: ¿Puede la base de datos aumentar directamente el recuento de iteraciones de Argon2id?

Ningún hash de contraseñas estándar con parámetros más altos puede derivarse de la salida antigua sin el texto plano del usuario. Un envoltorio externo puede endurecer temporalmente la salida antigua, pero cambia la semántica del registro y no puede borrar el riesgo de una salida previamente expuesta. Una actualización estándar aún recalcula tras una verificación exitosa de contraseña o requiere un restablecimiento.

Pregunta de seguimiento 3: ¿Por qué no permitir el inicio de sesión inmediatamente después de que falle el CAS?

La falla puede significar que otra solicitud completó la misma migración, o puede significar que el usuario estableció simultáneamente una contraseña diferente mediante la recuperación. La contraseña antigua es inválida en el segundo caso. Recargar el registro más reciente y verificar la entrada enviada distingue los casos; una verificación fallida no puede recibir una sesión.

Pregunta de seguimiento 4: ¿Son siempre mejores los parámetros más altos de Argon2id?

Un mayor costo de memoria o tiempo incrementa el costo de ataque fuera de línea y el uso de recursos para inicios de sesión legítimos. Parámetros excesivos crean latencia de cola, acumulación en cola, errores de OOM en instancias y un amplificador de denegación de servicio para solicitudes baratas. La política correcta es el costo sostenible más alto medido bajo restricciones reales de hardware, concurrencia, escalado y SLO, y debe reevaluarse a medida que cambien el hardware y las amenazas.

Pregunta de seguimiento 5: ¿Qué debería suceder con una cuenta que ha estado inactiva durante cinco años y todavía usa bcrypt?

Clasifíquela por privilegio, historial de exposición y parámetros heredados. A una cuenta ordinaria de bajo riesgo se le puede congelar el inicio de sesión por contraseña tras la fecha límite de migración y permitirle establecer una nueva contraseña mediante recuperación controlada cuando el usuario regrese. Las cuentas privilegiadas o afectadas deben restablecerse antes y tener sus sesiones revocadas. Mantener el verificador heredado para siempre impide que la migración se complete jamás.

Fuentes públicas

Preguntas relacionadas