Rapid Reset, que es nombre asignado a la vulnerabilidad 0-day, permite realizar ataques DDoS a través de un fallo estructural de HTTP/2.
Cloudflare, Amazon Web Services y Google Cloud Platform, presentaron sus hallazgos respecto a una serie de ataques ocurridos desde hace unos meses, donde una vulnerabilidad zero-day en el protocolo HTTP/2, —denominada HTTP/2 Rapid Reset—, permitió que cibercriminales llevaran a cabo enormes ataques de denegación de servicio distribuidos —DDoS, como se les conoce habitualmente—, contra la infraestructura de las compañías antes mencionadas, dirigido principalmente a sitios web.
HTTP es una pieza fundamental para la operatividad de la red de redes. Es el protocolo que permite que los navegadores puedan interactuar con los sitios web, y solicitar contenido —como texto e imágenes—, a un determinado servidor.
A finales de agosto de este año, Cloudflare descubrió que la vulnerabilidad aprovecha la estructura de HTTP/2 para realizar ataques de saturación HTTP, luego de que su red bloqueara un DDoS de más de 201 millones de peticiones por segundo, en una tendencia que apuntaba a meses de ataques similares.
Por su parte, AWS y Google Cloud Platform también sufrieron una cantidad inusualmente alta de tráfico HTTP/2, con 155 y 348 millones de peticiones en el punto más alto, respectivamente. Considerando que el último récord de un ataque mitigado con éxito era de 46 millones de solicitudes, queda claro que hablamos de un asunto grave.
HTTP/2 Rapid Reset técnicamente sería un ataque de saturación HTTP, que —según define AWS— consisten en un gran volumen de peticiones web ilegítimas, que son enviadas a un servidor web hasta sobrepasar sus capacidades, inhabilitándolo para continuar respondiendo a solicitudes de clientes legítimos.
HTTP/1.x, la primera versión de este protocolo, basa su funcionamiento en ir respondiendo las solicitudes web a manera que van llegando. El servidor recibe la petición desde el cliente, la procesa y posteriormente la responde, para continuar con la siguiente petición. En la práctica, esto significa que cada petición —o dato— necesita abrir una conexión independiente a través de la red, por cada viaje de ida y vuelta.
Como es de esperar, un ataque de denegación de servicio bajo este protocolo implica emitir una cantidad absurdamente alta de peticiones a un servidor web, hasta que éste caiga.
Una de las características estrella de HTTP/2, es el uso del «stream multiplexing«, que es una técnica que habilita a un servidor para establecer varios «streams» de datos en simultáneo, a fin de lograr un mejor aprovechamiento de cada conexión TCP entre cliente y servidor.
Pensemos en cada stream como una especie de «puente», que conecta una gran cantidad de datos desde las dos secciones. El uso de streams hace que la navegación sea mucho más eficiente y rápida para los usuarios, ya que se reduce el tiempo de carga de las páginas o servicios compatibles, al enviar todo por un mismo canal de datos, sin necesidad de generar una conexión por cada elemento, como sucedía con HTTP/1.x.
Cada stream tiene como característica que las dos partes puedan monitorear su estado, además de permitir que los clientes puedan realizar múltiples peticiones al vuelo dentro de ellos, sin necesidad de establecer nuevas conexiones con cada solicitud.
Por su parte, los clientes pueden indicarle al servidor que un stream previo debería ser restablecido o cerrado, mediante el envío de un frame RST_STREAM. Dado que el protocolo no requiere que el cliente coordine la cancelación con el servidor web, el cliente puede hacerlo de manera unilateral. Y aquí es donde la cosa se pone interesante.
Esta dinámica permite que el cliente asuma que la cancelación es de efecto inmediato cuando el servidor recibe el frame RST_STREAM, antes de que cualquier otro dato sea procesado.
Rapid Reset aprovecha la capacidad de un cliente —o endpoint— para enviar un frame RST_STREAM inmediatamente después de emitir una petición, lo que hace que la otra parte procese la solicitud e inmediatamente restablezca el stream. La petición estaría cancelada, pero la conexión seguiría abierta.
Google menciona que, al hacer uso de HTTP/2, los clientes pueden abrir múltiples streams concurrentes en una misma conexión TCP. Este número, en teoría, es controlable por el servidor, pero en la práctica, los clientes son capaces de abrir todos los streams que quieran por petición, y los servidores deberán procesar todas esas solicitudes en paralelo, sin la posibilidad de ajustarlas unilateralmente.
A partir de aquí, la cosa se simplifica para el cibercriminal, ya que tendría la capacidad de iniciar un gran número de streams a la vez, tal como sucede en los ataques DDoS comunes a HTTP/2, pero antes de esperar una respuesta desde el servidor, es el mismo cliente quien las cancela todas a la vez, repitiendo una y otra vez el proceso, para máxima saturación.
En un ejemplo hipotético, un cliente puede abrir 100 streams simultáneos por viaje y enviar una petición en cada uno de ellos. A su vez, el cliente puede continuar abriendo nuevos streams mientras recibe las respuestas de los pasados, dando una tasa de transferencia efectiva de 100 peticiones por cada viaje de ida y vuelta, con hasta 100 veces mejor utilización de cada conexión, comparado con un ataque DDoS tradicional.
Según indica Google en su blog, el servidor aún tendrá que hacer una cantidad significativa de trabajo cuando existan peticiones canceladas dentro de una implementación típica de HTTP/2. Concretamente, todavía necesitará reservar nuevas estructuras de datos para streams, analizar las solicitudes y descomprimir cabeceras, junto a la asignación de URL a cada recurso solicitado.
Este mecanismo de apertura y cierre simultáneo hace que el atacante pueda tener un número prácticamente indefinido de peticiones al vuelo, pero al ser canceladas de inmediato, el atacante jamás excederá el límite de streams concurrentes abiertos. Dicho eso, el número de peticiones al vuelo ya no dependerá del tiempo —de ida y vuelta— que las respuestas tardarán en llegar al cliente, sino del ancho de banda disponible entre el cliente y el servidor.
Por si fuera poco, las tres compañías afirman que la botnet encargada de realizar el ataque, es de apenas unos 20,000 equipos, una cifra insignificante si la comparamos con las de otros eventos similares, que son —al menos— uno o dos órdenes de magnitud superiores.
Aunque no se sabe a ciencia cierta de dónde provienen los ataques, Google observó distintos métodos de explotación de Rapid Reset, que si bien son menos efectivos que los primeros, siguen siendo de mayor impacto que cualquier otro DDoS tradicional.
Una de las variantes no cancelaba de manera inmediata los streams, sino que abría un montón de ellos a la vez, y los cerraba después de un tiempo, para luego abrir más y repetir el proceso. Este tipo de ataque podría saltar mitigaciones basadas únicamente en la tasa de entrada de los frames RST_STREAM, como permitir un máximo de 100 RST_STREAM por segundo en una conexión, antes de cerrarla.
Otra, por su parte, intentaba abrir más streams de los permitidos por el servidor, pero no cancelaba ninguno, sino que trataba de mantener el límite anunciado, y las conexiones siempre abiertas y ocupadas. El estándar HTTP/2 actual, que corresponde a la especificación RFC 9113, sugiere que el servidor únicamente debe invalidar los streams que se exceden del límite, más no toda la conexión. Esto representa un problema, ya que no todos los servidores podrán rechazar este tipo de ataque, y en su lugar, seguirán procesando streams luego de responder a los anteriores.
Simplificando todo lo anterior, un atacante podría realizar —de forma mucho más eficiente— ataques de denegación de servicio a un servidor web, a prácticamente cualquier servicio que se encuentre desprotegido en la internet.
Lamentablemente, no hay mucho que hacer para contrarrestar este problema de manera directa. Tal y como indican las tres compañías, la solución parece ser multifacética.
Google, por su parte, añade que bloquear individualmente las peticiones podría no ser una solución viable contra Rapid Reset, ya que es necesario cerrar conexiones completas cuando se detecte abuso. En teoría, HTTP/2 incorpora soporte para cerrar conexiones enviando un frame GOAWAY a los clientes, pero la realidad es que no se encuentra implementado en una forma tan robusta contra los clientes maliciosos.
Por otro lado, este vector de ataque seguramente continuará evolucionando de a poco, y la única forma para poder detectar y bloquear manualmente todas esas conexiones, sería mediante el uso de estadísticas internas y procedimientos para detectar la utilidad de esas conexiones. Esto es, si una conexión tiene más de 100 peticiones, y más del 50% de ellas son canceladas, esta podría ser una candidata para su terminación. Ya sea a través de frames GOAWAY, o cerrando las conexiones TCP asociadas.
En cuanto a servicios como Google Cloud Armor, AWS Shield y Cloudflare DDoS Protection, los tres proveedores han implementado algunos cambios para reducir el peligro que conlleva Rapid Reset a sus clientes. Dicho eso, no será necesaria —de momento— alguna acción al respecto.
Desafortunadamente, tocará esperar a que las distintas comunidades y empresas liberen actualizaciones para todas y cada una de sus implementaciones del estándar HTTP/2 afectadas por la vulnerabilidad CVE-2023-44487, a fin de reducir el impacto de Rapid Reset en la medida de lo posible, aunque una protección DDoS podría servir en el corto plazo.