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

Como proteger o painel administrativo do seu servidor de MU Online com autenticação em duas etapas (2FA)

Implemente autenticação em duas etapas (2FA) baseada em TOTP no painel administrativo PHP do seu servidor de MU Online, com geração de segredo, QR Code, verificação de código e plano de recuperação de acesso caso o jogador perca o dispositivo.

BR Bruno · Atualizado em 28 jul 2024 · ⏱ 15 min de leitura
Resposta rápida

O painel administrativo de um servidor de MU Online é o alvo mais valioso para um atacante: uma única conta comprometida com nível de Administrador pode gerar itens, alterar saldos, banir jogadores ou derrubar o banco de dados inteiro. Proteger esse acesso apenas com senha — mesmo senha forte — deix

O painel administrativo de um servidor de MU Online é o alvo mais valioso para um atacante: uma única conta comprometida com nível de Administrador pode gerar itens, alterar saldos, banir jogadores ou derrubar o banco de dados inteiro. Proteger esse acesso apenas com senha — mesmo senha forte — deixa o servidor vulnerável a phishing, reuso de senha vazada em outro site e keyloggers. A autenticação em duas etapas (2FA) baseada em TOTP adiciona uma segunda barreira que um atacante não consegue reproduzir só com a senha roubada. Este tutorial mostra como implementar 2FA no painel PHP legado do servidor, do lado do banco de dados até a tela de verificação do jogador.

Por que senha sozinha não é suficiente

Senhas vazam por vários caminhos que independem da força da senha em si: reuso da mesma senha em outro site que sofreu vazamento, phishing disfarçado de página de login idêntica, ou malware tipo keylogger na máquina do administrador. Em qualquer um desses casos, o atacante obtém a senha correta e passa pela autenticação normalmente. O 2FA quebra esse cenário porque exige um segundo fator — algo que o administrador tem (o código gerado no celular), não apenas algo que ele sabe (a senha).

Como funciona o TOTP (Time-based One-Time Password)

O TOTP gera um código numérico de 6 dígitos que muda a cada 30 segundos, calculado a partir de um segredo compartilhado entre o servidor e o aplicativo autenticador (Google Authenticator, Authy, Microsoft Authenticator) e do horário atual. O servidor e o celular nunca trocam esse código pela rede no momento da geração — ambos calculam o mesmo valor de forma independente, o que torna o método resistente a interceptação de rede.

ComponentePapel
Segredo compartilhado (secret)Gerado uma vez, armazenado no banco e no app do usuário
Timestamp atualSincronizado entre servidor e dispositivo (janela de 30s)
Algoritmo HMAC-SHA1 (RFC 6238)Combina segredo + timestamp para gerar o código de 6 dígitos
Janela de tolerânciaAceita o código do intervalo anterior/seguinte para tolerar pequena diferença de relógio

Passo 1 — Preparar a tabela de segredos no banco

Adicione uma coluna para armazenar o segredo TOTP de cada conta administrativa, e uma tabela separada para os códigos de recuperação:

ALTER TABLE admin_accounts ADD COLUMN totp_secret VARCHAR(64) NULL;
ALTER TABLE admin_accounts ADD COLUMN totp_enabled TINYINT(1) NOT NULL DEFAULT 0;

CREATE TABLE admin_recovery_codes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    admin_id INT NOT NULL,
    code_hash VARCHAR(255) NOT NULL,
    used TINYINT(1) NOT NULL DEFAULT 0,
    FOREIGN KEY (admin_id) REFERENCES admin_accounts(id)
);

Nunca armazene o segredo TOTP em texto simples acessível publicamente, e nunca armazene os códigos de recuperação sem hash — trate-os como senhas de uso único.

Passo 2 — Instalar uma biblioteca TOTP em PHP

Use uma biblioteca open source consolidada em vez de implementar o algoritmo do zero:

composer require spomky-labs/otphp

Isso evita erros sutis de implementação do RFC 6238 que poderiam gerar códigos incompatíveis com os aplicativos autenticadores padrão do mercado.

Passo 3 — Gerar o segredo e o QR Code de ativação

use OTPHP\TOTP;

$totp = TOTP::generate();
$totp->setLabel('PainelAdmin-ViciadosMU');
$totp->setIssuer('ViciadosMU');

$secret = $totp->getSecret();
// Salvar $secret (criptografado) na coluna totp_secret do admin logado

$qrCodeUrl = $totp->getQrCodeUri(
    'https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=[DATA]',
    '[DATA]'
);
// Exibir $qrCodeUrl na tela para o admin escanear com o app autenticador

Exiba o QR Code apenas uma vez, na tela de ativação, e nunca registre o segredo em log de aplicação — ele é equivalente a uma senha mestra do segundo fator.

Passo 4 — Verificar o código na ativação antes de confirmar

Antes de marcar totp_enabled = 1, exija que o administrador digite o código gerado pelo app, confirmando que o QR Code foi escaneado corretamente:

$codigoDigitado = $_POST['codigo'];

if ($totp->verify($codigoDigitado)) {
    // Ativar totp_enabled = 1 no banco
    // Gerar e exibir códigos de recuperação (uma única vez)
} else {
    // Erro: código inválido, não ativar ainda
}

Esse passo evita o cenário em que o administrador acha que ativou o 2FA, mas o app não foi configurado corretamente, e ele fica bloqueado no próximo login.

Passo 5 — Gerar e exibir códigos de recuperação

No momento da ativação bem-sucedida, gere de 8 a 10 códigos de uso único e exiba-os apenas uma vez, orientando o administrador a guardá-los offline:

function gerarCodigosRecuperacao(int $quantidade = 10): array {
    $codigos = [];
    for ($i = 0; $i < $quantidade; $i++) {
        $codigos[] = strtoupper(bin2hex(random_bytes(4))); // ex: A1B2C3D4
    }
    return $codigos;
}

// Salvar apenas o hash de cada código na tabela admin_recovery_codes
foreach ($codigos as $codigo) {
    $hash = password_hash($codigo, PASSWORD_BCRYPT);
    // INSERT INTO admin_recovery_codes (admin_id, code_hash) VALUES (?, ?)
}

Passo 6 — Exigir o segundo fator no login

No fluxo de login, depois da senha validada corretamente, exiba a tela de código TOTP antes de conceder a sessão administrativa completa:

if ($senhaValida) {
    if ($admin['totp_enabled']) {
        // Redirecionar para tela de verificação de código,
        // sem ainda conceder sessão de nível administrativo
        $_SESSION['pending_2fa_admin_id'] = $admin['id'];
    } else {
        // Conceder sessão normalmente (ou forçar ativação do 2FA, se obrigatório)
    }
}
// Na tela de verificação
$codigo = $_POST['codigo'];
$totp = TOTP::createFromSecret($segredoDoBanco);

if ($totp->verify($codigo)) {
    // Conceder sessão administrativa completa
} else {
    // Verificar se é um código de recuperação válido (hash match e used = 0)
    // Caso contrário, negar acesso e logar tentativa
}

Passo 7 — Definir a política de obrigatoriedade por nível de conta

Nem toda conta precisa do mesmo rigor. Defina a política conforme o risco do nível de acesso:

Nível de conta2FA obrigatório?Justificativa
OwnerSimAcesso total, maior dano possível se comprometido
AdministradorSimComandos sensíveis (additem, setmoney, ban)
Moderador de eventoRecomendadoAcesso limitado, mas ainda distribui itens
Suporte júniorOpcionalComandos de menor impacto econômico
Conta de jogador comumOpcional/incentivadoProteção de conta pessoal, não administrativa

Passo 8 — Plano de recuperação sem comprometer a segurança

Quando um administrador perde o dispositivo e não tem os códigos de recuperação, defina um processo manual e documentado em vez de simplesmente desativar o 2FA por pedido informal no Discord:

  1. Exija verificação de identidade fora de banda (chamada de vídeo com outro administrador de confiança, ou confirmação por e-mail cadastrado previamente).
  2. Um segundo administrador (nunca o próprio solicitante) reseta totp_enabled = 0 diretamente no banco.
  3. Force a reativação do 2FA imediatamente no próximo login.
  4. Registre o incidente em log interno, incluindo quem autorizou o reset.

Erros comuns e soluções

SintomaCausa provávelSolução
Código do app não bate com o servidorRelógio do celular ou servidor dessincronizadoSincronizar NTP no servidor e conferir hora do celular
Admin perdeu acesso e não tem códigos de recuperaçãoCódigos não gerados ou não guardados na ativaçãoImplementar processo manual de reset com verificação cruzada
Segredo TOTP exposto em log de aplicaçãoDebug/log registrando variável sensívelRemover log de variáveis de segredo e rotacionar segredos expostos
2FA ativado mas sessão nunca pede o segundo fatorFluxo de login não verifica totp_enabled corretamenteRevisar lógica de sessão pendente antes de conceder acesso completo
Reset de 2FA feito sem verificação de identidadeFalta de processo documentado de recuperaçãoFormalizar processo com segundo administrador obrigatório

Checklist de implementação de 2FA no painel

  • Tabela de segredo TOTP e códigos de recuperação criada no banco.
  • Biblioteca TOTP confiável integrada (ex.: spomky-labs/otphp).
  • Fluxo de ativação com QR Code e verificação de código antes de confirmar.
  • Códigos de recuperação gerados, hasheados e exibidos uma única vez.
  • Login exigindo segundo fator antes de conceder sessão administrativa completa.
  • Política de obrigatoriedade definida por nível de conta.
  • Processo documentado de recuperação de acesso com verificação cruzada.

Com o painel protegido por 2FA, revise também os demais controles de acesso da equipe administrativa — o guia de criação de servidor de MU Online cobre a base de infraestrutura sobre a qual essa camada extra de segurança deve ser construída.

Perguntas frequentes

2FA por SMS é seguro o suficiente para o painel de admin?

É melhor que nada, mas SMS é vulnerável a SIM swap e interceptação. Para contas de nível Administrador e Owner, prefira TOTP (Google Authenticator, Authy) ou uma chave física (FIDO2/WebAuthn), reservando SMS no máximo como método secundário de recuperação.

O que acontece se o administrador perder o celular com o autenticador?

Por isso é essencial gerar e armazenar códigos de recuperação (backup codes) no momento da ativação do 2FA, guardados em local seguro offline. Sem isso, a única saída é um processo manual de verificação de identidade para resetar o 2FA diretamente no banco de dados.

2FA deve ser obrigatório para todos os níveis de conta do painel?

Recomenda-se obrigatório para os níveis com comandos administrativos sensíveis (Admin, Owner) e opcional, mas incentivado, para contas comuns de jogador. Tornar obrigatório para todos de uma vez pode gerar atrito de suporte se a comunidade não estiver preparada.

TOTP funciona sem internet no celular do administrador?

Sim. O algoritmo TOTP gera o código localmente a partir do segredo compartilhado e do horário do dispositivo, sem precisar de conexão à internet no momento da geração — só o relógio do celular precisa estar sincronizado corretamente.

Preciso de uma biblioteca paga para implementar TOTP em PHP?

Não. Existem bibliotecas open source como spomky-labs/otphp ou implementações simples do algoritmo RFC 6238 que podem ser integradas gratuitamente ao painel PHP existente, sem depender de serviço externo pago.

BR
Editor de eventos, mapas e itens

Bruno é especialista em eventos, mapas, bosses e economia de itens do MU Online. Documenta cada detalhe com base em jogo real.

Continue lendo

Artigos relacionados