HTTP/2

La segunda versión del protocolo HTTP propone varios cambios sobre el HTTP original. El nuevo protocolo pretende resolver los problemas inherentes a HTTP/1.1 cambiando el formato de mensaje y cómo el cliente y el servidor se comunican. Una de las diferencias significativas es que las peticiones y respuestas HTTP/2 usan un protocolo binario completamente diferente, al contrario que HTTP/1.1 que es legible para humanos. Esto es una mejora masiva sobre la versión antigua ya que permite mandar información binaria de una forma que sea más fácil para las máquinas de parsear sin cometer errores.

Aunque el formato binario de HTTP/2 es difícil de leer para los humanos, usaremos una representación más simple de las peticiones en esta lección. Aquí una representación visual de HTTP/2 comparado a HTTP/1.1:

HTTP-2 Explained

Una petición HTTP/2 tiene los siguientes componentes:

  • Pseudo-headers: HTTP/2 define algunos headers que comienzan con :. Esos headers son el mínimo requerido para una petición HTTP/2 válida. En la imagen de arriba, vemos :method, :path, :scheme y :authority.
  • Headers: Después de los pseudo-headers, tenemos headers normales, como user-agent o content-length. Fíjate que HTTP/2 usa minúsculas para los nombres de los headers.
  • Request Body: Como en HTTP/1.1, esto contiene la información adicional mandada con la petición, como los parámetros POST, archivos e información subida.

Otro cambio importante en la estructura de una petición es que HTTP/2 establece fronteras precisas para cada parte de la petición o la respuesta. En lugar de depender de caracteres específicos como \r\n para separar diferentes headers o : para separar el nombre del header del valor como HTTP/1. HTTP/2 añade un campo para rastrear el tamaño de cada parte de la petición o respuesta.


Request Smuggling y HTTP/2

Una de las razones principales por las que HTTP Request Smuggling es posible en escenarios HTTP/1 es la existencia de diferentes maneras de definir el tamaño del body de una petición. Esta ambigüedad en el protocolo lleva a que diferentes proxies usen su propia interpretación de dónde una petición acaba y empieza otra, finalmente llevando a escenarios de contrabando.

La segunda versión de HTTP fue construida para mejorar muchas de las características de la primera versión. La que más nos importa en el contexto de HTTP Request Smuggling es la clara definición de los tamaños para cada componente de la petición HTTP. Para evitar ambigüedades, HTTP/2 prefija cada componente de la petición con su tamaño para que los parseadores sepan cuánta información esperar. Para entender esto mejor, veamos una petición capturada en Wireshark, fijándonos en los headers de la petición:

HTTP-2 Explained

En la imagen vemos el pseudo-header :method. Como podemos observar, ambos componentes del header (tanto nombre como valor) están definidos en tamaño. El header name tiene una longitud de 7, correspondiendo a :method y una longitud de header value de 3, correspondiendo a GET.

El body de la petición también incluye un indicador de longitud, renderizando headers como Content-Length y Transfer-Encoding: chunked, sin importancia en los entornos HTTP/2.

NOTE

Aunque los headers Content-Length no sean usados directamente en HTTP/2, los navegadores modernos pueden seguir incluyéndolos en escenarios específicos donde una degradación de HTTP pueda ocurrir.

Con dichas fronteras tan clara, cualquiera esperaría que el smuggling fuera imposible. Sin embargo, como con cualquier protocolo nuevo, no todos los dispositivos pueden ser actualizados a él directamente. Esto resulta en implementaciones donde balanceadores de carga o reverse proxies, que soportan HTTP/2, sirven contenido de server farms que todavía usan HTTP/1.