Same-Origin Policy
Web Security Fundamentals
Introducción
Este post tiene como objetivo explicar que es la Same-Origin Policy, como funciona y porque es tan importante saber de ella a la hora de auditar un sitio web.
¿Que es un origen?
Para entender que es un origen, primero tenemos que ver una URL tradicional, en donde podremos destacar las siguientes partes:
- Scheme: El protocolo que utiliza (HTTP o HTTPS)
- Domain: Dominio al que pertenece la URL
- Port: El puerto (El cual normalmente es 80 o 443)
El origen es determinado por estas tres partes. Debido a esto, cuando miramos dos URL podremos determinar si tienen el mismo origen en caso de que el Scheme, Domain y Port sean iguales.
Same-Origin Policy (SOP)
Fundamentalmente, la Same-Origin Policy restringe cómo un documento o un script cargado desde un origen evil.com
puede interactuar con un recurso de otro origen bank.com
. Ahora bien, porque esto es importante? Debido a que de no existir esta política, un sitio web podría acceder a datos de otros sitios webs ya que nos permite aislar los sitios uno del otro. El objetivo principal de la Same-Origin Policy es mantener la información sensible segura evitando lecturas no autorizadas.
Veamos su funcionamiento más detenidamente…
Cuando nosotros abrimos una página sitioA.com
en un navegador, en la pestaña se crea un nuevo “contexto” en el cual se encuentra el DOM del sitio y dentro de este contexto se correran los scripts del sitio sitioA.com
. Cada ventana o pestaña, se encuentra aislada de las otras debido a que cada una se encuentra en su propio “contexto”, pero si ambas pestañas o ventanas cuentan con el mismo origen, podrán acceder a sus datos entre sí.
Al abrir una nueva pestaña sitioB.com
, esta vuelve a crear un nuevo “contexto” separado del sitio anterior. Siguiendo el ejemplo, puede el Sitio A acceder al DOM del Sitio B?
La respuesta es NO! El sitio no va a poder acceder debido a la SOP, pero quien permite o deniega que el sitioA.com
pueda acceder al DOM del sitioB.com
? El encargado de permitir o denegar el acceso es el navegador. El navegador debe implementar la SOP para proteger que un sitio (Por ej. Un sitio malicioso) acceda a los datos del otro sitio. Un dato muy importante es que si bien el encagado es el navegador, el servidor web puede influir sobre esta protección.
Reglas de SOP
La Same-Orgin Policy controla las interacciones entre dos orígenes diferentes (Cross-origin), como cuando se usa XMLHttpRequest
o un elemento <img>
. Estas interacciones habitualmente se ubican en tres categorías:
- Las escrituras Cross-origin normalmente se permiten. Como ejemplo tenemos los enlaces, redirecciones y envíos de formulario.
- La integración Cross-origin (embedding) normalmente se permite.
- Las lecturas Cross-origin habitualmente no se permiten, pero el acceso de lectura es a menudo filtrado mediante integración.
Aplicación de la SOP en distintos escenarios
Como ya vimos anteriormente, la SOP nos restringe cómo un documento o un script cargado desde un origen puede interactuar con un recurso de otro origen. Hasta ahora solo vimos un escenario posible en el cual un sitio sitioA.com
intenta acceder a los recursos de otro sitio sitioB.com
dentro del navegador.
Ahora, agregaremos otro escenario más, en el cual un sitio sitioA.com
realiza una solicitud otro sitio sitioB.com
para acceder a sus recursos. Siguiendo el ejemplo, sitioA.com
podrá realizar la solicitud a sitioB.com
pero no podrá obtener la respuesta.
Interacción Cross-Origin escritura
Las interacciones Cross-Origin de escritura más comúnes son la utilización de enlaces, las redirecciones y los envíos de formularios. En este caso, veremos un ejemplo de como funciona una interacción Cross-Origin con envíos de formularios por POST y en los links.
Ejemplo de SOP en Forms
Los formularios pueden hacer una solicitud POST a otros sitios, al enviarse, la respuesta cargará en un nuevo contexto (Debido a esto, el sitio original será remplazado con el sitio accedido). Por lo cual nuevamente un formulario podrá realizar una solicitud POST a cualquier sitio, pero no puede leer la respuesta.
Código de ejemplo
<form action="http://siteb.com/" method="POST">
Diagrama
Sin embargo, que previene que un sitio malicioso pueda enviar los datos de un formulario a otro sitio y este sitio realice determinada acción (Por Ej. Que un sitio evil.com
tenga un formulario que al enviarse se envíe a bank.com
y realice una transferencia)? En este caso, estaríamos frente a una vulnerabilidad Cross-Site Request Forgery (CSRF) y la manera de prevenir que esto ocurra sería utilizando tokens Anti-CSRF.
En resumen, SOP evita que el sitio evil.com
pueda obtener la respuesta de bank.com
pero no que se realice la solicitud que permite que se haga la transferencia, para evitar eso debemos usar tokens Anti-CSRF.
Ejemplo de SOP en XMLHttpRequest
Al igual que con los formularios, podremos hacer solicitudes a otros sitios pero no podremos leer la respuesta.
Código de ejemplo
<script>
var req = new XMLHttpRequest();
req.open(“GET”, “https://sitioa.com", false);
req.send();
</script>
Diagrama
Ejemplo de SOP en anchors
Los sitios pueden crear un links a otros sitios, al hacer click accederemos al otro sitio el cual será cargado en nuestro navegador en un nuevo contexto (Debido a esto, el sitio original será remplazado con el sitio accedido). Cualquier sitio puede crear un link, pero no puede leer la respuesta.
Código de ejemplo
<a href="http://siteb.com/>
Diagrama
Interacción Cross-Origin integración (Embedding)
Las interacciones Cross-Origin de integración más comunes son la integración de Scripts, archivos CSS, imágenes y otros archivos multimedia. A continuación, veremos ejemplos de como funciona una integración Cross-Origin.
Ejemplo de SOP en Frames o IFrames
Si nosotros embebemos un sitio sitioa.com
en nuestro sitio sitioprincipal.com
podremos leer los datos del contexto de este sitio sitioa.com
? La respuesta es no! No podremos acceder a este sitio, a no ser que se enbeba un sitio con el mismo origen.
Diagrama
Es importante aclarar, que también podemos evitar el cross-origin embedding (Es decir, que el sitioa.com
se pueda embeber en sitioprincipal.com
) si utilizamos el header X-Frame-Options
.
Ejemplo de SOP en Imágenes y Archivos Multimedia
Cualquier sitio puede mostrar imágenes de cualquier otro sitio, sin embargo, los sitios no pueden leer datos de la imagen de otros sitios. Esto aplica también a otros archivos multimedia como videos y audios.
Código de ejemplo
<img src="http://siteb.com/pic.jpg" />
Diagrama
Ejemplo de SOP en Archivos CSS
Cualquier sitio puede incluir CSS de cualquier otro sitio, sin embargo, los sitios no pueden leer datos del CSS de otros sitios.
Código de ejemplo
<link rel="stylesheet" type="text/css" href="http://siteb.com/site.css" />
Diagrama
Ejemplo de SOP en Archivos JS
Cualquier sitio puede incluir un archivo Javascript de cualquier otro sitio, sin embargo, Javascript corre en su sitio original.
Código de ejemplo
<script src="http://siteb.com/ga.js" />
Diagrama
SOP y WebStorage
¿Como se aplica la SOP al Web Storage?
El acceso a datos almacenados en el navegador tales como el localStorage y el sessionStorage son separados por origen. Cada origen obtiene su propio almacenamiento separado, y JavaScript en un origen no puede leer desde o escribir al almacenamiento perteneciente a otro origen.
El localStorage comparte su contenido entre ventanas o pestañas con el mismo origen y su contenido sigue persistiendo en caso de que la ventana o pestaña se cierre.
El sessionStorage no se comparte su contenido entre ventanas y pestañas y es eliminado al cerrar la ventana o pestaña.
CORS
Luego de entender que es y como funciona la Same-Origin Policy, podemos empezar a hablar de CORS (Cross-Origin Resourse Sharing). CORS es un mecanismo que utiliza cabeceras HTTP adicionales para permitir que se pueda acceder a recursos seleccionados desde un servidor, en un origen distinto al que pertenece.
Explicado de otra manera, sin CORS ocurriría lo siguiente:
En resumen, CORS nos permite flexibilizar la SOP y permitir que ciertos dominios. En el siguiente diagrama podemos ver como se utiliza CORS para que el Sitio A, pueda leer la respuesta del Sitio B.
Veamos a continuación como se representaría este escenario en donde se aplicaría CORS:
El Sitio A ejecutaría el siguiente código para realizar la solicitud al Sitio B:
<script>
var req = new XMLHttpRequest();
req. open(“GET”, “https://sitiob.com", false);
req.send();
</script>
Normalmente, el Sitio A no podría leer la respuesta, pero debido a que el Sitio B implementa CORS, el Sitio A podrá leer la respuesta. A continuación, se muestra el header que devuelve el Sitio B indicando que el Sitio A puede leer la respuesta.
Access-Control-Allow-Origin: https://sitioa.com
Es importante aclarar que, si bien no trataremos lo trataremos con profundidad en este post, CORS cuenta con muchas mas funcionalidades que nos permiten determinar, por ejemplo, si la solicitud puede ser envíada con credenciales.
Conclusiones
Como conclusión final podemos determinar que es fundamental conocer la SOP y CORS a la hora de realizar un Web Pentest, dado que en caso de que CORS se encuentre mal configurado, pueden existir distintas vulnerabilidades en el sistema.
También es muy importante entender que la Same-Origin Policy no evita ataques del tipo Cross-Site Request Forgery y que estos deben ser evitados utilizando tokens Anti-CSRF.
Referencias
Referencia Principal
Otras Referencias
https://developer.mozilla.org/es/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/es/docs/Web/HTTP/CORS
https://securing-the-stack.teachable.com/courses/same-origin-policy/lectures/4970772
https://www.ionos.es/digitalguide/paginas-web/desarrollo-web/cross-origin-resource-sharing/
https://www.youtube.com/watch?v=KaEj_qZgiKY
https://www.youtube.com/watch?v=i0wxon609f8