El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Infra

Migrando el cifrado de contraseñas legado a un esquema moderno en tu servidor de MU Online

Entiende los riesgos de los esquemas de contraseña legado (MD5 puro, SHA1 sin sal) usados en servidores antiguos de MU Online y aprende a migrar a un hashing moderno (bcrypt/Argon2) sin obligar a todos los jugadores a resetear la contraseña de una vez.

RO Rodrigo · Actualizado el 12 may 2014 · ⏱ 17 min de lectura
Respuesta rápida

Un número significativo de servidores privados de MU Online todavía funciona sobre bases de datos heredadas de emuladores antiguos, donde la contraseña de la cuenta se almacena con MD5 puro o SHA1 sin sal —esquemas que eran aceptables hace 15-20 años, pero que hoy pueden ser quebrados por GPUs moder

Un número significativo de servidores privados de MU Online todavía funciona sobre bases de datos heredadas de emuladores antiguos, donde la contraseña de la cuenta se almacena con MD5 puro o SHA1 sin sal —esquemas que eran aceptables hace 15-20 años, pero que hoy pueden ser quebrados por GPUs modernas en cuestión de segundos para contraseñas comunes. Migrar ese esquema a un hashing moderno como bcrypt o Argon2 es una de las mejoras de seguridad más impactantes que un administrador puede hacer, pero debe realizarse sin obligar a miles de jugadores a resetear la contraseña al mismo tiempo. Este tutorial detalla el problema, la estrategia de migración incremental y los puntos de sincronización entre GameServer y WebEngine.

Por qué el hash legado es un riesgo real

MD5 y SHA1 sin sal tienen dos debilidades centrales: son demasiado rápidos (permitiendo miles de millones de intentos por segundo en hardware moderno) y, sin sal, permiten el uso de tablas rainbow precomputadas —es decir, un atacante con acceso a un dump de la base de datos puede recuperar contraseñas comunes casi instantáneamente, sin siquiera necesitar fuerza bruta. Si el mismo jugador reutiliza la contraseña en otros servicios (correo, redes sociales), la filtración de tu servidor de MU se convierte en puerta de entrada a cuentas fuera del juego —un riesgo de reputación serio para el administrador.

Comparando los esquemas de hash

EsquemaVelocidad de cálculoResistente a GPU/ASICUso recomendado hoy
MD5 sin salExtremadamente rápidoNoNunca (legado a migrar)
SHA1 sin salMuy rápidoNoNunca (legado a migrar)
SHA256 con sal simpleRápidoParcialmenteAceptable, pero no ideal
bcrypt (costo 10-12)Lento por diseñoRecomendado
Argon2idLento y resistente a memoriaSí (el más robusto)Recomendado cuando esté disponible

La diferencia central es que bcrypt y Argon2 son deliberadamente lentos y configurables (factor de costo), haciendo que los ataques de fuerza bruta sean imprácticos a escala, incluso con hardware dedicado.

Requisitos previos antes de iniciar la migración

  • Backup completo y probado de la base de cuentas (MEMB_INFO o equivalente) antes de cualquier modificación.
  • Entorno de staging con copia de la base de producción para probar la lógica de migración sin riesgo.
  • Acceso al código fuente del GameServer (o del módulo de autenticación) y del WebEngine.
  • Biblioteca de bcrypt/Argon2 disponible en el lenguaje usado por el GameServer (C++/Delphi/C#) y por el WebEngine (PHP/.NET).
  • Ventana de mantenimiento programada con bajo tráfico para el deploy final.

Paso 1 — Mapear todos los puntos que validan contraseña

Antes de migrar, identifica todos los lugares que comparan contraseña de login: el propio GameServer (autenticación del cliente del juego), el WebEngine (login en el panel), y cualquier API auxiliar (app móvil, bot de Discord con login vinculado). Si alguno de estos puntos no se actualiza, el jugador puede quedar con acceso inconsistente entre ellos.

Paso 2 — Agregar una columna de versión de hash

Agrega una columna (password_hash_version o similar) en la tabla de cuentas, indicando qué esquema está almacenado en ese registro:

ALTER TABLE MEMB_INFO ADD password_hash_version TINYINT NOT NULL DEFAULT 0;
-- 0 = MD5/SHA1 legado, 1 = bcrypt, 2 = Argon2id

Esta columna es lo que permite al sistema saber, en cada login, qué algoritmo usar para validar ese registro específico —sin ella, no puedes tener dos esquemas coexistiendo con seguridad.

Paso 3 — Implementar la validación doble (legado + moderno)

En el código de autenticación (GameServer y WebEngine), la lógica de login pasa a verificar la versión del hash antes de validar:

function validarLogin($senhaDigitada, $hashArmazenado, $versao) {
    if ($versao == 0) {
        // Esquema legado (ejemplo: MD5 sin sal)
        return md5($senhaDigitada) === $hashArmazenado;
    } elseif ($versao == 1) {
        return password_verify($senhaDigitada, $hashArmazenado); // bcrypt
    } elseif ($versao == 2) {
        return password_verify($senhaDigitada, $hashArmazenado); // Argon2id (misma API en PHP moderno)
    }
    return false;
}

Paso 4 — Recalcular el hash automáticamente en el login exitoso

Esta es la etapa central de la migración incremental: cada vez que un jugador con password_hash_version = 0 hace login con éxito, el sistema aprovecha que la contraseña en texto plano acaba de ser tecleada correctamente y la recalcula con el esquema nuevo, actualizando la columna:

if ($versao == 0 && validarLogin($senhaDigitada, $hashArmazenado, 0)) {
    $novoHash = password_hash($senhaDigitada, PASSWORD_BCRYPT, ['cost' => 12]);
    atualizarSenhaNoBanco($contaId, $novoHash, 1); // versión 1 = bcrypt
}

De esta forma, la migración ocurre de forma transparente, un jugador a la vez, conforme hace login naturalmente —sin exigir un reseteo masivo.

Paso 5 — Definir la política para cuentas inactivas

Las cuentas que no hacen login desde hace mucho tiempo nunca pasarán por el recálculo automático, porque este solo ocurre en el momento del login. Define una política explícita:

EstrategiaVentajasDesventajas
Dejarlo como está (el hash legado permanece)Simple, sin esfuerzo extraLas cuentas antiguas siguen vulnerables indefinidamente
Forzar reseteo de contraseña por correo tras X meses de inactividadMigra todas las cuentas eventualmenteRequiere un sistema de correo funcional y puede generar soporte
Exigir redefinición de contraseña en el próximo login de una cuenta muy antiguaMigra en la reactivaciónPuede frustrar al jugador que regresa tras años

Para la mayoría de los servidores, la combinación de "migración automática en el login" más "reseteo forzado por correo tras un plazo largo (ej.: 12 meses) para cuentas inactivas" es el equilibrio más razonable.

Paso 6 — Sincronizar GameServer y WebEngine

Si el GameServer y el WebEngine validan la contraseña de forma independiente (arquitecturas comunes en emuladores de MU), garantiza que ambos lean la misma columna de versión e implementen la misma lógica de validación doble. Un error común es actualizar solo el WebEngine y olvidar el GameServer (o viceversa), dejando al jugador autenticado en un lado y rechazado en el otro.

Paso 7 — Probar exhaustivamente en staging

  1. Restaura una copia de la base de producción en staging.
  2. Simula el login de cuentas con versao = 0 y confirma que autentican correctamente y son migradas a versao = 1/2.
  3. Simula el login de cuentas ya migradas y confirma que la validación bcrypt/Argon2 funciona sin recalcular de nuevo.
  4. Prueba contraseña incorrecta en ambos esquemas, garantizando que el sistema rechaza correctamente sin filtrar información sobre qué esquema está en uso (mismo mensaje de error genérico).
  5. Mide el tiempo de respuesta del login con bcrypt/Argon2 bajo carga —el costo deliberadamente alto no debe generar un timeout perceptible para el jugador.

Paso 8 — Publicar en producción con monitoreo

Publica en la ventana de mantenimiento programada, con backup inmediatamente antes. Monitorea la tasa de login exitoso y el tiempo de respuesta de autenticación en las primeras horas —un pico de fallos de login tras el deploy es señal de que algo en la lógica de validación doble no es correcto.

Errores comunes y soluciones

SíntomaCausa probableSolución
El jugador migrado en el WebEngine no puede loguearse en el cliente del juegoGameServer no sincronizado con la nueva lógica/columnaReplica la validación doble en el código del GameServer
El login es extremadamente lento tras el cambioCosto de bcrypt/Argon2 configurado demasiado alto para el hardwareReduce el factor de costo manteniendo una seguridad aceptable (ej.: cost 10-12)
Las cuentas antiguas nunca migranFalta de política para cuentas inactivasImplementa el reseteo forzado por correo tras un plazo definido
El mensaje de error revela el esquema en usoMensajes de error diferentes por versión de hashEstandariza un único mensaje genérico de "usuario o contraseña inválidos"
Falla silenciosa al actualizar el hash en el loginError en la escritura de la nueva columna no manejadoAgrega manejo de errores y log en la etapa de recálculo del hash

Lista de verificación de migración de contraseñas

  • Todos los puntos de validación de contraseña mapeados (GameServer, WebEngine, APIs auxiliares).
  • Columna de versión de hash agregada a la tabla de cuentas.
  • Validación doble (legado + moderno) implementada en todos los puntos.
  • Recálculo automático de hash en el login exitoso implementado y probado.
  • Política definida para cuentas inactivas que nunca hacen login.
  • GameServer y WebEngine sincronizados en la misma lógica y columna.
  • Probado exhaustivamente en staging, incluyendo casos de error y rendimiento.
  • Deploy realizado en ventana de mantenimiento con backup y monitoreo activo.

Con el esquema de contraseñas modernizado, el siguiente paso natural en seguridad es revisar las demás capas de protección de tu entorno —como la autenticación del panel administrativo y el hardening general de la base de datos— dentro de la estrategia de infraestructura descrita en el tutorial de creación de servidor de MU Online.

Preguntas frecuentes

¿Por qué los servidores antiguos de MU usan MD5 o SHA1 sin sal?

Porque esos emuladores fueron escritos hace más de 15 años, cuando MD5/SHA1 aún se consideraban aceptables y el hardware para quebrar hashes era mucho más lento. Hoy, con GPUs modernas, MD5 sin sal puede romperse por fuerza bruta o tablas rainbow en segundos para contraseñas comunes.

¿Migrar el esquema de contraseña tumba las cuentas de los jugadores actuales?

No es necesario. El enfoque correcto es una migración incremental: mantienes el hash antiguo funcionando para el login, pero en la primera autenticación exitosa del jugador, recalculas la contraseña con el esquema nuevo (bcrypt/Argon2) y reemplazas el hash guardado, de forma transparente.

¿Bcrypt o Argon2, cuál elegir para el WebEngine/servidor de MU?

Ambos son adecuados; bcrypt tiene soporte más amplio en bibliotecas PHP/.NET antiguas usadas por paneles de MU, mientras que Argon2 es más moderno y ganador de la Password Hashing Competition. Si tu stack ya soporta Argon2 nativamente, prefiérelo; si no, bcrypt con un costo adecuado es una elección sólida y comprobada.

¿Necesito cambiar el esquema en el GameServer, en el WebEngine, o en ambos?

En ambos, si los dos validan la contraseña de forma independiente (común en configuraciones donde el cliente del juego autentica directamente contra el GameServer y el WebEngine autentica por separado en el panel). Si no sincronizas ambos puntos, el jugador puede quedar con contraseña válida en un lado e inválida en el otro.

¿Cómo evito bloquear todo el servidor durante la migración?

Realiza la migración en una ventana de mantenimiento programada y con bajo tráfico, migra primero el esquema de lectura (aceptando ambos formatos de hash), prueba exhaustivamente en staging, y solo después activa la escritura del nuevo formato. Nunca hagas el cambio completo en producción sin este período de transición doble.

RO
Fundador y editor jefe

Rodrigo mantiene ViciadosMU desde los inicios del portal. Especialista en creación y administración de servidores de MU Online, historia del juego y la evolución de las seasons — escribió buena parte del archivo antes de 2024.

Sigue leyendo

Artículos relacionados