Política Same-origin

La política same-origin (mismo-origen) restringe cómo un documento o script cargado desde un origen puede interactuar con un recurso de otro origen. Es un mecanismo de seguridad crítico para aislar documentos potencialmente maliciosos.

Definición de origen

Dos páginas tienen el mismo origen si el protocolo, puerto (si es especificado) y anfitrión son los mismos para ambas páginas. Verá esto a veces referido como la "tupla esquema/anfitrión/puerto" (donde una "tupla" es un conjunto de componentes que juntos forman un todo).

La siguiente tabla muestra ejemplos de comparaciones de origenes para la URL http://store.company.com/dir/page.html:

URL Resultado Razón
http://store.company.com/dir2/other.html Mismo origen Solo la ruta difiere
http://store.company.com/dir/inner/another.html Mismo origen Solo la ruta difiere
https://store.company.com/secure.html Fallo Diferente protocolo
http://store.company.com:81/dir/etc.html Fallo Diferente puerto
http://news.company.com/dir/other.html Fallo Diferente host

Ver también definición de origen para file: URLs, puesto que su comparación es más complicada.

Orígenes heredados

Los scripts ejecutados desde páginas con una URL about:blank o javascript: heredan el origen del documento que contiene esa URL, puesto que esos tipos de URLs no contienen información sobre un servidor de origen.

Nota: Por ejemplo, about:blank a menudo se usa como URL de nuevas ventanas popup en las que el script padre escribe contenido (por ejemplo mediante el mecanismo Window.open()). Si este popup además contiene JavaScript, ese escript heredará el mismo origen que el script que lo ha creado.

Advertencia: data: URLs obtienen un nuevo, vacío, contexto de seguridad.

Excepciones en Internet Explorer

Internet Explorer tiene dos excepciones mayores en lo que se refiere a la política same-origin

Estas excepciones no son estándar y no están soportadas en otro navegador pero son útiles cuando se desarrolla una app para Windows RT (o) basada en IE.

Cambiando el origen

Una página puede cambiar su propio origen con algunas limitaciones. Un script puede asignar el valor de document.domain al dominio actual o a un superdominio del dominio actual. Si se asigna a un superdominio del dominio actual, el dominio más corto es usado para las posteriores comprobaciones de origen. Por ejemplo, sea un script en http://store.company.com/dir/other.html que ejecuta lo siguiente:

document.domain = "company.com";

Tras su ejecución, la página puede pasar la comprobación de origen con http://company.com/dir/page.html (asumiendo que http://company.com/dir/page.html asigna su document.domain a "company.com" para indicar que desea hacerlo - ver document.domain para más información). Sin embargo, company.com no podría asignar document.domain a othercompany.com ya que no es un superdominio de company.com.

El número de puerto es guardado de forma separada por el navegador. Cualquier llamada al setter, incluyendo document.domain = document.domain causa que el número del puerto sea sobrescrito con null. Por lo tanto no se puede hacer que company.com:8080 hable con company.com solo asignando document.domain = "company.com" en el primero. Tiene que ser asignado en ambos para que los números de puerto sean null.

Nota: Cuando se use document.domain para permitir a un subdominio acceder a su padre de forma segura, necesitas asignar document.domain al mismo valor tanto en el padre como en el subdominio. Esto es necesario incluso si solo se asigna el dominio padre a su valor original. Un fallo al hacer esto puede resultar en errores de permisos.

Acceso de red de origen cruzado

La política de mismo origen controla las interacciones entre dos orígenes diferentes, 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. Algunas peticiones HTTP raramente usadas requieren preflight.
  • La integración Cross-origin (embedding) normalmente se permite. Los ejemplos se listan debajo.
  • Las lecturas Cross-origin habitualmente no se permiten, pero el acceso de lectura es a menudo filtrado mediante integración. Por ejemplo, puedes leer el ancho y el alto de una imagen integrada, las acciones de un script integrado, o la disponibilidad de un recurso integrado.

Aquí hay algunos ejemplos de recursos que pueden ser orígen cruzado incrustado:

  • JavaScript con <script src="..."></script>. Los mensajes de error para errores de sintaxis están solo disponibles para scripts de mismo origen.
  • CSS con <link rel="stylesheet" href="...">. Debido a las reglas de sintaxis relajadas de CSS, un CSS de origen cruzado requiere de una cabecera Content-Type correcta. Las restricciones varían según el navegador: IE, Firefox, Chrome, Safari (bajar hasta CVE-2010-0051) y Opera.
  • Imágeness con <img>. Los formatos de imagen soportados incluyen PNG, JPEG, GIF, BMP, SVG, ...
  • Archivos multimedia con <video> y <audio>.
  • Plug-ins con <object>, <embed> y <applet>.
  • Fuentes con @font-face. Algunos buscadores permiten fuentes de orígen cruzado, otros requieren fuentes de mismo orígen.
  • Cualquiera con <frame> and <iframe>. Un sitio puede usar la cabecera X-Frame-Options para prevenir este tipo de interacción de orígen cruzado.

Cómo permitir el acceso de origen cruzado

Usa CORS para permitir el acceso de origen cruzado.

Cómo bloquear el acceso de origen cruzado

  • Para prevenir escrituras de orígen cruzado, comprobar un token imposible de adivinar en la petición, conocido como token Cross-Site Request Forgery (CSRF). Debes prevenir lecturas de orígen cruzado de páginas que conozcan este token.
  • Para prevenir lecturas de origen cruzado de un recurso, asegurar que no es incrustable. Frecuentemente es necesario prevenir incrustaciones debido a que al incrustar un recurso siempre se filtra alguna información sobre él.
  • Para prevenir incrustaciones de origen cruzado, asegurar que tu recurso no puede ser interpretado como uno de los formatos incrustables de arriba. El navegador no respeta el Content-Type en muchos casos. Por ejemplo, si señalas una etiqueta <script> en un documento HTML, el navegador tratará de interpretar el HTML como JavaScript. Cuando tu recurso no es un punto de entrada a tu sitio, puedes usar también un token CSRF para prevenir el incrustamiento.

Acceso script API de Origen Cruzado

Las APIs de JavaScript APIs tales como iframe.contentWindow, window.parent, window.open y window.opener permiten a los documentos referenciarse directamente entre ellos. Cuando dos documentos no tienen el mismo origen, estas referencias proveen un acceso muy limitado a los objetos Window y Location, como se describe en las siguientes dos secciones.

Para una mayor comunicación entre documentos de origenes diferentes, usar window.postMessage.

Window

Especificación: http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#security-window.

Los siguientes accesos de origen-cruzado a las propiedades de Window están permitidos:

Métodos
window.blur
window.close
window.focus
window.postMessage
Atributos
window.closed Solo lectura.
window.frames Solo lectura.
window.length Read only.
window.location Solo lectura.
window.opener Solo lectura.
window.parent Solo lectura.
window.self Solo lectura.
window.top Solo lectura.
window.window Solo lectura.

Algunos navegadores permiten el acceso a más propiedades de las que permite la especificación.

Location

Especificación: http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#security-location.

Los siguientes accesos de origen cruzado a las propiedades de Location están permitidos:

Métodos
location.replace
Atributos
URLUtils.href Solo escritura.

Algunos navegadores permiten el acceso a más propiedades de las que permite la especificación.

Acceso de almacenamiento de datos de origen cruzado

El acceso a datos almacenados en el navegador tales como localStorage y IndexedDB 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.

Las cookies usan una definición separada de orígenes. Una página puede asignar una cookie para su propio dominio o cualquier dominio padre, siempre que el dominio padre no sea un sufijo público. Firefox y Chrome usan la Lista de Sufijos Públicos para determinar si un dominio es un sufijo público. Internet Explorer usa su propio método interno para determinar si un dominio es un sufijo públicio. El navegador hará disponible una cookie para el dominio dado incluyendo cualquier subdominio, no importa qué protocolo (HTTP/HTTPS) o puerto sea usado. Cuando asignas una cookie, puedes limitar su disponibilidad usando los flags Domain, Path, Secure y Http-Only. Cuando lees una cookie, no puedes ver desde dónde fue asignada. Incluso si sólo usas conexiones HTTPS, cualquier cookie que veas puede haber sido asignada usando una conexión insegura.

Ver también

Información de Documento Original

  • Autor(es): Jesse Ruderman