DevGuideTK
← Trilha Backend

Autenticação em múltiplos fatores

TOTP, chaves de acesso e SMS, e o que cada fator protege de fato.

O problema: a senha sozinha não basta

Senhas vazam: em bancos invadidos, em sites falsos, em máquinas com programas espiões. E são reutilizadas, então a senha que vazou de um fórum abre a conta de e-mail. Ataques que testam listas de senhas vazadas em outros sites (credential stuffing) funcionam justamente por isso.

A autenticação em múltiplos fatores (MFA) exige, além da senha, uma prova de outro tipo:

Tipo de fatorExemplos
Algo que você sabeSenha, PIN
Algo que você temCelular com aplicativo autenticador, chave de segurança, chip do celular
Algo que você éDigital, rosto (normalmente usado para destravar o que você tem)

Com dois fatores de tipos diferentes, quem tem só a senha vazada não entra. Mas os fatores não são iguais: cada um resiste a ataques diferentes.

TOTP: o código do aplicativo autenticador

O código de 6 dígitos que muda a cada 30 segundos (Google Authenticator, Microsoft Authenticator, 1Password e outros) segue o padrão TOTP (time-based one-time password, RFC 6238).

No cadastro, o servidor gera um segredo aleatório e o mostra num QR code. O aplicativo guarda o segredo. A partir daí, os dois lados calculam o mesmo código, sem conversar:

passo   = segundos desde 1970 / 30          (muda a cada 30 s)
código  = HMAC-SHA1(segredo, passo), reduzido a 6 dígitos

O QR code contém uma URI como esta, gerada no teste com a biblioteca pyotp:

otpauth://totp/Loja:ana%40exemplo.com?secret=YOMG2QNFELC6B3L3C3REZ22ZUKUHXRXO&issuer=Loja

O segredo vai em base32. Ele é tão sensível quanto uma senha, e o servidor precisa guardá-lo de forma recuperável (criptografado, e não com hash), porque precisa recalcular os códigos.

Como os relógios do celular e do servidor nunca estão perfeitamente iguais, o servidor costuma aceitar o código do passo anterior e do seguinte. E, para o código ser realmente de uso único, guarda o último passo aceito e recusa qualquer código desse passo ou de antes.

O limite de tentativas é obrigatório

Um código de 6 dígitos tem um milhão de combinações. Com a janela de três passos, três códigos valem ao mesmo tempo: cada chute tem 3 chances em um milhão.

Parece pouco, até medir. Montamos uma rota que confere o código TOTP sem limite de tentativas e um atacante com 64 conexões chutando códigos aleatórios, os dois na mesma máquina:

RodadaTentativas até acertarTempo
116.0563,6 s
2140.59837,3 s
3274.13881,3 s

Entre 3.400 e 4.500 tentativas por segundo, e o código caiu nas três rodadas, em menos de um minuto e meio. Pela rede, o atacante faria menos tentativas por segundo, mas a conta continua a favor dele: a média esperada é de 333 mil tentativas.

Com um limite de 5 tentativas a cada 15 minutos por conta, as mesmas 333 mil tentativas levariam cerca de 690 dias. O limite transforma o código de 6 dígitos de inútil em eficaz. Ele precisa valer por conta, e não só por IP, porque o atacante pode distribuir as tentativas entre muitos endereços.

O ponto fraco dos códigos: sites falsos

TOTP, SMS e códigos por e-mail têm uma fraqueza em comum: o usuário digita o código. Um site falso, idêntico ao verdadeiro, pede a senha e o código, e os repassa ao site verdadeiro na hora, dentro dos 30 segundos. Ferramentas de phishing automatizam esse repasse e capturam até o cookie de sessão. O segundo fator não ajuda: o usuário o entregou ao atacante.

Chaves de acesso: o fator que resiste a sites falsos

As chaves de acesso (passkeys), baseadas no padrão WebAuthn, funcionam de outro jeito. No cadastro, o dispositivo (celular, computador ou chave de segurança) cria um par de chaves para aquele site. A chave privada nunca sai do dispositivo. No login, o servidor manda um desafio, o dispositivo o assina, e o servidor confere com a chave pública.

O ponto decisivo: o navegador amarra cada chave ao domínio do site, e se recusa a usá-la em outro domínio. O usuário não tem como entregar a assinatura a um site falso, mesmo se cair no golpe.

Testamos num Chrome real, com um autenticador virtual. A chave foi criada em loja.test. Depois, a mesma página foi servida em 1oja.test (com o número 1 no lugar da letra l):

SituaçãoResultado
Cadastro e login em loja.testAssinatura conferida pelo servidor
Site falso pede uma assinatura para loja.testSecurityError: The RP ID "loja.test" is invalid for this domain
Site falso pede uma assinatura para o próprio domínioNotAllowedError: não existe chave para 1oja.test

Nas duas tentativas do site falso, o navegador não produziu nenhuma assinatura. Com TOTP, o mesmo site falso teria recebido o código digitado pelo usuário.

As chaves de acesso podem substituir a senha inteira: o dispositivo confere a digital ou o PIN (algo que você é ou sabe) e guarda a chave (algo que você tem). São dois fatores numa só ação.

SMS e e-mail

FatorO que protegeFraquezas
Código por SMSSenha vazadaTroca fraudulenta do chip (SIM swap), interceptação, phishing com repasse
Código por e-mailSenha vazadaQuem tem o e-mail tem tudo; phishing com repasse
TOTPSenha vazada, SIM swapPhishing com repasse; segredo vazado do servidor
Chave de acessoSenha vazada, SIM swap, phishingPerder todos os dispositivos sem uma forma de recuperação

O SMS é o fator mais fraco, e entidades como o NIST desaconselham o seu uso como única opção. Ainda assim, um SMS barra a grande maioria dos ataques automatizados com senhas vazadas. Para muitos usuários, a escolha real é entre SMS e nada.

Recuperação: o lado esquecido

O usuário troca de celular, perde o aparelho ou apaga o aplicativo. Sem um plano, a conta fica inacessível, e o suporte recebe o pedido "desativa o MFA para mim". Se o suporte desativa sem conferir a identidade, essa vira a porta de entrada do atacante.

As saídas usuais: códigos de recuperação de uso único, mostrados no cadastro e guardados com hash; cadastro de mais de um fator (duas chaves de acesso, ou chave e TOTP); e um processo de recuperação pelo suporte tão rigoroso quanto o próprio login.

Por que isso importa quando a IA escreve o código

Um assistente que implementa "login com código do Google Authenticator" costuma acertar o cálculo e errar o resto:

  • Nenhum limite de tentativas na rota que confere o código.
  • O mesmo código aceito duas vezes dentro dos 30 segundos.
  • Uma janela grande demais, aceitando códigos de minutos atrás.
  • O segredo TOTP guardado em texto puro na tabela de usuários.
  • Códigos de recuperação guardados em texto puro, ou reutilizáveis.
  • Comparação com == em vez de comparação em tempo constante.
  • Trocar o e-mail ou desativar o MFA sem pedir o segundo fator.

O próximo nível compara os fatores em detalhe, os fluxos de cadastro e de recuperação, e quando exigir o segundo fator.

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Autenticação em múltiplos fatores em cinco minutos

    Explique em no máximo cinco minutos de leitura o que é autenticação em múltiplos fatores, para alguém que já fez um login com senha, mas nunca implementou um segundo fator.
    
    Cubra só o essencial: os tipos de fator, como funciona o código do aplicativo autenticador, por que as chaves de acesso resistem a sites falsos, o que o SMS protege e o que não protege, e para que servem os códigos de recuperação.
    
    Use o exemplo de uma loja online. No final, me faça três perguntas curtas para eu verificar se entendi, e corrija as minhas respostas.
  • TOTP por dentro

    Quero entender como funciona o TOTP, o código de 6 dígitos dos aplicativos autenticadores.
    
    Aja como um mentor e vá por etapas, esperando a minha resposta em cada uma:
    1. O segredo compartilhado, o QR code e a URI otpauth.
    2. Como o passo de 30 segundos e o HMAC geram o código, com um exemplo numérico.
    3. Por que o servidor aceita uma janela de passos, e o risco de uma janela grande.
    4. Como garantir que o mesmo código não seja aceito duas vezes.
    5. Por que um código de 6 dígitos sem limite de tentativas é inseguro, com a conta da probabilidade.
    
    Em cada etapa, me faça uma pergunta para verificar se entendi antes de seguir.
  • Chaves de acesso e phishing

    Quero entender por que as chaves de acesso (passkeys, WebAuthn) resistem a sites falsos e os códigos digitados não.
    
    Explique:
    1. Como funciona um ataque de phishing com repasse em tempo real contra TOTP e SMS.
    2. O par de chaves criado no cadastro e o desafio assinado no login.
    3. O papel do navegador ao amarrar a chave ao domínio (RP ID) e incluir a origem na assinatura.
    4. Por que o usuário não consegue entregar a chave a um site falso, mesmo caindo no golpe.
    5. O que ainda pode dar errado: sessão roubada depois do login, recuperação fraca, perda dos dispositivos.
    
    Depois me descreva três ataques e pergunte quais fatores resistem a cada um. Corrija as minhas respostas.
  • Recuperação de contas com MFA

    Quero entender como recuperar o acesso de quem perdeu o segundo fator sem abrir uma porta para atacantes.
    
    Explique:
    1. Códigos de recuperação: como gerar, mostrar e guardar.
    2. Cadastro de mais de um fator.
    3. Recuperação pelo suporte e os golpes de engenharia social contra ela.
    4. A espera com aviso antes de remover um fator.
    5. Por que remover o MFA só com um link no e-mail desfaz a proteção.
    
    Depois me descreva duas situações de usuário que perdeu o celular e pergunte como eu resolveria cada uma com segurança.