Resumo

  • O TLS executava um segundo handshake dentro do canal cifrado sem criar um vínculo criptográfico entre as duas negociações.
  • A RFC 5746 fez o novo handshake carregar a prova do anterior; o TLS 1.3 depois removeu a renegociação.

Um canal, duas origens

O atacante primeiro cria sua própria conexão TLS com o servidor e envia um prefixo da aplicação. Pode ser o começo de uma requisição que só ganhará efeito quando bytes posteriores chegarem. Em seguida, encaminha o novo handshake de uma vítima pela conexão já protegida que mantém com o servidor.

Para a vítima, trata-se de sua negociação inicial com o servidor verdadeiro. Para o servidor, o mesmo tráfego aparece como uma renegociação da conexão do atacante. Ao final, o atacante não consegue ler a comunicação posterior da vítima. O erro está na autoria: o servidor pode unir o prefixo adversário aos bytes autenticados da vítima e interpretar tudo como uma única operação.

A RFC 5746 separou propriedades que pareciam idênticas. Continuidade do transporte, continuidade da cifra e continuidade do transcript da aplicação não são a mesma coisa. Manter o socket aberto não prova quem deve responder pelos dados enviados antes e depois de uma mudança de identidade criptográfica.

A prova guardada no Finished

A correção mantém estado por conexão: uma indicação de renegociação segura e os valores verify_data que cliente e servidor enviaram nos Finished do handshake imediatamente anterior. Esses valores comprovam que os dois lados viram aquela negociação específica.

A extensão renegotiation_info, tipo 0xff01, usa um campo vazio no handshake inicial. Assim, os pares anunciam suporte sem alegar um passado inexistente. Em uma renegociação, o ClientHello leva o verify_data anterior do cliente; o ServerHello leva a concatenação dos valores anteriores de cliente e servidor. A ausência da extensão ou qualquer divergência exige o aborto do handshake.

O atacante pode transportar a negociação da vítima, mas não pode fazê-la apresentar a prova correta da conexão anterior do atacante. O novo handshake é aceito não porque está envolto pela cifra antiga, e sim porque identifica de maneira autenticada o handshake que pretende continuar.

Compatibilidade como parte do risco

Algumas implementações antigas encerravam a negociação ao encontrar extensões desconhecidas, embora devessem ignorá-las. Para facilitar a transição, a RFC 5746 definiu TLS_EMPTY_RENEGOTIATION_INFO_SCSV. O valor aparece na lista de suites, mas não representa algoritmos e não pode ser escolhido; ele apenas sinaliza o mesmo suporte de uma extensão inicial vazia.

Ainda restava ambiguidade. Um servidor sem a nova sinalização poderia aceitar renegociação insegura ou poderia ter desativado toda renegociação e, por isso, não ser vulnerável. O cliente não tinha como provar qual política estava em vigor. Encerrar a conexão favorecia a garantia; continuar favorecia a interoperabilidade. A implantação tornou a ausência de evidência uma decisão operacional, não um detalhe neutro.

O TLS 1.3 remove a transição

A RFC 8446 proíbe renegociação no TLS 1.3. Um ClientHello fora do momento previsto leva ao encerramento da conexão. Atualização de chaves e autenticação pós-handshake continuam existindo como mecanismos separados, sem recriar a renegociação geral.

A RFC 9325 preserva a obrigação no TLS 1.2: clientes e servidores devem implementar renegotiation_info, e o cliente deve terminar a conexão se o servidor não reconhecer a extensão. As fontes não medem o total de vítimas em 2009 nem o número atual de sistemas que renegociam. Elas estabelecem o defeito, a ligação corrigida e a retirada posterior. A regra histórica é clara: toda transição de chave ou identidade deve provar o estado que herda. O canal cifrado, sozinho, não faz essa prova.

Fontes