Formas de eludir la política del mismo origen

150

La misma política de origen.

Quería hacer un wiki comunitario con respecto a las políticas HTML / JS del mismo origen para ayudar a cualquiera que busque este tema. Este es uno de los temas más buscados en SO y no hay un wiki consolidado para él, así que aquí voy :)

La misma política de origen evita que un documento o script cargado desde un origen obtenga o establezca propiedades de un documento desde otro origen. Esta política se remonta a Netscape Navigator 2.0.

¿Cuáles son algunas de sus formas favoritas de evitar las políticas del mismo origen?

Mantenga ejemplos detallados y preferiblemente también vincule sus fuentes.

David Titarenco
fuente
44
buena idea .. Sin embargo, debe poner sus ejemplos en respuesta (s); tal como está, hacen que la pregunta sea bastante voluminosa
Shog9
1
También debe agregar una lista de implicaciones de seguridad para cada enfoque. JSONP es altamente inseguro para los datos privados.
Erlend
¿Por qué el cierre? Esta pregunta (wiki) ha sido bastante útil durante los últimos 2 años. Además, muchas respuestas están respaldadas por referencias. Se agradecería una explicación ya que una not constructiveetiqueta parece completamente inútil. Votado para reabrir.
David Titarenco

Respuestas:

84

El document.domainmetodo

  • Tipo de método: iframe .

Tenga en cuenta que este es un método de iframe que establece el valor de document.domain en un sufijo del dominio actual. Si lo hace, el dominio más corto se usa para verificaciones de origen posteriores. Por ejemplo, suponga que una secuencia de comandos en el documento http://store.company.com/dir/other.htmlejecuta la siguiente instrucción:

document.domain = "company.com";

Después de que se ejecuta esa declaración, la página pasaría la verificación de origen con http://company.com/dir/page.html. Sin embargo, por el mismo razonamiento, company.com no podían establecer document.domain a othercompany.com.

Con este método, se le permitirá ejecutar JavaScript desde un iframe de un subdominio en una página del dominio principal. Este método no es adecuado para recursos entre dominios, ya que los navegadores como Firefox no le permitirán cambiarlo document.domaina un dominio completamente extraño.

Fuente: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

El método de intercambio de recursos de origen cruzado

  • Tipo de método: AJAX .

Cross-Origin Resource Sharing (CORS) es un borrador de trabajo del W3C que define cómo el navegador y el servidor deben comunicarse cuando acceden a las fuentes de todos los orígenes. La idea básica detrás de CORS es usar encabezados HTTP personalizados para permitir que tanto el navegador como el servidor sepan lo suficiente el uno del otro para determinar si la solicitud o la respuesta deben tener éxito o fallar.

Para una solicitud simple, una que usa GETo POSTsin encabezados personalizados y cuyo cuerpo es text/plain, la solicitud se envía con un encabezado adicional llamado Origin. El encabezado Origen contiene el origen (protocolo, nombre de dominio y puerto) de la página solicitante para que el servidor pueda determinar fácilmente si debe responder o no. Un Originencabezado de ejemplo podría verse así:

Origin: http://www.stackoverflow.com

Si el servidor decide que se debe permitir la solicitud, envía un Access-Control-Allow-Originencabezado que repite el mismo origen que se envió o *si es un recurso público. Por ejemplo:

Access-Control-Allow-Origin: http://www.stackoverflow.com

Si falta este encabezado o los orígenes no coinciden, el navegador rechaza la solicitud. Si todo está bien, el navegador procesa la solicitud. Tenga en cuenta que ni las solicitudes ni las respuestas incluyen información de cookies.

El equipo de Mozilla sugiere en su publicación sobre CORS que debe verificar la existencia de la withCredentials propiedad para determinar si el navegador admite CORS a través de XHR. Luego puede acoplar la existencia del XDomainRequestobjeto para cubrir todos los navegadores:

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
    request.onload = function() {
        // ...
    };
    request.onreadystatechange = handler;
    request.send();
}

Tenga en cuenta que para que el método CORS funcione, debe tener acceso a cualquier tipo de mecánica de encabezado de servidor y no puede simplemente acceder a ningún recurso de terceros.

Fuente: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

El window.postMessagemetodo

  • Tipo de método: iframe .

window.postMessage, cuando se llama, hace MessageEventque se envíe un a en la ventana de destino cuando se completa cualquier secuencia de comandos pendiente que se debe ejecutar (por ejemplo, controladores de eventos restantes si window.postMessagese llama desde un controlador de eventos, tiempos de espera pendientes previamente establecidos, etc.). El MessageEventtiene el tipo de mensaje, una datapropiedad que se establece en el valor de cadena del primer argumento proporcionado a window.postMessage, una originpropiedad que corresponde al origen del documento principal en la ventana llamando window.postMessageen el momento window.postMessagefue llamado, y una sourcepropiedad que es la ventana de que window.postMessagese llama

Para usar window.postMessage, se debe adjuntar un detector de eventos:

    // Internet Explorer
    window.attachEvent('onmessage',receiveMessage);

    // Opera/Mozilla/Webkit
    window.addEventListener("message", receiveMessage, false);

Y una receiveMessagefunción debe ser declarada:

function receiveMessage(event)
{
    // do something with event.data;
}

El iframe fuera del sitio también debe enviar eventos correctamente a través de postMessage:

<script>window.parent.postMessage('foo','*')</script>

Cualquier ventana puede acceder a este método en cualquier otra ventana, en cualquier momento, independientemente de la ubicación del documento en la ventana, para enviarle un mensaje. En consecuencia, cualquier detector de eventos utilizado para recibir mensajes primero debe verificar la identidad del remitente del mensaje, utilizando el origen y posiblemente las propiedades de origen. Esto no se puede subestimar: si no se verifican las propiedades originy posiblemente se sourcehabilitan los ataques de secuencias de comandos entre sitios.

Fuente: https://developer.mozilla.org/en/DOM/window.postMessage

David Titarenco
fuente
Espero que no sea demasiado tarde para obtener una respuesta: por la única pregunta, ¿es localhost SIEMPRE una excepción? ¿No está siempre permitido? ¿Debo dejar de probar a través de mi host local?
Ayyash
1
No estoy seguro de por qué, pero cuando configuro: en Access-Control-Allow-Origin: http://www.stackoverflow.com/lugar de: Access-Control-Allow-Origin: http://www.stackoverflow.com(barra al final de la URL), no funciona en Safari y FF, pero funciona en Chrome. Por supuesto, sin barra oblicua funciona bien en todos los navegadores.
mtfk
1
Podría valer la pena hacerle saber a la gente que el postMessagemétodo solo funciona para los navegadores que lo admiten, ya que es una adición de HTML5. Este complemento intenta dar cuenta de eso. Solo lo menciono porque estoy aprendiendo esto de la manera difícil.
IronicMuffin
41

El método de proxy inverso

  • Tipo de método: Ajax

La configuración de un proxy inverso simple en el servidor permitirá que el navegador use rutas relativas para las solicitudes de Ajax, mientras que el servidor actuaría como un proxy para cualquier ubicación remota.

Si usa mod_proxy en Apache, la directiva de configuración fundamental para configurar un proxy inverso es ProxyPass. Por lo general, se usa de la siguiente manera:

ProxyPass     /ajax/     http://other-domain.com/ajax/

En este caso, el navegador podrá solicitar /ajax/web_service.xmlcomo una URL relativa, pero el servidor lo servirá actuando como un proxy para http://other-domain.com/ajax/web_service.xml.

Una característica interesante de este método es que el proxy inverso puede distribuir fácilmente las solicitudes hacia múltiples back-end, actuando así como un equilibrador de carga .

Daniel Vassallo
fuente
17

Yo uso JSONP.

Básicamente, agregas

<script src="http://..../someData.js?callback=some_func"/>

en tu pagina.

Se debe llamar a some_func () para que se le notifique que los datos están en.

Nicolas Viennot
fuente
77
JSONP tiene dos problemas: a) Está agregando una etiqueta de script al dominio de destino. Pueden enviar cualquier cosa, incluso JavaScript normal (ataque XSS). Por lo tanto, realmente debe confiar en que no harán cosas malas ni serán pirateados b) Cualquier otra página web puede agregar la misma etiqueta de script y robar los datos, por lo que nunca use JSONP para datos privados.
Erlend
1
@Erlend: cualquier información que se publique en la web puede ser recuperada por cualquier persona (a menos que se requiera una autenticación adecuada). El formato exacto de cómo se presenta esa información no lo hace mejor o peor, ni siquiera si se trata de JSONP.
T-Bull
2
@ T-Bull: El problema es que la autenticación adecuada es imposible con JSONP. Un usuario inicia sesión en el sitio A y luego va al sitio B, que carga datos de A usando una etiqueta de script JSONP. Como está bien y bien. Luego, se engaña al usuario para que visite el sitio malvado C, que también usa una etiqueta de script JSONP para cargar datos de A. Entonces, debido a que el usuario está autenticado con A, el propietario de C ahora puede robar los datos de los usuarios de A. Y eso incluso si el usuario usó la autenticación de dos factores para autenticarse con A. El problema es que JSONP es altamente inseguro. Y JSONP no es presentación. Es una transferencia de datos insegura.
Erlend
1
JSONP solo es compatible con HTTP GET.
opiato
¿Qué archivo .js representa esto? -> "http: //..../someData.js.... Estoy tratando de leer el dom desde otro sitio del lado del cliente, y necesito eludir la política del mismo origen .
CS_2013
13

AnyOrigin no funcionó bien con algunos sitios https, por lo que acabo de escribir una alternativa de código abierto llamada whateverorigin.org que parece funcionar bien con https.

Código en github .

ripper234
fuente
@DavidTitarenco: me volvió loco tratar de entender algunas de las cosas que están sucediendo en el vientre de anyorigin. Afortunadamente, encontré una publicación en el blog que me ayudó, y ahora el siguiente chico tendrá un sitio de prueba en funcionamiento si alguna vez lo necesita.
ripper234
@neoascetic: se corrigió el uso ... la URL debe codificarse ahora.
ripper234
12

La forma más reciente de superar la política del mismo origen que he encontrado es http://anyorigin.com/

El sitio está hecho para que solo le des cualquier URL y genera un código javascript / jquery que te permite obtener el html / data, independientemente de su origen. En otras palabras, convierte cualquier url o página web en una solicitud JSONP.

Lo he encontrado bastante útil :)

Aquí hay un ejemplo de código JavaScript de anyorigin:

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});
revs rk1s
fuente
Aunque me dio algunos problemas con los sitios https, consulte mi alternativa de código abierto a continuación: stackoverflow.com/questions/3076414/…
ripper234
13
Lo que significa que: a) anyorigin podrá leer todos sus datos transferidos a través de tem b) anyorigin puede XSS su sitio, leer todos sus datos en su sitio y entregar malware a sus usuarios (¿qué sucede si se piratea anyorigin?)
Erlend
@Erlend: bifurque Cualquiera que sea su origen y guárdelo en su propio servidor. El código es trivial, por lo que puede revisarlo para asegurarse de que no haya vulnerabilidades ocultas allí.
ripper234
3

El JSONP viene a la mente:

JSONP o "JSON con relleno" es un complemento del formato de datos JSON base, un patrón de uso que permite que una página solicite y use JSON de manera más significativa desde un servidor que no sea el servidor primario. JSONP es una alternativa a un método más reciente llamado Intercambio de recursos de origen cruzado.

Sarfraz
fuente
Vea mi comentario a JSONP arriba. No es una buena opción para datos privados.
Erlend
1

Personalmente, window.postMessagees la forma más confiable que he encontrado para los navegadores modernos. Tienes que hacer un poco más de trabajo para asegurarte de no dejarte abierto a ataques XSS, pero es una compensación razonable.

También hay varios complementos para los populares kits de herramientas de Javascript window.postMessageque ofrecen una funcionalidad similar a los navegadores más antiguos que utilizan los otros métodos mencionados anteriormente.

Justin Niessner
fuente
1

Bueno, usé curl en PHP para sortear esto. Tengo un servicio web ejecutándose en el puerto 82.

<?php

$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;

?>

Aquí está el javascript que hace la llamada al archivo PHP

function getdata(obj1, obj2) {

    var xmlhttp;

    if (window.XMLHttpRequest)
            xmlhttp=new XMLHttpRequest();
    else
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
                document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
    }
    xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
    xmlhttp.send();
}

Mi HTML se ejecuta en WAMP en el puerto 80. Así que ahí vamos, se ha eludido la misma política de origen :-)

harihb
fuente
1

Estas son algunas soluciones y explicaciones de la política del mismo origen: Blog de Thiru : solución alternativa de la misma política
del navegador

usuario1094140
fuente