Como o 'Fortalecimento da Criptografia' Quebrou a Autenticação: FreshRSS e o Limite de 72 Bytes do bcrypt
Aprofundamento CEVIU
Aprofundamento
A CVE-2025-68402 não é um erro de implementação aleatória, é um caso clássico de 'fortalecimento criptográfico' mal aplicado. Trocar SHA-1 por SHA-256 no nonce parecia uma melhoria óbvia, mas ignorou uma regra fundamental do bcrypt: ele lê apenas os primeiros 72 bytes da entrada e descarta o restante sem aviso. Como o nonce passou de 40 para 64 caracteres hexadecimais (128 bytes em UTF-8), a concatenação $nonce . $hash deixou apenas 8 bytes disponíveis para o hash real da senha, o suficiente para o prefixo $2y$10$ e um pedaço do salt, mas zero bytes para os dados que dependem da senha. Resultado: password_verify() validava qualquer senha digitada.
O erro se repete em outros projetos: a Okta sofreu com CVE-2025-61884 por concatenar identificadores longos antes do hash, e o Spring Security teve CVE-2025-22228 por não tratar senhas acima de 72 caracteres como inválidas antes de chamar matches(). A lição não é trocar algoritmos, mas entender como eles lidam com entradas compostas, e testar o comportamento sob limite, não só sob condição ideal.
Por que isso importa
Empresas que usam FreshRSS em ambientes corporativos ou governamentais para agregação de feeds de segurança, inteligência de ameaças ou monitoramento regulatório poderiam ter exposto credenciais de acesso a sistemas internos, mesmo sem ter implantado a branch edge, pois alguns administradores testam versões de desenvolvimento em ambientes paralelos. Mais grave: essa falha mostra como decisões técnicas bem-intencionadas (como migrar para SHA-256) viram vetores de ataque quando feitas sem revisão de impacto em camadas inferiores, como funções de verificação de senha. Não é sobre 'criptografia forte', mas sobre composição segura de primitivas.
Perguntas frequentes
Essa vulnerabilidade afetou versões estáveis do FreshRSS?
Não. A falha existia apenas na branch de desenvolvimento (edge), nunca foi lançada em nenhuma versão estável. Usuários que mantêm instâncias com releases oficiais (ex: 1.26.x) não foram impactados.
Por que o bcrypt trunca em 72 bytes e não dá erro?
É um comportamento intencional desde a implementação original do bcrypt em C. Ele converte a entrada em um array de 18 palavras de 32 bits (72 bytes). Entradas maiores são cortadas silenciosamente, uma escolha de projeto antiga, não um bug. Muitas bibliotecas modernas ainda replicam esse comportamento por compatibilidade.
Como evitar esse tipo de erro ao usar bcrypt com dados compostos?
Duas práticas eficazes: (1) validar o comprimento total da string antes de passar para password_verify() e rejeitar entradas acima de 72 bytes; (2) usar funções de derivação de chave (como HKDF) para combinar dados antes de alimentar o bcrypt, garantindo saída fixa e controlada.
Existe risco em migrar para Argon2 ou scrypt nesse cenário?
Argon2 não tem limite rígido de 72 bytes, mas exige cuidado com parâmetros de memória e tempo. O risco real não está no algoritmo, mas na forma como os dados são preparados. Migrar sem revisar a lógica de concatenação não resolve o problema, só muda onde ele pode reaparecer.
Fontes
- pentesterlab.comfonte original
- Categoria
- CEVIU Segurança da Informação
- Publicado
- 12 de março de 2026
- Editoria
- CEVIU Segurança da Informação
