Vulnerabilidad de Truncamiento en Bcrypt: Análisis y Mitigaciones

StringManolo
StringManolo
Cybersecurity Researcher
github.com/StringManolo
Publicado: 4 de Noviembre 2025 | Tiempo de lectura: 5 min | Tags: #bcrypt #Vulnerabilidad #Truncamiento #Ciberseguridad
⚠️ ADVERTENCIA: Sistemas que usan bcrypt sin validar longitud de contraseña pueden ser vulnerables a bypass de autenticación.

Introducción

Bcrypt es ampliamente usado para el almacenamiento seguro de contraseñas, pero su limitación de 72 bytes puede ser explotada si no se valida correctamente la longitud de entrada.

Problema Técnico

Truncamiento Silencioso

Bcrypt procesa solo los primeros 72 bytes de la contraseña, ignorando silenciosamente cualquier contenido adicional.

// Ejemplo de comportamiento
bcrypt.hash("a".repeat(72)) == bcrypt.hash("a".repeat(72) + "cualquier_cosa")

Bytes vs Caracteres

La confusión surge al diferenciar bytes de caracteres:

Impacto en Seguridad

Vectores de Ataque

Demostración Práctica

CTF educativo disponible: 🔗 Demo Interactivo

testAdminPassword("a".repeat(72)); // → Válida
testAdminPassword("a".repeat(72) + "ADMIN"); // → Válida

Ejemplo de interpretación de bytes

Ingresa en el CTF en una nueva pestaña y registra un nuevo usuario llamado Manolo.

Utiliza como contraseña para el usuario MANOLO 36 letras 'ñ' seguidas de cualquier texto, puedes copiar y pegar: ññññññññññññññññññññññññññññññññññññMANOLO123

Registra otro usuario llamado PACO
Utiliza como contraseña para el usuario PACO 36 letras 'ñ' seguidas de cualquier texto, puedes copiar y pegar: ññññññññññññññññññññññññññññññññññññPACO456

Las contraseña son distinas, pero puedes ingresar en la cuenta de cualquiera de los 2 usuarios usando la contraseña ññññññññññññññññññññññññññññññññññññABCDEFG

Esto sucede porque el carcater 'ñ' ocupa 2 bytes, ya que es un carcater especial. Y Bcrypt trunca tras los 72 primeros bytes (36 ñ de 2 bytes == 72 bytes).

Emojis y otros caracteres especiales (como letras en otros idiomas) pueden utilizar hasta un máximo de 4 bytes por caracter.

Mitigaciones

Validación de Entrada

  • Limitar a 18 caracteres máximo
  • Utilizar otro algitmo de hashing

Implementación Segura

const validatePassword = (pwd) => {
  if (pwd.length > 18) {
    throw new Error("Máximo 18 caracteres");
  }
  return true;
}

Alternativas

  • Argon2id (recomendado)
  • PBKDF2
  • Scrypt

Conclusión

Bcrypt sigue siendo seguro cuando se implementa correctamente. La clave está en validar la longitud de contraseñas (18 caracteres máximo) o migrar a algoritmos modernos como Argon2id.

Vulnerabilidades Relacionadas