Seguridad a través de la restricción del usuario o cómo crear una vulnerabilidad

En 2019, se descubrió la vulnerabilidad de denegación de servicio envenenada de caché CPDoS en la red CDN, lo que permite envenenar el caché HTTP del proveedor de CDN y causar una denegación de servicio. La vulnerabilidad aún no ha generado mucha expectación, ya que no se ha visto en ataques reales. Pero quiero hablar sobre uno de los métodos de envenenamiento de caché por separado. Método HTTP Override.


Si otras variantes de explotar la vulnerabilidad de una forma u otra se basan en errores o características de modificación de solicitud por parte de un intermediario, entonces la variante de Anulación de método se basa en la táctica del mismo nombre, que no forma parte del estándar HTTP, conlleva problemas adicionales, que surgieron y se propagaron por descuido relación con la seguridad. Aquí lo consideraremos.

Corto sobre CPDoS si te lo perdiste
, URI method .

, , , , - . — - - -, , - , . , .

, . , , -. - , , .


Limite al cliente, menos puede - menos se romperá


La necesidad de anular el método en la solicitud surgió debido al hecho de que algunos firewalls de aplicaciones web e implementaciones de clientes HTTP eran muy limitados y no permitían la ejecución de métodos distintos a GET y POST. El problema no es que se tratara de una restricción de implementación, sino que era una restricción intencional de clientes HTTP por una política de seguridad.

Está claro que todo se llevó a cabo con buenas intenciones para cortar el tráfico reducido, no estándar para clientes HTTP comunes. Pero en pos de la seguridad, se cortaron todos los métodos, excepto GET y POST. Quizás porque estos son los únicos métodos que no son opcionales y necesarios para servidores de uso general.

No está claro por qué se requería introducir una restricción tan estricta. Sí, los ataques con la introducción de varios caracteres para confundir al analizador son solo el pasatiempo de los protocolos de texto. Pero podría permitir un poco más de métodos, por ejemplo, tome al menos los que se describen en el estándar en sí o que están registrados en IANA . No valía la pena eliminar por completo la verificación del método, pero podría marcar varios de los métodos más populares y excluir de ellos aquellos que cambian el protocolo de interacción y rompen el trabajo con las conexiones en el servidor proxy (CONNECT). Pero no, resultó una política de seguridad que introdujo restricciones y prohibiciones innecesarias para los clientes.

Y los clientes se limitaron a los equivocados. Querían limitar la variabilidad de los mensajes de los clientes HTTP y limitar los clientes que protegían estos WAF, los servidores de aplicaciones finales y sus desarrolladores. Ahora, los desarrolladores solo tenían dos métodos que no siempre eran suficientes para describir la lógica del cliente HTTP.

Se crean restricciones para superarlos.


Era de esperar que esta restricción excesiva tarde o temprano comenzaría a interferir con los desarrolladores web. La ironía es que es muy fácil no deshacerse de tales WAF. Especialmente cuando están con clientes o proveedores. Desafiar las políticas de seguridad de otras personas es un asunto desastroso.

Debido a la flexibilidad de HTTP, no es difícil eludir esta limitación; solo agregue algo a la solicitud donde pueda anular el método. El WAF estricto solo verificará el método en la línea de solicitud (la primera línea de la solicitud) y estará encantado de ver un GET o POST aprobado allí. Y el backend podrá analizar el elemento agregado y extraer el método real de él.

Puedes buscar en Google un montón de artículos, realmente un montónsobre cómo los proxies malos rompieron las aplicaciones REST y cómo los autores tuvieron que pasar el método real en un encabezado separado. En todos ellos, sugieren que ingrese aproximadamente el mismo encabezado (X-HTTP-Method, X-HTTP-Method-Override o X-Method-Override - la ortografía varía un poco) para indicar un método anulado. Muy, muy raramente se pueden encontrar referencias que se puedan usar para el mismo propósito de URI de componente de consulta.

Lo que falta en estos artículos es la sección Consideraciones de seguridad. Y ellos simplemente son.

¿La anulación de métodos es segura?


A veces los desarrolladores de aplicaciones web olvidan que entre el cliente y el servidor puede haber participantes intermedios que interactúan a través del protocolo HTTP: servidores proxy, cachés web de proveedores, CDN y WAF. La proliferación de TLS reduce en gran medida la posibilidad de un participante intermedio entre el cliente y el servidor. Lo más probable es que el único proxy entre el cliente y el backend sea su propio servidor con Nginx. Y dicha configuración es bastante fácil de probar en escenarios típicos antes del lanzamiento.

Pero estamos avanzando hacia la era de CDN, y cada vez más aplicaciones se esconderán detrás de CDN que leen y manipulan el tráfico de usuarios. Los backends directamente casi nunca sirven a los usuarios y se esconden detrás de servidores proxy inversos para aumentar la capacidad de respuesta y el rendimiento. Por lo tanto, deberá recordar cómo anular un método puede afectar el procesamiento de una solicitud en un servidor de mediación.

Los ataques de los que quiero hablar son principalmente aplicables a HTTP / 1.1. HTTP / 2 de alguna manera hereda el comportamiento del antiguo estándar, de alguna manera sigue su propio camino, por lo que la aplicabilidad de cada ataque al nuevo estándar se considerará por separado.

Ataques de caché


La mayoría de las veces, los servidores intermedios no tienen en cuenta las anulaciones de métodos, no verifican los encabezados de la familia X-HTTP-Method-Override y trabajan con la solicitud utilizando su método principal desde la Línea de solicitud. Y dado que el método anulado no se incluye en la clave para buscar una solicitud en la memoria caché (método + URI), dichos servidores no pueden distinguir POST de POST + X-HTTP-Method-Override: DELETE. Esto significa que no puede permitir el almacenamiento en caché de ninguna solicitud a un determinado URI si el back-end puede monitorear y ejecutar métodos anulados.

El documento CPDoS tiene un buen ejemplo de lo que sucede si almacena en caché dicha solicitud. Cuando un atacante disfraza una solicitud POST como una solicitud GET, el proxy no reconoce las sustituciones y trata la solicitud como una solicitud GET legítima. Sin embargo, el backend reconoce el método reemplazado y ejecuta el verbo descrito en el encabezado POST de X-HTTP-Method-Override. Como el método POST no está definido para el URI de destino, el servidor genera un error. Además, la respuesta del backend se almacena en la memoria caché como respuesta al método original: GET. Ahora cualquier próxima solicitud GET para el mismo URI devolverá un error en caché.


De hecho, el ataque es ligeramente más amplio que el presentado en el documento. Los autores se centraron en almacenar el error en la memoria caché, que no está en todas partes (ya) puede reproducirse. Pero si el método solicitado para el URI seleccionado está definido y se ejecutará con éxito, el proxy recibirá una respuesta con un estado de 200 y lo almacenará en caché. Luego, las solicitudes posteriores del mismo URI para recibir respuestas al método completamente incorrecto. En este escenario, ya no hay un requisito con un error de caché de respuestas 4XX, como en la descripción original de CPDoS.

El problema inverso puede ocurrir. Si un cliente HTTP respetable envía una solicitud GET + X-HTTP-Method-Override: PATCH (esto es malo, pero más sobre eso más adelante), y el caché ya tiene una respuesta GET, entonces el cliente recibirá esta respuesta en caché. En este caso, el backend nunca recibirá una solicitud PATCH, que puede violar la lógica de la aplicación tanto en el cliente como en el servidor.

Puede reducir el efecto en la memoria caché creando las políticas de almacenamiento en caché correctas y dividiendo los recursos en dos grupos: aquellos para los cuales la operación de anulación del método es inaceptable o no se requiere, las respuestas a ellos pueden almacenarse en caché y aquellos para los que la operación de anulación del método es necesaria, cualquier almacenamiento en caché de tales respuestas es inaceptable . Pero cuanto menos recursos se almacenan en caché, menos útil es el CDN y cuanto más tráfico llega al backend, más se expone la aplicación a la inundación HTTP.

Por lo tanto, es mejor usar el caché HTTP tanto como sea posible, para esto es necesario que el servidor de caché pueda distinguir entre solicitudes con diferentes métodos anulados. La primera forma es transferir la anulación del método del componente de consulta al URI:

POST /some-uri HTTP/1.1
X-HTTP-Method-Override: DELETE
   ↓  ↓   ↓
POST /some-uri?method=DELETE HTTP/1.1

Ahora las solicitudes con diferentes métodos se ven diferentes para el caché, ya que obtienen diferentes claves. Algunos servidores proxy prefieren no almacenar en caché las respuestas a las solicitudes que contienen el componente de consulta en el URI. Pero esto solo afectará la eficiencia del almacenamiento en caché. Este método siempre resuelve problemas con el almacenamiento en caché incorrecto.

Otra forma es dejar la anulación del método en un encabezado separado, pero ingrese una clave secundaria para encontrar la respuesta en el caché. Esto es posible con el encabezado Vary. Al atender la solicitud, el servidor repetirá el encabezado con la anulación del método y reflejará el nombre de este encabezado en el encabezado Vary. Luego, en las siguientes solicitudes, el servidor de caché utilizará el valor del método anulado como clave secundaria cuando busque una solicitud en la caché.


Este método funciona si el servidor intermedio puede trabajar con claves secundarias. Este suele ser el caso, pero el nivel de confianza del proxy, que corta todos los métodos excepto GET y POST, generalmente es más bajo y es mejor verificar esto.

Anular un método a través de cualquier entidad dentro del cuerpo de la solicitud tiene exactamente los mismos inconvenientes que anular a través de un encabezado adicional: está fuera de la visibilidad del caché.

Ataques de mensajes en cola


Incluso si los ataques de caché están cerrados, eso no es todo. Un atacante anulando un método puede intentar cambiar el marco de la respuesta y, por lo tanto, violar la correspondencia de los pares de solicitud-respuesta para otros clientes. O forzar el lado del servidor de la aplicación para procesar la misma solicitud varias veces.

Lo más importante que se requiere para esto es un servidor intermedio que funcione en modo proxy inverso. Es decir, cualquier caché o servidor CDN. Dicho proxy admite un número relativamente pequeño de conexiones al backend y multiplica las solicitudes de muchos clientes en cada una de ellas. Esto es necesario tanto para asumir la carga de soportar una gran cantidad de conexiones de clientes desde los servidores al servidor proxy como para equilibrar la carga entre los servidores. La terminación de las conexiones TLS también ocurre en el proxy, las conexiones del cliente nunca se conectan directamente al backend.

Dado que ahora las solicitudes de diferentes clientes estarán en la misma conexión entre el servidor y el proxy, es necesario mantener una correspondencia clara entre los pares de solicitud-respuesta. La mayoría de los servidores proxy no se canalizan(canalizaciones) solicita al back-end y trabaja con él en el modo de solicitud-respuesta. El modo de solicitud-respuesta es más simple y está sujeto a prácticamente una amenaza: el bloqueo de la conexión. Si hace que la conexión se cuelgue en un solo par de solicitud-respuesta, puede causar un retraso o incluso una negativa a procesar las siguientes solicitudes (por ejemplo, si logra desbordar las colas de solicitudes de proxies).

Solicitudes de canalización de servidores proxy más productivos al backend: esto le permite enviar un paquete de solicitudes al servidor de inmediato y esperar su ejecución. El rendimiento es mayor, pero hay más amenazas. En primer lugar, el problema del bloqueo de cabecera de línea no desaparece en ningún lado, incluso si el backend puede rastrear la canalización de consultas y ejecutarlas en paralelo, no se pueden enviar si el primero se cuelga. En segundo lugar, si interrumpe el encuadre de la respuesta, puede confundir el proxy y romper la correspondencia de los pares de solicitud-respuesta, entonces algunos clientes pueden obtener las respuestas de otras personas, o al menos lograr un cierre de conexión instantánea con el back-end.


La redefinición más simple y divertida de un método es reemplazar GET con el verbo HEAD. Si la respuesta a la primera tiene un cuerpo, entonces la segunda no. Además, todos los demás encabezados son iguales, incluidos los que proporcionan el marco de la solicitud. Cuando el proxy redirige un HEAD anulado al servidor, esperará del servidor no solo los encabezados de respuesta, sino también el cuerpo de respuesta, que el backend no enviará. Si el proxy y el servidor interactúan en el modo de solicitud-respuesta, la conexión se "colgará" hasta que se rompa por tiempo de espera.

Si el servidor envía las siguientes respuestas (modo canalizado), entonces se pueden analizar no como respuestas independientes, sino como parte de la respuesta incompleta anterior al GET. El proxy los colocará (o parte de ellos) en el cuerpo de la respuesta "OBTENER" y lo enviará al atacante para leerlos. Puede crear un pseudo-GET para recibir un archivo grande y volcar algo de tráfico entre el proxy y el back-end. El éxito depende de cómo el backend coloca Content-Length y Transfer-Encoding: encabezados fragmentados para enmarcar mensajes. El primero casi siempre le permitirá obtener un volcado, el segundo a menudo generará errores de análisis y provocará una desconexión del back-end. Si no tienes suerte, entonces el pseudo-GET puede cubrir varias respuestas en su totalidad y finalizar justo antes de la siguiente respuesta.El proxy no podrá reconocer este problema en absoluto y para obtener más respuestas a este respecto, se violará la correspondencia de solicitud-respuesta.


Incluso si todo lo que se logró al anular el método fue cerrar la conexión entre el proxy y el backend, entonces esto puede ser suficiente para un ataque. Puede lanzar solicitudes de servicio con tales solicitudes: las conexiones con backends se interrumpirán constantemente. No hay tantos, y la reapertura lleva tiempo, como resultado, puede lograr una disminución significativa en el rendimiento de la conexión de back-end del proxy y, por lo tanto, reducir el ancho de banda del servicio.

Reproducción automática de spam


Dije anteriormente que las solicitudes de la forma GET + X-HTTP-Method-Override: PATCH de clientes respetables son malas. Y esto es malo porque los métodos tienen dos propiedades: seguridad e idempotencia . Seguridad significa que el método no cambia el estado del servidor (solo lectura) y no nos interesa en el contexto de este artículo. La idempotencia del método asegura que la solicitud repetida tenga el mismo efecto que una solicitud única. Puede dibujar una analogía: (a = 5)- solicitud idempotente, y (a += 2) - no idempotente.

Esta propiedad es lo que nos interesa. Si la conexión entre el cliente y el servidor se rompe repentinamente, el cliente, sabiendo que el método es idempotente, puede reenviar automáticamente la solicitud. Los proxies se comportan de la misma manera. Las solicitudes no idempotentes no se repiten automáticamente porque no se sabe cómo afectan al servidor y qué recibirá el cliente al final. Creo que todos conocen las ventanas emergentes en el navegador: "¿Está seguro de que desea repetir la solicitud?"

Si enmascara un método no idempotente como idempotente, en caso de errores, no se descartará, sino que se redirigirá al servidor nuevamente. Incluso si el cliente considerará el método de solicitud real antes de volver a enviar la solicitud, esto no ayudará mucho, porque el servidor proxy no sabe sobre la anulación del método y repetirá dichas solicitudes.

Si un atacante puede forzar las desconexiones entre el servidor y los clientes, podrá hacer que el servidor ejecute repetidamente solicitudes no idempotentes y reduzca la confiabilidad y la previsibilidad de la aplicación. En la sección anterior, acabamos de encontrar una forma de causar interrupciones de conexión con el mismo método de anulación. Aunque debe recordarse que Internet es una red poco confiable, por definición, y la aplicación en sí misma está en peligro.

Para protegerse contra este ataque, debe usar solo métodos que no agreguen nuevas propiedades a la solicitud como transporte. POST es un buen candidato, porque por defecto no es seguro ni idempotente.

¿Ese antiguo HTTP / 1.1, como con HTTP / 2?


HTTP / 2 ha cambiado la forma en que las solicitudes se transportan entre nodos, pero no ha cambiado su significado léxico. Por lo tanto, en los ataques relacionados con el valor de la solicitud, HTTP / 2 se comporta igual. Pero los ataques de "transporte" no se reproducen, ya que ya se tienen en cuenta en la norma.

Los ataques en la memoria caché se reproducen de manera similar a HTTP / 1, y la protección es similar.

Los ataques de Message Queue Server no son aplicables a HTTP / 2. Los mensajes HTTP en él se dividen en marcos separados, con encabezados de marco separados que determinan explícitamente la longitud y el final del mensaje. Como si el atacante no cambiara el método y modificara los encabezados HTTP, esto no afectará el marco del mensaje. Robar la respuesta fallará.

Los ataques a la repetición de mensajes no idempotentes son aplicables incluso teniendo en cuenta el hecho de que en HTTP / 2 haymecanismo de notificación de la última solicitud procesada . En HTTP / 2, las solicitudes múltiples se multiplican en el mismo TCP y, por lo tanto, crean flujos . Cada hilo tiene su propio número. Si el servidor HTTP / 2 se desconecta, puede indicar el número de la última solicitud procesada en GOAWAY. Las solicitudes con un número más alto siempre son seguras para redirigir; las solicitudes con un número más bajo solo se redirigen si son idempotentes. Si una solicitud con un método anulado parece idempotente para un servidor proxy, entonces el proxy lo reenviará al servidor.

Cómo anular un método de forma segura


La respuesta corta es de ninguna manera. Es mejor no utilizar anulaciones de métodos. Y deshabilite completamente el soporte en el backend, si lo hay. Bloquee los métodos de anulación de clientes HTTP. Rechazar proxy / WAF, que corta los métodos "extra".

Si tiene que vivir de alguna manera con la redefinición del método, entonces para evitar suficientes ediciones en el back-end. Primero, es recomendable anular el método solo a través del componente de consulta del URI.

En segundo lugar, debería haber una lista blanca de la transformación de los métodos: cuáles son aceptables como "transporte" y cuáles son los resultantes. No debe haber funciones de transformación generalizadas cuando cualquier método puede ser anulado por cualquiera. El método de "transporte" no debe tener las propiedades de seguridad e idempotencia si el resultante no lo tiene. Deben prohibirse las transformaciones peligrosas, el mismo reemplazo GET -> HEAD.

¿Necesito parchear un proxy / WAF problemático?


Si el proxy implementa solo los métodos GET y POST, y bloquea los demás por una razón u otra, definitivamente sí. Puede optimizarlo principalmente para GET y POST, pero bloquear otros métodos es una mala idea. Lo que todavía crea un abismo de desconfianza en el producto: si las cosas básicas están bloqueadas, ¿qué esperar de la implementación de problemas más complejos?

Si le preocupa la seguridad de las aplicaciones web protegidas, puede valer la pena proteger las aplicaciones de las políticas de anulación de métodos inseguros. Por supuesto, en el caso general, sin conocer los detalles de la implementación de la aplicación web, es imposible proteger completamente la aplicación de las anulaciones incorrectas, pero puede cubrir parcialmente a los usuarios que simplemente no conocen el problema. Es necesario no solo para proteger contra el envenenamiento de su propio caché, sino también para habilitar o deshabilitar la anulación de cada aplicación protegida. Para hacer esto, realice un seguimiento de los encabezados de uso común.X-HTTP-Method, X-HTTP-Method-Override y X-Method-Override. El seguimiento de la redefinición en el componente de consulta del URI no tiene mucho sentido: el caché no envenena dicha solicitud, y la consulta puede ser muy larga y tener un formato completamente arbitrario.

?


Desarrolladores de seguridad, no limiten a los desarrolladores de aplicaciones a políticas de seguridad. Todavía encontrarán la forma de sortearlos, y cuanto más flexible sea el protocolo, más fácil será hacerlo. Es muy probable que no lo pateen y esperen hasta que haga que las restricciones sean más razonables, sino que simplemente las eludirán.

Si descubrió cómo implementar algo en el protocolo, pero esto anula o va en contra de uno de los conceptos clave del estándar, seguramente surgirán problemas de compatibilidad y seguridad. Y deben estar cubiertos al mismo tiempo que la decisión. Cada vez. Si cumplió con estos consejos y no vio advertencias de seguridad, no los duplique en Internet. Siempre sea crítico con la decisión y descubra qué podría salir mal .

En lugar de un epílogo


¿Qué problemas del servidor proxy encontraste? ¿Qué tenía que ser evitado y cómo?

All Articles