CORS - Misconfigurations & Bypass
Last updated
Last updated
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
El intercambio de recursos de origen cruzado (CORS) estándar permite a los servidores definir quién puede acceder a sus activos y qué métodos de solicitud HTTP están permitidos desde fuentes externas.
Una política de mismo origen exige que un servidor que solicita un recurso y el servidor que aloja el recurso compartan el mismo protocolo (por ejemplo, http://
), nombre de dominio (por ejemplo, internal-web.com
) y puerto (por ejemplo, 80). Bajo esta política, solo se permite el acceso a los recursos desde páginas web del mismo dominio y puerto.
La aplicación de la política de mismo origen en el contexto de http://normal-website.com/example/example.html
se ilustra de la siguiente manera:
http://normal-website.com/example/
Sí: Esquema, dominio y puerto idénticos
http://normal-website.com/example2/
Sí: Esquema, dominio y puerto idénticos
https://normal-website.com/example/
No: Esquema y puerto diferentes
http://en.normal-website.com/example/
No: Dominio diferente
http://www.normal-website.com/example/
No: Dominio diferente
http://normal-website.com:8080/example/
No: Puerto diferente*
*Internet Explorer ignora el número de puerto al hacer cumplir la política de mismo origen, permitiendo así este acceso.
Access-Control-Allow-Origin
Esta cabecera puede permitir múltiples orígenes, un valor null
o un comodín *
. Sin embargo, ningún navegador soporta múltiples orígenes, y el uso del comodín *
está sujeto a limitaciones. (El comodín debe usarse solo, y su uso junto con Access-Control-Allow-Credentials: true
no está permitido.)
Esta cabecera es emitida por un servidor en respuesta a una solicitud de recurso de dominio cruzado iniciada por un sitio web, con el navegador añadiendo automáticamente una cabecera Origin
.
Access-Control-Allow-Credentials
Por defecto, las solicitudes de origen cruzado se realizan sin credenciales como cookies o la cabecera de autorización. Sin embargo, un servidor de dominio cruzado puede permitir la lectura de la respuesta cuando se envían credenciales configurando la cabecera Access-Control-Allow-Credentials
a true
.
Si se establece en true
, el navegador transmitirá credenciales (cookies, cabeceras de autorización o certificados de cliente TLS).
Al iniciar una solicitud entre dominios bajo condiciones específicas, como el uso de un método HTTP no estándar (cualquier cosa que no sea HEAD, GET, POST), la introducción de nuevos encabezados, o el empleo de un valor especial para el encabezado Content-Type, puede ser necesaria una solicitud de pre-vuelo. Esta solicitud preliminar, que utiliza el método OPTIONS
, sirve para informar al servidor sobre las intenciones de la próxima solicitud de origen cruzado, incluidos los métodos HTTP y encabezados que se pretende utilizar.
El protocolo de Intercambio de Recursos de Origen Cruzado (CORS) exige esta verificación de pre-vuelo para determinar la viabilidad de la operación de origen cruzado solicitada, verificando los métodos y encabezados permitidos, así como la confiabilidad del origen. Para una comprensión detallada de qué condiciones eluden la necesidad de una solicitud de pre-vuelo, consulte la guía completa proporcionada por Mozilla Developer Network (MDN).
Es crucial notar que la ausencia de una solicitud de pre-vuelo no anula el requisito de que la respuesta lleve encabezados de autorización. Sin estos encabezados, el navegador se ve incapacitado para procesar la respuesta de la solicitud de origen cruzado.
Considere la siguiente ilustración de una solicitud de pre-vuelo destinada a emplear el método PUT
junto con un encabezado personalizado llamado Special-Request-Header
:
En respuesta, el servidor podría devolver encabezados que indican los métodos aceptados, el origen permitido y otros detalles de la política CORS, como se muestra a continuación:
Access-Control-Allow-Headers
: Este encabezado especifica qué encabezados se pueden usar durante la solicitud real. Es establecido por el servidor para indicar los encabezados permitidos en las solicitudes del cliente.
Access-Control-Expose-Headers
: A través de este encabezado, el servidor informa al cliente sobre qué encabezados pueden ser expuestos como parte de la respuesta además de los encabezados de respuesta simples.
Access-Control-Max-Age
: Este encabezado indica cuánto tiempo se pueden almacenar en caché los resultados de una solicitud de pre-vuelo. El servidor establece el tiempo máximo, en segundos, que la información devuelta por una solicitud de pre-vuelo puede ser reutilizada.
Access-Control-Request-Headers
: Utilizado en solicitudes de pre-vuelo, este encabezado es establecido por el cliente para informar al servidor sobre qué encabezados HTTP el cliente desea usar en la solicitud real.
Access-Control-Request-Method
: Este encabezado, también utilizado en solicitudes de pre-vuelo, es establecido por el cliente para indicar qué método HTTP se utilizará en la solicitud real.
Origin
: Este encabezado es establecido automáticamente por el navegador e indica el origen de la solicitud de origen cruzado. Es utilizado por el servidor para evaluar si la solicitud entrante debe ser permitida o denegada según la política de CORS.
Tenga en cuenta que generalmente (dependiendo del tipo de contenido y los encabezados establecidos) en una solicitud GET/POST no se envía una solicitud de pre-vuelo (la solicitud se envía directamente), pero si desea acceder a los encabezados/cuerpo de la respuesta, debe contener un encabezado Access-Control-Allow-Origin que lo permita. Por lo tanto, CORS no protege contra CSRF (pero puede ser útil).
Access-Control-Request-Local-Network
: Este encabezado se incluye en la solicitud del cliente para significar que la consulta está dirigida a un recurso de red local. Sirve como un marcador para informar al servidor que la solicitud se origina desde dentro de la red local.
Access-Control-Allow-Local-Network
: En respuesta, los servidores utilizan este encabezado para comunicar que el recurso solicitado está permitido para ser compartido con entidades fuera de la red local. Actúa como una luz verde para compartir recursos a través de diferentes límites de red, asegurando un acceso controlado mientras se mantienen los protocolos de seguridad.
Una respuesta válida que permita la solicitud de red local también necesita tener en la respuesta el encabezado Access-Controls-Allow-Local_network: true
:
Tenga en cuenta que la IP de linux 0.0.0.0 funciona para bypassear estos requisitos para acceder a localhost, ya que esa dirección IP no se considera "local".
También es posible bypassear los requisitos de la red local si utiliza la dirección IP pública de un endpoint local (como la IP pública del enrutador). Porque en varias ocasiones, incluso si se está accediendo a la IP pública, si es desde la red local, se otorgará acceso.
Tenga en cuenta que incluso si la siguiente configuración puede parecer super permisiva:
Esto no es permitido por los navegadores y, por lo tanto, las credenciales no se enviarán con la solicitud permitida por esto.
Se ha observado que la configuración de Access-Control-Allow-Credentials
a true
es un requisito previo para la mayoría de los ataques reales. Esta configuración permite que el navegador envíe credenciales y lea la respuesta, mejorando la efectividad del ataque. Sin esto, el beneficio de hacer que un navegador emita una solicitud en lugar de hacerlo uno mismo disminuye, ya que aprovechar las cookies de un usuario se vuelve inviable.
Existe una excepción donde la ubicación de la red de la víctima actúa como una forma de autenticación. Esto permite que el navegador de la víctima se use como un proxy, eludiendo la autenticación basada en IP para acceder a aplicaciones de intranet. Este método comparte similitudes en impacto con el DNS rebinding, pero es más simple de explotar.
Origin
en Access-Control-Allow-Origin
El escenario del mundo real donde el valor del encabezado Origin
se refleja en Access-Control-Allow-Origin
es teóricamente improbable debido a las restricciones sobre la combinación de estos encabezados. Sin embargo, los desarrolladores que buscan habilitar CORS para múltiples URL pueden generar dinámicamente el encabezado Access-Control-Allow-Origin
copiando el valor del encabezado Origin
. Este enfoque puede introducir vulnerabilidades, particularmente cuando un atacante emplea un dominio con un nombre diseñado para parecer legítimo, engañando así la lógica de validación.
null
El origen null
, especificado para situaciones como redirecciones o archivos HTML locales, ocupa una posición única. Algunas aplicaciones incluyen este origen en la lista blanca para facilitar el desarrollo local, permitiendo inadvertidamente que cualquier sitio web imite un origen null
a través de un iframe en un entorno aislado, eludiendo así las restricciones de CORS.
Al encontrarse con una lista blanca de dominios, es crucial probar oportunidades de bypass, como agregar el dominio del atacante a un dominio en la lista blanca o explotar vulnerabilidades de toma de subdominio. Además, las expresiones regulares utilizadas para la validación de dominios pueden pasar por alto matices en las convenciones de nomenclatura de dominios, presentando más oportunidades de bypass.
Los patrones de regex típicamente se concentran en caracteres alfanuméricos, punto (.) y guion (-), descuidando otras posibilidades. Por ejemplo, un nombre de dominio diseñado para incluir caracteres interpretados de manera diferente por los navegadores y patrones de regex puede eludir las verificaciones de seguridad. El manejo de caracteres de subrayado en subdominios por parte de Safari, Chrome y Firefox ilustra cómo tales discrepancias pueden ser explotadas para eludir la lógica de validación de dominios.
Para más información y configuraciones de esta verificación de bypass: https://www.corben.io/advanced-cors-techniques/ y https://medium.com/bugbountywriteup/think-outside-the-scope-advanced-cors-exploitation-techniques-dad019c68397
Los desarrolladores a menudo implementan mecanismos defensivos para protegerse contra la explotación de CORS al blanquear dominios que están permitidos para solicitar información. A pesar de estas precauciones, la seguridad del sistema no es infalible. La presencia de incluso un solo subdominio vulnerable dentro de los dominios en la lista blanca puede abrir la puerta a la explotación de CORS a través de otras vulnerabilidades, como XSS (Cross-Site Scripting).
Para ilustrar, considere el escenario donde un dominio, requester.com
, está en la lista blanca para acceder a recursos de otro dominio, provider.com
. La configuración del lado del servidor podría verse algo así:
En esta configuración, se permite el acceso a todos los subdominios de requester.com
. Sin embargo, si un subdominio, digamos sub.requester.com
, está comprometido con una vulnerabilidad XSS, un atacante puede aprovechar esta debilidad. Por ejemplo, un atacante con acceso a sub.requester.com
podría explotar la vulnerabilidad XSS para eludir las políticas de CORS y acceder maliciosamente a recursos en provider.com
.
La hoja de trucos para eludir la validación de URL de PortSwigger encontró que algunos navegadores admiten caracteres extraños dentro de los nombres de dominio.
Chrome y Firefox admiten guiones bajos _
que pueden eludir las expresiones regulares implementadas para validar el encabezado Origin
:
Safari es aún más indulgente al aceptar caracteres especiales en el nombre de dominio:
Es posible que al explotar el envenenamiento de caché del lado del servidor a través de la inyección de encabezados HTTP, se pueda inducir una vulnerabilidad de Cross-Site Scripting (XSS) almacenada. Este escenario se desarrolla cuando una aplicación no sanitiza el encabezado Origin
para caracteres ilegales, creando una vulnerabilidad particularmente para los usuarios de Internet Explorer y Edge. Estos navegadores tratan (0x0d) como un terminador de encabezado HTTP legítimo, lo que lleva a vulnerabilidades de inyección de encabezados HTTP.
Considera la siguiente solicitud donde se manipula el encabezado Origin
:
Internet Explorer y Edge interpretan la respuesta como:
Mientras que explotar directamente esta vulnerabilidad haciendo que un navegador web envíe un encabezado malformado no es factible, se puede generar manualmente una solicitud elaborada utilizando herramientas como Burp Suite. Este método podría llevar a que una caché del lado del servidor guarde la respuesta y, sin querer, la sirva a otros. La carga útil elaborada tiene como objetivo alterar el conjunto de caracteres de la página a UTF-7, una codificación de caracteres a menudo asociada con vulnerabilidades XSS debido a su capacidad para codificar caracteres de una manera que puede ser ejecutada como script en ciertos contextos.
Para más información sobre vulnerabilidades XSS almacenadas, consulte PortSwigger.
Nota: La explotación de vulnerabilidades de inyección de encabezados HTTP, particularmente a través de la contaminación de caché del lado del servidor, subraya la importancia crítica de validar y sanitizar toda entrada proporcionada por el usuario, incluidos los encabezados HTTP. Siempre emplee un modelo de seguridad robusto que incluya validación de entrada para prevenir tales vulnerabilidades.
En este escenario, se observa una instancia de una página web que refleja el contenido de un encabezado HTTP personalizado sin la codificación adecuada. Específicamente, la página web refleja de vuelta el contenido incluido en un encabezado X-User-id
, que podría incluir JavaScript malicioso, como se demuestra en el ejemplo donde el encabezado contiene una etiqueta de imagen SVG diseñada para ejecutar código JavaScript al cargarse.
Las políticas de Cross-Origin Resource Sharing (CORS) permiten el envío de encabezados personalizados. Sin embargo, sin que la respuesta sea renderizada directamente por el navegador debido a las restricciones de CORS, la utilidad de tal inyección podría parecer limitada. El punto crítico surge al considerar el comportamiento de la caché del navegador. Si el encabezado Vary: Origin
no está especificado, se vuelve posible que la respuesta maliciosa sea almacenada en caché por el navegador. Posteriormente, esta respuesta en caché podría ser renderizada directamente al navegar a la URL, eludiendo la necesidad de renderizado directo en la solicitud inicial. Este mecanismo mejora la fiabilidad del ataque al aprovechar la caché del lado del cliente.
Para ilustrar este ataque, se proporciona un ejemplo de JavaScript, diseñado para ser ejecutado en el entorno de una página web, como a través de un JSFiddle. Este script realiza una acción simple: envía una solicitud a una URL especificada con un encabezado personalizado que contiene el JavaScript malicioso. Al completar con éxito la solicitud, intenta navegar a la URL objetivo, potencialmente activando la ejecución del script inyectado si la respuesta ha sido almacenada en caché sin un manejo adecuado del encabezado Vary: Origin
.
Aquí hay un desglose resumido del JavaScript utilizado para ejecutar este ataque:
XSSI, también conocido como Cross-Site Script Inclusion, es un tipo de vulnerabilidad que aprovecha el hecho de que la Política de Mismo Origen (SOP) no se aplica al incluir recursos utilizando la etiqueta de script. Esto se debe a que los scripts necesitan poder ser incluidos desde diferentes dominios. Esta vulnerabilidad permite a un atacante acceder y leer cualquier contenido que se haya incluido utilizando la etiqueta de script.
Esta vulnerabilidad se vuelve particularmente significativa cuando se trata de JavaScript dinámico o JSONP (JSON con Padding), especialmente cuando se utilizan información de autoridad ambiental como cookies para la autenticación. Al solicitar un recurso de un host diferente, las cookies se incluyen, haciéndolas accesibles para el atacante.
Para comprender mejor y mitigar esta vulnerabilidad, puedes utilizar el plugin de BurpSuite disponible en https://github.com/kapytein/jsonp. Este plugin puede ayudar a identificar y abordar posibles vulnerabilidades XSSI en tus aplicaciones web.
Lee más sobre los diferentes tipos de XSSI y cómo explotarlos aquí.
Intenta agregar un callback
parameter en la solicitud. Quizás la página estaba preparada para enviar los datos como JSONP. En ese caso, la página devolverá los datos con Content-Type: application/javascript
, lo que eludirá la política de CORS.
Una forma de eludir la restricción Access-Control-Allow-Origin
es solicitando a una aplicación web que haga una solicitud en tu nombre y devuelva la respuesta. Sin embargo, en este escenario, las credenciales de la víctima final no se enviarán ya que la solicitud se realiza a un dominio diferente.
CORS-escape: Esta herramienta proporciona un proxy que reenvía tu solicitud junto con sus encabezados, mientras también falsifica el encabezado Origin para que coincida con el dominio solicitado. Esto elude efectivamente la política de CORS. Aquí hay un ejemplo de uso con XMLHttpRequest:
simple-cors-escape: Esta herramienta ofrece un enfoque alternativo para hacer proxy de solicitudes. En lugar de pasar tu solicitud tal cual, el servidor hace su propia solicitud con los parámetros especificados.
Puedes eludir las verificaciones de CORS como e.origin === window.origin
creando un iframe y desde él abriendo una nueva ventana. Más información en la siguiente página:
El rebinding DNS a través de TTL es una técnica utilizada para eludir ciertas medidas de seguridad manipulando registros DNS. Así es como funciona:
El atacante crea una página web y hace que la víctima acceda a ella.
El atacante luego cambia el DNS (IP) de su propio dominio para apuntar a la página web de la víctima.
El navegador de la víctima almacena en caché la respuesta DNS, que puede tener un valor de TTL (Tiempo de Vida) que indica cuánto tiempo se debe considerar válido el registro DNS.
Cuando expira el TTL, el navegador de la víctima realiza una nueva solicitud DNS, lo que permite al atacante ejecutar código JavaScript en la página de la víctima.
Al mantener el control sobre la IP de la víctima, el atacante puede recopilar información de la víctima sin enviar ninguna cookie al servidor de la víctima.
Es importante notar que los navegadores tienen mecanismos de caché que pueden prevenir el abuso inmediato de esta técnica, incluso con valores de TTL bajos.
El rebinding DNS puede ser útil para eludir verificaciones de IP explícitas realizadas por la víctima o para escenarios donde un usuario o bot permanece en la misma página durante un período prolongado, permitiendo que la caché expire.
Si necesitas una forma rápida de abusar del rebinding DNS, puedes usar servicios como https://lock.cmpxchg8b.com/rebinder.html.
Para ejecutar tu propio servidor de rebinding DNS, puedes utilizar herramientas como DNSrebinder (https://github.com/mogwailabs/DNSrebinder). Esto implica exponer tu puerto local 53/udp, crear un registro A que apunte a él (por ejemplo, ns.example.com), y crear un registro NS que apunte al subdominio A creado previamente (por ejemplo, ns.example.com). Cualquier subdominio del subdominio ns.example.com será resuelto por tu host.
También puedes explorar un servidor en funcionamiento públicamente en http://rebind.it/singularity.html para una mejor comprensión y experimentación.
El rebinding DNS a través de inundación de caché DNS es otra técnica utilizada para eludir el mecanismo de caché de los navegadores y forzar una segunda solicitud DNS. Así es como funciona:
Inicialmente, cuando la víctima realiza una solicitud DNS, se responde con la dirección IP del atacante.
Para eludir la defensa de caché, el atacante aprovecha un service worker. El service worker inunda la caché DNS, lo que efectivamente elimina el nombre del servidor del atacante almacenado en caché.
Cuando el navegador de la víctima realiza una segunda solicitud DNS, ahora se responde con la dirección IP 127.0.0.1, que normalmente se refiere al localhost.
Al inundar la caché DNS con el service worker, el atacante puede manipular el proceso de resolución DNS y forzar al navegador de la víctima a realizar una segunda solicitud, esta vez resolviendo a la dirección IP deseada por el atacante.
Otra forma de eludir la defensa de caché es utilizando múltiples direcciones IP para el mismo subdominio en el proveedor de DNS. Así es como funciona:
El atacante configura dos registros A (o un solo registro A con dos IPs) para el mismo subdominio en el proveedor de DNS.
Cuando un navegador verifica estos registros, recibe ambas direcciones IP.
Si el navegador decide usar primero la dirección IP del atacante, el atacante puede servir una carga útil que realice solicitudes HTTP al mismo dominio.
Sin embargo, una vez que el atacante obtiene la dirección IP de la víctima, deja de responder al navegador de la víctima.
El navegador de la víctima, al darse cuenta de que el dominio no responde, pasa a usar la segunda dirección IP dada.
Al acceder a la segunda dirección IP, el navegador elude la Política de Mismo Origen (SOP), permitiendo al atacante abusar de esto y recopilar y exfiltrar información.
Esta técnica aprovecha el comportamiento de los navegadores cuando se proporcionan múltiples direcciones IP para un dominio. Al controlar estratégicamente las respuestas y manipular la elección de la dirección IP del navegador, un atacante puede explotar la SOP y acceder a información de la víctima.
Ten en cuenta que para acceder a localhost deberías intentar rebind 127.0.0.1 en Windows y 0.0.0.0 en Linux. Proveedores como godaddy o cloudflare no me permitieron usar la IP 0.0.0.0, pero AWS route53 me permitió crear un registro A con 2 IPs siendo una de ellas "0.0.0.0"
Para más información puedes consultar https://unit42.paloaltonetworks.com/dns-rebinding/
Si no se permiten IPs internas, podrían haber olvidado prohibir 0.0.0.0 (funciona en Linux y Mac)
Si no se permiten IPs internas, responde con un CNAME a localhost (funciona en Linux y Mac)
Si no se permiten IPs internas como respuestas DNS, puedes responder CNAMEs a servicios internos como www.corporate.internal.
Puedes encontrar más información sobre las técnicas de bypass anteriores y cómo usar la siguiente herramienta en la charla Gerald Doussot - Estado de los Ataques de Rebinding DNS & Singularidad de Origen - Conferencia DEF CON 27.
Singularity of Origin
es una herramienta para realizar ataques de rebinding DNS. Incluye los componentes necesarios para volver a enlazar la dirección IP del nombre DNS del servidor de ataque a la dirección IP de la máquina objetivo y para servir cargas útiles de ataque para explotar software vulnerable en la máquina objetivo.
Usa TLS en servicios internos
Solicita autenticación para acceder a datos
Valida el encabezado Host
https://wicg.github.io/private-network-access/: Propuesta para siempre enviar una solicitud previa cuando los servidores públicos quieren acceder a servidores internos
Fuzz posibles configuraciones incorrectas en políticas de CORS
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)