flawopen.com/Teardowns/cve-2026-61500-rejetto-hfs-predictable-session-key
CVE-2026-61500: chave previsível de assinatura de sessão no Rejetto HFS
O Rejetto HFS 3.0.0–3.2.0 usava valores derivados de Math.random() para assinar sessões e no login. A Horizon3 relata que a exposição permitia falsificar sessões; a VulnCheck diz que observou atividade de exploração a partir de 1º de outubro. Atualize para 3.2.1+; não há comprometimento de vítima específica confirmado.[1], [4], [5]
A assinatura de um cookie é como um selo de cera em uma credencial administrativa. O HFS criava o segredo do selo com uma sequência numérica previsível, enquanto o login revelava outros números da mesma sequência. Se alguém deduz o segredo, consegue falsificar o selo. A correção passa a usar a aleatoriedade criptográfica do Node.js.[1], [3]
Conceitos Centrais e Termos
Chave de assinatura de sessão- Segredo usado pelo Koa para assinar cookies de sessão e permitir detectar adulterações.[1], [3]
Math.random()- API pseudorrandômica de uso geral, inadequada para gerar segredos criptográficos.[6], [4]
CWE-338- Uso de um gerador de números pseudoaleatórios criptograficamente fraco; fraqueza mapeada no registro CVE.[1], [6]
Estado do PRNG- Estado interno que determina os próximos valores pseudoaleatórios. Usar o mesmo gerador para um segredo e valores observáveis pode revelar relações entre eles.[4]
Contexto da descoberta- A Horizon3 afirma que seu sistema de pesquisa multiagente, com apoio do Mythos, identificou e validou esta cadeia de vulnerabilidades do HFS. Isso descreve como pesquisadores encontraram a falha; não é uma vulnerabilidade do Mythos nem prova de ataque autônomo de IA a uma instalação real.[4]
Mapeamentos de frameworks
- Referência CWE para a fraqueza descrita neste guia: CWE-338
Análise de Causa Raiz
O registro CVE identifica as versões 3.0.0 a 3.2.0 do HFS e a CWE-338. No commit upstream 59472e5, o código vulnerável fornecia ao Koa [randomId(30)]; randomId() usava Math.random(). A correção troca isso por [randomBytes(32).toString('base64url')], importado de node:crypto. O mesmo commit muda o identificador público do handshake de login de Math.random() para randomUUID(). A Horizon3 relata que respostas de login acessíveis sem autenticação expunham saídas relacionadas suficientes para recuperar o estado do PRNG V8 e derivar a chave de assinatura. Com uma sessão administrativa falsificada, funções administrativas internas poderiam levar à execução de código no servidor. Este artigo descreve a cadeia em alto nível, sem reproduzir o solucionador, as requisições ou os payloads. A VulnCheck informa que o Canary Intelligence começou a observar atividade de exploração em 1º de outubro de 2026, em relatório publicado em 2 de outubro; essa telemetria não identifica uma instalação HFS comprometida.[1], [3], [4], [5]
Fluxo de Ataque Passo a Paso
A fraqueza atravessa a barreira da sessão
Segundo a Horizon3, as saídas permitiam recuperar o estado do PRNG, viabilizando falsificação da assinatura da sessão e acesso administrativo. O procedimento detalhado de recuperação foi omitido.[4]
O acesso administrativo pode chegar à execução no servidor
A Horizon3 documenta a cadeia da sessão administrativa falsificada até a funcionalidade server_code do HFS. A VulnCheck informa que seu Canary Intelligence começou a observar atividade de exploração em 1º de outubro de 2026, conforme relatório de 2 de outubro; essa telemetria não comprova o comprometimento de uma instalação específica.[4], [5]
Código-Fonte: Vulnerável vs. Seguro
Os trechos refletem o commit upstream real. randomBytes(32) fornece 256 bits do módulo criptográfico do Node.js para a chave; randomUUID() substitui a fonte do identificador público de login. Segredos que autenticam sessões devem vir de uma fonte criptográfica e ser independentes de saídas observáveis do PRNG da aplicação. Atualize para HFS 3.2.1 ou versão suportada posterior; este trecho explica a correção, mas não é um patch independente. Isso protege apenas o valor gerado como fallback: se COOKIE_SIGN_KEYS estiver configurada, cada chave fornecida também deve ser gerada independentemente com aleatoriedade criptográfica, mantida em segredo e trocada se for exposta.[3], [1]
Trecho de origem: src/index.ts (chave de assinatura de cookies) e src/api.auth.ts (identificador do handshake de login, commit upstream 59472e5)
import { httpStream, randomId } from './misc'
const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
|| [randomId(30)]
export const app = new Koa({ keys })
const sid = Math.random()
import { randomBytes, randomUUID } from 'node:crypto'
const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
|| [randomBytes(32).toString('base64url')]
export const app = new Koa({ keys })
const sid = randomUUID()
Lista de Verificação de Segurança para Engenharia
- ✓Atualize HFS 3.0.0–3.2.0 para 3.2.1 ou posterior; prefira a versão estável suportada mais recente.[2], [1]
- ✓Inventarie instâncias HFS em hosts Windows, contêineres, ambientes de teste e compartilhamentos expostos à internet; registre versões e exposição.[4]
- ✓Se não puder atualizar imediatamente, restrinja o acesso a redes confiáveis e remova a exposição pública enquanto planeja a atualização. Isso reduz a exposição, mas não corrige a geração fraca da chave.[4]
- ✓Após atualizar qualquer instância que esteve publicamente acessível enquanto vulnerável, invalide todas as sessões existentes e troque qualquer
COOKIE_SIGN_KEYSconfigurada; se a investigação encontrar atividade administrativa não autorizada, troque também as credenciais de administrador. Preserve os registros para análise.[1], [4] - ✓Trate sondagens observadas como motivo para investigar, não como prova de comprometimento. Preserve registros e procure alterações de configuração ou execução não autorizadas.[5], [4]
- ✓Em aplicações Node.js, verifique se cada valor configurado em
COOKIE_SIGN_KEYSfoi gerado independentemente com aleatoriedade criptográfica, é mantido em segredo e será trocado se exposto; o fallback seguro não valida valores substitutos. Para outros segredos, use APIs denode:crypto, comorandomBytes(). Nunca derive chaves de assinatura, tokens de redefinição ou valores de autorização deMath.random().[3], [6]