Pipelining HTTP: produzindo resposta antes que o corpo da solicitação tenha terminado

1

Eu sei que é possível para um cliente HTTP enviar a próxima solicitação em uma conexão TCP, mesmo que ela não tenha recebido as respostas para suas solicitações anteriores - isso é chamado de pipelining HTTP.

No entanto, é aceitável que um servidor HTTP inicie a transferência da resposta antes que a solicitação tenha sido recebida completamente? Existe um RFC que rege esse comportamento?

Por exemplo imagine um serviço que receba alguns dados via HTTP POST, faça alguma transformação e responda com os dados transformados. Se a transformação puder ser feita de forma contínua, o servidor poderá começar a produzir o corpo da resposta mesmo que o corpo da solicitação esteja incompleto.

    
por Tamás Zahola 19.12.2017 / 23:43

2 respostas

0

Eu ficaria surpreso se os padrões explicitamente descrevessem e abençoassem tal operação (porque ela é extremamente rara, você pode ter certeza de que a solicitação parcial que você recebeu contém informações suficientes para começar a produzir uma resposta) mas espero que funcione na maioria dos casos. Quaisquer dados que você enviar de volta em resposta quase certamente não serão lidos pelo cliente até que ele termine de enviar a solicitação, para que ele fique no buffer de leitura até que o cliente comece a ler. isso foi rápido!" e comece a mastigar alegremente. Não vai perceber que os dados já estavam dentro do prédio ...

Tenho certeza de que há uma implementação estranha de cliente HTTP que faz coisas estranhas com seu loop de envio, de modo que, se ele achar o soquete legível antes de terminar de escrever o pedido, ele fica assustado, mas a única maneira de encontrá-los é experimentá-lo e ver o que quebra. Ou seja, como tudo é feito em terra HTTP de qualquer maneira - e como novos padrões de comportamento são feitos (alguém faz algo insano, o que se torna popular o suficiente para que todos tenham que se adaptar, então o IETF WG diz: vou fazer desse comportamento o padrão, então ").

    
por 20.12.2017 / 00:47
0

Eu adicionarei à resposta do @wombie que isso seria bastante perigoso.

Quando um agente http (digamos, um proxy reverso ou um balanceador de carga, atuando entre o navegador e o servidor final) recebe uma resposta, geralmente assume que a consulta foi totalmente enviada e que a próxima consulta pode ser enviada de volta.

A maioria dos agentes proxy reversos não usaria pipelines ao transferir consultas para um backend final. Isso significa que, mesmo que o navegador esteja tentando fazer um pipeline de consultas n , a comunicação entre o proxy reverso e o back-end normalmente será n consultas e respostas individuais , aguardando cada resposta antes de enviar a próxima consulta (pode usar uma conexão keep alive, mas geralmente não pipelining).

Esse comportamento reduz bastante o risco de contrabando HTTP, com solicitações HTTP ou ataques de resposta.

Enviar sua resposta antes de receber todo o corpo facilitará o ataque de contrabando.

Para ser mais claro, imagine que você está enviando uma consulta única , com uma sintaxe estranha e um corpo grande. Este conteúdo do corpo se parece com outra consulta com um corpo. E o corpo dessa consulta no corpo é outra terceira consulta. Mas esta é apenas uma consulta com um corpo.

O proxy reverso tem um bug na estranha sintaxe e não vê o corpo da primeira consulta. Para o proxy, é um pipeline de 2 consultas. Então ele envia essa primeira consulta, sem o corpo, para o backend.

O servidor back-end não apresenta nenhum bug na estranha sintaxe , por isso está aguardando o corpo . Mas envia uma resposta antecipada ... começaremos a ter problemas. Se você esperasse pelo corpo completo antes de enviar a resposta, os ataques parariam por aqui.

O reverso tem uma resposta, então ele acha que pode prosseguir para a próxima consulta e envia de volta a segunda consulta (que contém um corpo com uma terceira consulta oculta) para o backend.

O backend acha que é apenas o corpo da primeira consulta e faz algo com ela ou não. Mas, para o back-end, não é uma consulta. Digamos que esse corpo tenha um tamanho de 20k e que o backend esteja esperando por um corpo de 10k. O último 10k é outra consulta para o backend, uma consulta escondida no corpo, e essa consulta será tratada como outra, com uma nova resposta.

O proxy receberá uma resposta para a terceira consulta oculta e acredita que é uma resposta para a segunda consulta.

Você pode explorar isso para o envenenamento de cache. A resposta inicial não é suficiente para construir um ataque (aqui você também precisa de uma sintaxe estranha na consulta em que o proxy e o backend terão uma percepção diferente do tamanho do corpo), mas torna as explorações mais fáceis. E, claro, você pode encontrar esse comportamento na natureza.

    
por 05.01.2018 / 15:54

Tags