O maior portal de MU Online do Brasil — desde 2003
Tutorial Avançado Infra

Migrando criptografia de senhas legado para um esquema moderno no seu servidor de MU Online

Entenda os riscos de esquemas de senha legado (MD5 puro, SHA1 sem sal) usados em servidores antigos de MU Online e aprenda a migrar para hashing moderno (bcrypt/Argon2) sem forçar todos os jogadores a resetar a senha de uma vez.

RO Rodrigo · Atualizado em 12 mai 2014 · ⏱ 17 min de leitura
Resposta rápida

Um número significativo de servidores privados de MU Online ainda roda sobre bancos herdados de emuladores antigos, onde a senha da conta é armazenada com MD5 puro ou SHA1 sem sal — esquemas que eram aceitáveis há 15-20 anos, mas que hoje podem ser quebrados por GPUs modernas em questão de segundos

Um número significativo de servidores privados de MU Online ainda roda sobre bancos herdados de emuladores antigos, onde a senha da conta é armazenada com MD5 puro ou SHA1 sem sal — esquemas que eram aceitáveis há 15-20 anos, mas que hoje podem ser quebrados por GPUs modernas em questão de segundos para senhas comuns. Migrar esse esquema para um hashing moderno como bcrypt ou Argon2 é uma das melhorias de segurança mais impactantes que um administrador pode fazer, mas precisa ser feita sem forçar milhares de jogadores a resetar a senha ao mesmo tempo. Este tutorial detalha o problema, a estratégia de migração incremental e os pontos de sincronização entre GameServer e WebEngine.

Por que hash legado é um risco real

MD5 e SHA1 sem sal têm duas fraquezas centrais: são rápidos demais (permitindo bilhões de tentativas por segundo em hardware moderno) e, sem sal, permitem o uso de tabelas rainbow pré-computadas — ou seja, um invasor com acesso a um dump de banco pode recuperar senhas comuns quase instantaneamente, sem nem precisar de força bruta. Se o mesmo jogador reutiliza a senha em outros serviços (email, redes sociais), o vazamento do seu servidor de MU vira porta de entrada para contas fora do jogo — um risco de reputação sério para o administrador.

Comparando os esquemas de hash

EsquemaVelocidade de cálculoResistente a GPU/ASICUso recomendado hoje
MD5 sem salExtremamente rápidoNãoNunca (legado a migrar)
SHA1 sem salMuito rápidoNãoNunca (legado a migrar)
SHA256 com sal simplesRápidoParcialmenteAceitável, mas não ideal
bcrypt (custo 10-12)Lento por designSimRecomendado
Argon2idLento e resistente a memóriaSim (o mais robusto)Recomendado quando disponível

A diferença central é que bcrypt e Argon2 são deliberadamente lentos e configuráveis (fator de custo), tornando ataques de força bruta impraticáveis em escala, mesmo com hardware dedicado.

Pré-requisitos antes de iniciar a migração

  • Backup completo e testado do banco de contas (MEMB_INFO ou equivalente) antes de qualquer alteração.
  • Ambiente de staging com cópia do banco de produção para testar a lógica de migração sem risco.
  • Acesso ao código-fonte do GameServer (ou do módulo de autenticação) e do WebEngine.
  • Biblioteca de bcrypt/Argon2 disponível na linguagem usada pelo GameServer (C++/Delphi/C#) e pelo WebEngine (PHP/.NET).
  • Janela de manutenção agendada com baixo tráfego para o deploy final.

Passo 1 — Mapear todos os pontos que validam senha

Antes de migrar, identifique todos os lugares que comparam senha de login: o próprio GameServer (autenticação do cliente do jogo), o WebEngine (login no painel), e qualquer API auxiliar (app mobile, bot de Discord com login vinculado). Se qualquer um desses pontos não for atualizado, o jogador pode ficar com acesso inconsistente entre eles.

Passo 2 — Adicionar uma coluna de versão de hash

Adicione uma coluna (password_hash_version ou similar) na tabela de contas, indicando qual esquema está armazenado naquele registro:

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

Essa coluna é o que permite ao sistema saber, a cada login, qual algoritmo usar para validar aquele registro específico — sem ela, você não consegue ter dois esquemas coexistindo com segurança.

Passo 3 — Implementar a validação dupla (legado + moderno)

No código de autenticação (GameServer e WebEngine), a lógica de login passa a checar a versão do hash antes de validar:

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

Passo 4 — Recalcular o hash automaticamente no login bem-sucedido

Esta é a etapa central da migração incremental: sempre que um jogador com password_hash_version = 0 faz login com sucesso, o sistema aproveita que a senha em texto puro acabou de ser digitada corretamente e a recalcula com o esquema novo, atualizando a coluna:

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

Dessa forma, a migração acontece de forma transparente, um jogador de cada vez, conforme ele naturalmente faz login — sem exigir reset em massa.

Passo 5 — Definir a política para contas inativas

Contas que não fazem login há muito tempo nunca vão passar pelo recálculo automático, porque ele só acontece no momento do login. Defina uma política explícita:

EstratégiaPrósContras
Deixar como está (hash legado permanece)Simples, sem esforço extraContas antigas continuam vulneráveis indefinidamente
Forçar reset de senha por e-mail após X meses de inatividadeMigra todas as contas eventualmenteExige sistema de e-mail funcional e pode gerar suporte
Exigir redefinição de senha no próximo login de conta muito antigaMigra na reativaçãoPode frustrar jogador que retorna após anos

Para a maioria dos servidores, a combinação de "migração automática no login" mais "reset forçado por e-mail após um prazo longo (ex.: 12 meses) para contas paradas" é o equilíbrio mais razoável.

Passo 6 — Sincronizar GameServer e WebEngine

Se o GameServer e o WebEngine validam senha de forma independente (arquiteturas comuns em emuladores de MU), garanta que ambos leem a mesma coluna de versão e implementam a mesma lógica de validação dupla. Um erro comum é atualizar só o WebEngine e esquecer o GameServer (ou vice-versa), deixando o jogador autenticado em um lado e rejeitado no outro.

Passo 7 — Testar exaustivamente em staging

  1. Restaure uma cópia do banco de produção em staging.
  2. Simule login de contas com versao = 0 e confirme que autenticam corretamente e são migradas para versao = 1/2.
  3. Simule login de contas já migradas e confirme que a validação bcrypt/Argon2 funciona sem recalcular de novo.
  4. Teste senha incorreta em ambos os esquemas, garantindo que o sistema rejeita corretamente sem vazar informação sobre qual esquema está em uso (mesma mensagem de erro genérica).
  5. Meça o tempo de resposta do login com bcrypt/Argon2 sob carga — o custo deliberadamente alto não deve gerar timeout perceptível ao jogador.

Passo 8 — Publicar em produção com monitoramento

Publique na janela de manutenção agendada, com backup imediatamente antes. Monitore a taxa de login com sucesso e o tempo de resposta de autenticação nas primeiras horas — um pico de falhas de login após o deploy é sinal de que algo na lógica de validação dupla não está correto.

Erros comuns e soluções

SintomaCausa provávelSolução
Jogador migrado no WebEngine não consegue logar no cliente do jogoGameServer não sincronizado com a nova lógica/colunaReplique a validação dupla no código do GameServer
Login extremamente lento após a mudançaCusto do bcrypt/Argon2 configurado alto demais para o hardwareReduza o fator de custo mantendo segurança aceitável (ex.: cost 10-12)
Contas antigas nunca migramFalta de política para contas inativasImplemente reset forçado por e-mail após um prazo definido
Mensagem de erro revela o esquema em usoMensagens de erro diferentes por versão de hashPadronize uma única mensagem genérica de "usuário ou senha inválidos"
Falha silenciosa ao atualizar o hash no loginErro na escrita da nova coluna não tratadoAdicione tratamento de erro e log na etapa de recálculo do hash

Checklist de migração de senhas

  • Todos os pontos de validação de senha mapeados (GameServer, WebEngine, APIs auxiliares).
  • Coluna de versão de hash adicionada à tabela de contas.
  • Validação dupla (legado + moderno) implementada em todos os pontos.
  • Recálculo automático de hash no login bem-sucedido implementado e testado.
  • Política definida para contas inativas que nunca fazem login.
  • GameServer e WebEngine sincronizados na mesma lógica e coluna.
  • Testado exaustivamente em staging, incluindo casos de erro e performance.
  • Deploy realizado em janela de manutenção com backup e monitoramento ativo.

Com o esquema de senhas modernizado, o próximo passo natural de segurança é revisar as demais camadas de proteção do seu ambiente — como autenticação do painel administrativo e hardening geral do banco de dados — dentro da estratégia de infraestrutura descrita no tutorial de criação de servidor de MU Online.

Perguntas frequentes

Por que servidores antigos de MU usam MD5 ou SHA1 sem sal?

Porque esses emuladores foram escritos há mais de 15 anos, quando MD5/SHA1 ainda eram considerados aceitáveis e o hardware de quebra de hash era muito mais lento. Hoje, com GPUs modernas, MD5 sem sal pode ser quebrado por força bruta ou tabelas rainbow em segundos para senhas comuns.

Migrar o esquema de senha derruba as contas dos jogadores atuais?

Não precisa. A abordagem correta é uma migração incremental: você mantém o hash antigo funcionando para login, mas na primeira autenticação bem-sucedida com sucesso do jogador, recalcula a senha com o esquema novo (bcrypt/Argon2) e substitui o hash salvo, de forma transparente.

Bcrypt ou Argon2, qual escolher para o WebEngine/servidor de MU?

Ambos são adequados; bcrypt tem suporte mais amplo em bibliotecas PHP/.NET antigas usadas por painéis de MU, enquanto Argon2 é mais moderno e vencedor da Password Hashing Competition. Se sua stack já suporta Argon2 nativamente, prefira-o; senão, bcrypt com custo adequado é uma escolha sólida e comprovada.

Preciso trocar o esquema no GameServer, no WebEngine, ou nos dois?

Nos dois, se ambos validam senha de forma independente (comum em setups onde o cliente do jogo autentica direto no GameServer e o WebEngine autentica separadamente no painel). Se não sincronizar os dois pontos, o jogador pode ficar com senha válida em um lado e inválida no outro.

Como evito travar o servidor todo durante a migração?

Faça a migração em uma janela de manutenção agendada e com baixo tráfego, migre o esquema de leitura primeiro (aceitando ambos os formatos de hash), teste exaustivamente em staging, e só depois ative a gravação do novo formato. Nunca faça a troca completa em produção sem esse período de transição dupla.

RO
Fundador e editor-chefe

Rodrigo mantém o ViciadosMU desde os primórdios do portal. Especialista em criação e administração de servidores de MU Online, história do jogo e a evolução das seasons — escreveu boa parte do acervo antes de 2024.

Continue lendo

Artigos relacionados