O Link Que Você Mesmo Pode Escrever: Derivando um Token de Redefinição a Partir do Código-Fonte
O desafio
A redefinição de senha da Brightloom faz tudo o que os checklists pedem. Não revela se um endereço está cadastrado, o link expira em trinta minutos, e vai para o endereço registrado. Ele também nunca precisa chegar até você, porque o token enviado é calculado, não gerado. Três arquivos-fonte e um export do suporte a partir do console administrativo estão aqui. Descubra o token que o servidor enviaria para a conta de operações, [email protected], e escreva exatamente como o servidor escreveria.
O que você vai aprender
- Rastrear qual gerador um fluxo realmente chama quando vários se parecem
- Derivar o valor de um token executando manualmente uma format string
- Explicar por que um token de redefinição precisa ser imprevisível, não apenas único
- Identificar os campos que um atacante já pode ver como fonte de entropia do token
- Reconhecer que confirmar um token sem sessão remove a última barreira
Habilidades testadas
Pré-requisitos
- Leitura de Python
- O que strftime e o operador módulo fazem
Como funciona
Um link de redefinição de senha é uma capability. Possuí-lo equivale a provar que você controla a caixa de e-mail para onde ele foi enviado, e é por isso que o valor precisa ser imprevisível para qualquer pessoa que não recebeu o e-mail. Unicidade é uma propriedade de banco de dados e não tem nada a ver com isso: inteiros sequenciais também são únicos.
Este gerador extrai os dois componentes de campos que são exibidos em um console de suporte, em faturas e na UI administrativa. A data de cadastro e o número da conta não são segredos e nunca foram pensados como tal. Alimentá-los em uma format string produz um valor único por conta e derivável por qualquer pessoa que já tenha visto um registro de cliente, um grupo muito maior do que as pessoas com acesso à caixa de e-mail.
O que piora a situação são os controles em volta dele. Sem enumeração de contas, expiração em trinta minutos, entrega apenas ao endereço cadastrado: cada um deles está correto, e cada um deles assume que o token é a parte difícil. Quando o token pode ser calculado, eles protegem a coisa errada, e o endpoint de confirmação buscar um token sem sessão associada é o que transforma o cálculo em uma tomada de conta.
Erros comuns
- Usar a coluna id. A linha de operações tem
id7741 eaccount_no40218. O gerador lêaccount_no. - Pegar a data da linha de faturamento. Ela compartilha a data de cadastro 2024-03-11, mas tem um número de conta diferente.
- Pegar os dígitos de Rosa Castellanos. O
account_nodela, 30218, também termina em 0218, por isso uma linha errada ainda parece plausível. - Usar invite_token. Está bem acima da função que importa e usa o dia do ano com três dígitos. O fluxo de redefinição não a chama.
- Descartar o zero à esquerda. O formato é
%04d, então é0218, e não218. - Se tranquilizar com
secrets.token_urlsafe. Está no mesmo arquivo, mas é usado para sessões, não para redefinições.
Como se proteger
Gere o token, não o derive.
- Use um valor aleatório criptograficamente seguro de pelo menos 128 bits, por exemplo
secrets.token_urlsafe(32), que este arquivo já importa para sessões. - Armazene um hash do token em vez do token, para que uma leitura do banco de dados não entregue links de redefinição ativos.
- Vincule a confirmação a algo além do token: aplique rate limit rigoroso, invalide todas as outras sessões em caso de sucesso, e envie um e-mail para a conta quando a senha for alterada.
- Invalide tokens pendentes quando um novo for solicitado, e mantenha a expiração curta. Ambos são baratos e ambos limitam a janela.
- Trate BILL-1877 como o achado que é. Uma linha de redefinição que pode ser consumida por qualquer pessoa que saiba o nome, sem rate limit, é a segunda metade desse bug.