同一生成元ポリシーを回避する方法


150

同じオリジンポリシー

HTML / JSの同一生成元ポリシーに関するコミュニティーWikiを作成して、このトピックを検索している人を助けたいと思っています。これは、SOで最も検索されているトピックの1つであり、統合されたWikiがないため、ここに移動します:)

同じ生成元ポリシーは、ある生成元からロードされたドキュメントまたはスクリプトが別の生成元からドキュメントのプロパティを取得または設定することを防ぎます。このポリシーは、Netscape Navigator 2.0までさかのぼります。

同じ生成元のポリシーを回避するためのお気に入りの方法は何ですか?

例を冗長に保ち、できればソースもリンクしてください。


4
いいアイデアです。あなたの例を答えに入れるべきです。
現状

1
また、各アプローチのセキュリティへの影響のリストを追加する必要があります。JSONPはプライベートデータに対して非常に安全ではありません。
Erlend

なぜクローズ?この(wiki)の質問は、過去2年間非常に役に立ちました。さらに、多くの回答参照によってサポートされています。not constructiveタグはまったくとんでもないように見えるので、説明はありがたいです。再開に投票しました。
David Titarenco、2012

回答:


84

document.domain方法

  • メソッドタイプ:iframe

これは、document.domainの値を現在のドメインのサフィックスに設定するiframeメソッドであることに注意してください。その場合、後続のオリジンチェックに短いドメインが使用されます。たとえば、ドキュメントのスクリプトがhttp://store.company.com/dir/other.html次のステートメントを実行するとします。

document.domain = "company.com";

そのステートメントが実行された後、ページはによるオリジンチェックに合格しhttp://company.com/dir/page.htmlます。ただし、同じ理由で、company.comはに設定できませんでしdocument.domainothercompany.com

この方法では、メインドメインをソースとするページのサブドメインをソースとするiframeからJavaScriptを除外できます。Firefoxなどのブラウザではdocument.domainを完全にエイリアンドメインに変更できないため、この方法はクロスドメインリソースには適していません。

ソース:https : //developer.mozilla.org/en/Same_origin_policy_for_JavaScript

Cross-Origin Resource Sharingメソッド

  • メソッドタイプ:AJAX

クロスオリジンリソースシェアリング(CORS)は、W3Cワーキングドラフトであり、オリジン全体でソースにアクセスするときにブラウザとサーバーが通信する方法を定義しています。CORSの背後にある基本的な考え方は、カスタムHTTPヘッダーを使用して、ブラウザーとサーバーの両方が互いについて十分に認識し、要求または応答が成功するか失敗するかを判断できるようにすることです。

シンプルなリクエストの場合、カスタムヘッダーのいずれGETPOSTを使用するか、または使用せず、本文がtext/plainであるリクエストは、という追加のヘッダーとともに送信されOriginます。Originヘッダーには、要求元ページの起点(プロトコル、ドメイン名、およびポート)が含まれているため、サーバーは応答を提供する必要があるかどうかを簡単に判断できます。Originヘッダーの例は次のようになります。

Origin: http://www.stackoverflow.com

サーバーは、リクエストを許可する必要があると判断した場合、送信Access-Control-Allow-Originされたのと同じオリジンをエコーバックするヘッダーを送信するか*、それがパブリックリソースであるかどうかを確認します。例えば:

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

このヘッダーがない場合、またはオリジンが一致しない場合、ブラウザはリクエストを許可しません。すべてが順調であれば、ブラウザがリクエストを処理します。リクエストにもレスポンスにもCookie情報が含まれていないことに注意してください。

Mozillaチームは、CORSに関する投稿で、withCredentials プロパティの存在を確認して、ブラウザーがXHRを介してCORSをサポートしているかどうかを判断することを推奨しいます。次に、XDomainRequestオブジェクトの存在と組み合わせて、すべてのブラウザーをカバーできます。

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();
}

CORSメソッドが機能するためには、任意のタイプのサーバーヘッダーメカニズムにアクセスする必要があり、サードパーティのリソースに単純にアクセスすることはできません。

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

window.postMessage方法

  • メソッドタイプ:iframe

window.postMessageを呼び出すと、MessageEvent実行する必要のある保留中のスクリプトが完了すると、ターゲットウィンドウでがディスパッチされます(たとえばwindow.postMessage、イベントハンドラーから呼び出された場合の残りのイベントハンドラー、以前に設定された保留中のタイムアウトなど)。MessageEventタイプメッセージ有しdataに設けられた第一引数の文字列値に設定されているプロパティwindow.postMessageorigin呼び出しウィンドウのメインドキュメントの原点に対応するプロパティwindow.postMessage時にはwindow.postMessage呼ばれていた、そしてsource窓から提示されたプロパティをこれwindow.postMessageと呼ばれています。

を使用するにwindow.postMessageは、イベントリスナーをアタッチする必要があります。

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

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

そしてreceiveMessage関数は宣言されなければなりません:

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

オフサイトのiframeも、次を介してイベントを適切に送信する必要がありますpostMessage

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

ウィンドウは、ウィンドウ内のドキュメントの場所に関係なく、いつでも他のウィンドウのこのメソッドにアクセスしてメッセージを送信できます。したがって、メッセージの受信に使用されるイベントリスナーは、最初に、起点とソースのプロパティを使用して、メッセージの送信者のIDを確認する必要があります。これは控えめに言っても過言ではありません。プロパティのチェックに失敗するoriginと、場合によってはsourceプロパティがクロスサイトスクリプト攻撃を有効にします。

ソース:https : //developer.mozilla.org/en/DOM/window.postMessage



私は答えを得るのに遅すぎないことを願っています:質問のみですが、localhostは常に例外ですか?常に許可されていませんか?ローカルホストを介したテストを停止する必要がありますか?
Ayyash

1
理由はわかりませんが、次のように設定した場合 Access-Control-Allow-Origin: http://www.stackoverflow.com/Access-Control-Allow-Origin: http://www.stackoverflow.com(URLの末尾のスラッシュ)ではなく、SafariおよびFFでは機能せず、Chromeでは機能します。もちろん、スラッシュなしですべてのブラウザでうまく機能します。
mtfk

1
このpostMessage方法はHTML5の追加であるため、この方法がサポートされているブラウザでのみ機能することを人々に知らせる価値があるかもしれません。このプラグインはそれを説明しようとします。私はこれを難しい方法で学んでいるので、それについて言及するだけです。
IronicMuffin 2012

41

リバースプロキシ方式

  • メソッドタイプ:Ajax

サーバー上に単純なリバースプロキシを設定すると、ブラウザーがAjaxリクエストに相対パスを使用できるようになりますが、サーバーはリモートの場所へのプロキシとして機能します。

Apacheでmod_proxyを使用する場合、リバースプロキシを設定するための基本的な設定ディレクティブはProxyPassです。通常、次のように使用されます。

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

この場合、ブラウザは/ajax/web_service.xml相対URLとしてリクエストできますが、サーバーはのプロキシとして機能してこれを処理しhttp://other-domain.com/ajax/web_service.xmlます。

このメソッドの興味深い機能の1つは、リバースプロキシが複数のバックエンドに向けてリクエストを簡単に分散できるため、ロードバランサーとして機能することです。


17

私はJSONPを使用しています。

基本的に、あなたは追加します

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

あなたのページに。

some_func()が呼び出され、データが入っていることが通知されます。


7
JSONPには2つの問題があります。a)ターゲットドメインにスクリプトタグを追加しています。通常のjavascript(XSS攻撃)でさえ、何でも送り返すことができます。したがって、悪いことをしたり、ハッキングされたりしないように本当に信頼する必要があります。b)他のWebページが同じスクリプトタグを追加してデータを盗む可能性があるため、プライベートデータにJSONPを使用しないでください。
Erlend

1
@Erlend:Webで提供される情報は誰でも取得できます(適切な認証が必要でない限り)。その情報がどのように提示されるかについての正確な形式は、たとえJSONPであっても、これを良くも悪くもしません。
T-Bull

2
@ T-Bull:問題は、JSONPでは適切な認証が不可能であることです。ユーザーがサイトAにログインし、サイトBに移動します。サイトBは、JSONPスクリプトタグを使用してAからデータを読み込みます。まあまあです。次に、ユーザーは悪質なサイトCにアクセスし、JSONPスクリプトタグを使用してAからデータをロードします。したがって、ユーザーはAで認証されているため、Cの所有者はAからユーザーデータを盗むことができます。ユーザーはAで認証するために2要素認証を使用しました。問題は、JSONPが非常に安全でないことです。そしてJSONPはプレゼンテーションではありません。安全でないデータ転送です。
Erlend 2012

1
JSONPはHTTP GETのみをサポートします。
2012

これが表す.jsファイル-> "http://..../ someData.js ....別のサイトのクライアント側からdomを読み取ろうとしているため、同じ生成元のポリシーを回避する必要がある。
CS_2013

13

AnyOriginは一部のhttpsサイトでは適切に機能しなかったため、httpsで適切に機能するように見えるwhateverorigin.orgというオープンソースの代替を作成しました。

githubのコード


@DavidTitarenco-anyoriginの腹で起こっていることのいくつかを理解しようとすることに夢中になりました。幸いなことに、役立つブログ投稿が1つ見つかりました。次の人が必要に応じて、テストサイトが機能するようになります。
ripper234 '27 / 10/27

@neoascetic-使用法を修正しました... URLをエンコードする必要があります。
ripper234 2012年

12

私が見つけた同じ起源のポリシーを克服する最新の方法はhttp://anyorigin.com/です。

このサイトは、URLを指定するだけで、javascript / jqueryコードを生成するように作成されているため、その起源に関係なく、html / dataを取得できます。つまり、URLまたはWebページをJSONPリクエストにします。

私はそれがかなり便利だと思った:)

以下は、anyoriginのJavaScriptコードの例です。

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});

:それは私のhttpsのサイトなので、以下の私のオープンソースの代替チェックアウトするいくつかの問題与えたもののstackoverflow.com/questions/3076414/...を
ripper234

13
つまり、a)anyoriginはtemを介して転送されたすべてのデータを読み取ることができますb)anyoriginはサイトをXSSし、サイト上のすべてのデータを読み取り、マルウェアをユーザーに配信できます(anyoriginがハッキングされるとどうなりますか?)
Erlend

@Erlend-Whateveroriginをフォークし、独自のサーバーでホストします。コードは簡単なので、コードを見直して、エクスプロイトが隠されていないことを確認できます。
ripper234 2012年


3

JSONPが頭に浮かぶ:

JSONPまたは「パディング付きのJSON」は、基本JSONデータ形式を補完するものです。これは、ページがプライマリサーバー以外のサーバーからJSONをリクエストし、より有意義に使用できるようにする使用パターンです。JSONPは、クロスオリジンリソースシェアリングと呼ばれる最近の方法の代替手段です。


上記のJSONPに対する私のコメントを参照してください。個人データには適していません。
Erlend

1

個人的にwindow.postMessageは、私が最近のブラウザーで見つけた最も信頼できる方法です。XSS攻撃にさらされないようにするためにもう少し作業を行う必要がありますが、それは妥当なトレードオフです。

またwindow.postMessage、上記の他の方法を使用して古いブラウザに同様の機能を提供するラップする人気のあるJavaScriptツールキット用のプラグインもいくつかあります。


1

まあ、私はPHPでcurlを使用してこれを回避しました。ポート82でWebサービスを実行しています。

<?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;

?>

PHPファイルを呼び出すJavaScriptは次のとおりです

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();
}

私のHTMLはポート80のWAMPで実行されます。そこで、同じ起源のポリシーが回避されました:-)



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.