Resumo

  • A máscara do WebSocket não oferece sigilo: os quatro bytes da chave viajam no quadro, mas a imprevisibilidade impede que a aplicação determine antes do envio a imagem exata do quadro no fio.
  • A regra respondeu a uma falha concreta de intermediários: quadros do cliente devem usar uma chave nova, quadros do servidor não podem ser mascarados e a aplicação não pode alterar um quadro depois que a transmissão começa.

Os primeiros quadros confiavam nos próprios limites

O rascunho de maio de 2010 do IETF propunha um canal bidirecional para o navegador depois de uma abertura em HTTP. O formato inicial era pequeno: 0x00 iniciava um quadro de texto, 0xff o encerrava, e outra forma transportava um comprimento. Para duas pontas que falavam WebSocket corretamente, isso bastava.

Não bastava para governar cada equipamento já instalado no caminho. Um proxy de interceptação podia permitir o Upgrade e, ainda assim, continuar procurando uma nova requisição HTTP nos bytes seguintes. As pontas haviam mudado de gramática; o analisador intermediário continuava preso à anterior.

O proxy nem precisava ser malicioso. Navegador e servidor podiam cumprir o acordo. Bastava um terceiro participante atribuir o protocolo errado à sequência seguinte para produzir um efeito no cache que nenhuma das pontas havia autorizado.

Um disfarce constante ainda deixava o resultado sob controle

Em janeiro de 2011, o rascunho -04 já exigia máscara em todos os quadros do cliente para o servidor. A chave, porém, era derivada de valores da abertura e permanecia igual durante a conexão.

Uma transformação estável altera a aparência sem retirar do emissor o poder de escolher o resultado. Se a aplicação conhece a regra, pode calcular uma entrada que produza a saída desejada. O embaralhamento só surpreende quem não aprendeu a transformação.

A propriedade necessária era outra: em cada quadro, a aplicação poderia escolher a mensagem lógica ou conhecer a próxima transformação, mas não controlar as duas antes de fixar os bytes enviados. Era preciso um novo compromisso a cada limite de quadro.

O proxy deu à resposta o nome errado

O artigo de 2011 Talking to Yourself for Fun and Profit estudou mecanismos de soquete do navegador diante de proxies transparentes — mais precisamente, proxies de interceptação. Alguns equipamentos encaminhavam consentimento ou Upgrade sem compreender a mudança de estado e, depois, liam dados controlados pelo atacante como uma requisição HTTP.

A cadeia atravessava vários donos. Um site malicioso fazia o navegador se conectar a um servidor do atacante. O intermediário confundido atribuía aos bytes posteriores a identidade de outro recurso. O servidor hostil devolvia dados com aparência de resposta. O cache guardava essa resposta sob a identidade falsa, permitindo que outros usuários recebessem conteúdo que não vinha da origem nomeada.

No experimento publicitário de março de 2011, os pesquisadores observaram condições de envenenamento em uma parcela pequena, mas não nula, dos caminhos Java e Flash medidos. Entre 47.338 aberturas de um modelo de WebSocket baseado em Upgrade que chegaram ao teste, oito casos tiveram êxito. Esses números descrevem aquele experimento e aquela época; não são uma estimativa sobre proxies atuais.

A contribuição duradoura não era a prevalência. Acrescentar um prefixo não HTTP jamais provaria que todo analisador defeituoso o respeitaria; algum poderia ignorá-lo e retomar a leitura no corpo. A defesa mais firme era negar ao código hostil o controle deliberado da representação dos dados no fio.

A chave passou a pertencer a cada quadro

O rascunho -05, de fevereiro de 2011, introduziu a mudança decisiva. Cada quadro do cliente recebeu uma chave própria de 32 bits, escolhida de uma fonte forte de entropia e imprevisível a partir das anteriores. A RFC 4086 explica a cautela: uma saída pode parecer irregular e ainda ser previsível quando nasce de relógios, contadores ou de um espaço de sementes pequeno.

A RFC 6455 final preservou o desenho por quadro. O bit MASK informa a presença dos quatro octetos da chave. O octeto i do conteúdo sofre XOR com o octeto i mod 4 da chave. O comprimento não muda, e a chave não entra na contagem do conteúdo.

Qualquer receptor consegue desfazer o XOR. Isso é intencional. A aplicação precisa comprometer o conteúdo antes de conhecer a chave imprevisível; o servidor precisa receber a chave para recuperar a mensagem. O controle depende da ordem das decisões, não de um segredo.

Iniciar o envio tornou o quadro imutável

Uma chave nova seria insuficiente se a aplicação pudesse deduzi-la no início de um quadro longo e reescrever a parte ainda não enviada. Um prefixo conhecido revela a transformação repetida; uma cauda mutável poderia então ser escolhida para parecer uma requisição HTTP depois da máscara.

Por isso, a RFC 6455 fixa uma fronteira temporal. Assim que a transmissão de um quadro do cliente começa, a aplicação não pode mais modificar o conteúdo daquele quadro. Dados adicionais ou alterados devem seguir em outro quadro, sob outra chave nova.

Não se trata apenas de “usar aleatoriedade”. Antes do envio, a aplicação escolhe o significado. Depois do primeiro byte, a implementação cliente mantém sob custódia uma sequência já comprometida. Sem essa entrega de controle, observar o começo voltaria a dar poder sobre o fim.

A direção revelou o modelo de ameaça

Todo quadro do cliente para o servidor deve ser mascarado, enquanto o servidor não pode mascarar quadros enviados ao cliente. Uma ponta que recebe a direção errada deve encerrar a conexão, podendo indicar o erro de protocolo 1002.

A assimetria acompanha o ataque. Para dar uma identidade falsa a uma resposta em cache, eram necessários bytes com aparência de requisição no sentido navegador-servidor. Um servidor hostil já pode escolher dados parecidos com resposta, mas sem a requisição forjada o cache confundido não recebe o nome falso que completa o envenenamento.

Isso não torna o tráfego do servidor confiável. Autenticação, autorização, política de origem, validação de conteúdo e proteção do canal continuam sendo decisões distintas. A máscara no sentido inverso apenas não era o controle para essa falha específica.

O TLS não tornou a máscara redundante

A máscara do cliente vale tanto em ws quanto em wss, dentro do TLS. Sob criptografia ela pode parecer desperdício, pois um equipamento no caminho não lê um fluxo TLS bem protegido. Os contratos, porém, são diferentes: o TLS oferece confidencialidade e integridade entre seus terminais; a máscara limita quais bytes de quadro um código não confiável pode fazer um cliente WebSocket conforme emitir.

Manter a regra uniforme evita que a validade dos quadros dependa de onde o TLS termina. Um gateway pode terminar a proteção antes de outro salto interno, e a topologia pode mudar. A segurança de uma camada não deve conceder silenciosamente uma exceção à gramática de outra.

Os novos transportes HTTP conservaram a obrigação

A RFC 8441 passou a iniciar WebSocket com Extended CONNECT em um fluxo HTTP/2. Como :protocol sinalizava a transição, o caminho deixou de processar Sec-WebSocket-Key e Sec-WebSocket-Accept do HTTP/1.1. Ainda assim, não aboliu a máscara: as considerações de segurança da RFC 6455 continuam aplicáveis, salvo a discussão de SHA-1 específica da abertura na seção 10.8.

A RFC 9220 levou o Extended CONNECT ao HTTP/3 sem criar nova exceção de segurança. A abertura externa mudou de uma troca de protocolo na conexão HTTP/1.1 para um fluxo HTTP/2 selecionado e depois para um fluxo QUIC; o quadro WebSocket preservou a mesma evidência direcional.

Essa continuidade mostra que a máscara não era um remendo para a grafia de um cabeçalho Upgrade. Ela codificava a relação entre a escolha da aplicação, o compromisso do cliente e a confusão do intermediário, uma relação que sobreviveu à mudança do transporte ao redor.

O que a chave pública prova — e o que não prova

Uma chave nova não prova identidade, aprovação de Origin, autorização da ação nem integridade fora de um transporte protegido. Ver a chave numa captura é normal. Reuso ou previsibilidade é que indica a quebra da premissa.

A conformidade também não conserta todos os intermediários. A RFC 6455 observa que clientes e servidores não conformes ainda podem expor proxies vulneráveis à mesma classe de ataque. O protocolo reduziu o que um caminho de navegador conforme poderia ser induzido a fazer; não assumiu o controle de cada cache da Internet.

A lição histórica é precisa: quando infraestrutura antiga pode interpretar bytes sob a gramática errada, um protocolo novo não pode depender apenas de anunciar que está correto. Talvez também precise restringir quais padrões perigosos um participante não confiável consegue colocar de propósito no caminho compartilhado.

Fontes e limites da evidência

Os rascunhos e as RFCs sustentam a evolução do desenho e o comportamento normativo. O artigo relata um experimento delimitado de 2011, não uma vulnerabilidade ou participação de mercado atual. Nenhuma fonte estabelece o comportamento de um navegador, proxy, CDN ou gateway moderno específico. A máscara não é criptografia, integridade, autenticação de terminal nem prova de que uma resposta em cache pertence à origem aparente.