동일 출처 정책을 우회하는 방법


150

동일한 원산지 정책

HTML / JS 동일 출처 정책 에 관한 커뮤니티 위키를 만들고 싶었습니다 . 이것은 SO에서 가장 많이 검색되는 주제 중 하나이며 통합 위키는 없으므로 여기로 이동하십시오.)

동일한 원본 정책은 한 원본에서로드 된 문서 또는 스크립트가 다른 원본에서 문서의 속성을 가져 오거나 설정하지 못하게합니다. 이 정책은 Netscape Navigator 2.0으로 거슬러 올라갑니다.

동일 출처 정책을 둘러 보는 가장 좋아하는 방법은 무엇입니까?

예제를 자세하게 유지하고 소스를 연결하는 것이 좋습니다.


4
좋은 생각입니다. 그래도 예제를 답변에 넣어야합니다. 그것이 의미하는대로, 그들은 질문을 다소 크게 만듭니다
Shog9

1
또한 각 접근 방식에 대한 보안 관련 목록을 추가해야합니다. JSONP는 개인 데이터에 대해 매우 안전하지 않습니다.
Erlend

왜 가까이? 이 (wiki) 질문은 지난 2 년 동안 매우 유용했습니다. 또한 많은 답변 참조 지원됩니다. 설명은 not constructive태그가 완전히 미쳐 보이는 것처럼 이해 될 것입니다. 재개로 투표했습니다.
David Titarenco

답변:


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에서 자바 스크립트를 예상 할 수 있습니다. Firefox와 같은 브라우저 document.domain에서는 완전히 외계인 도메인 으로 변경할 수 없으므로이 방법은 도메인 간 리소스에 적합하지 않습니다 .

출처 : https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

Cross-Origin 리소스 공유 방법

  • 방법의 유형 : AJAX .

CORS ( Cross-Origin Resource Sharing )는 여러 출처에서 소스에 액세스 할 때 브라우저와 서버가 통신해야하는 방법을 정의하는 W3C 실무 초안입니다. CORS의 기본 개념은 사용자 정의 HTTP 헤더를 사용하여 브라우저와 서버가 서로에 대해 충분히 알도록하여 요청 또는 응답의 성공 또는 실패 여부를 판별하는 것입니다.

사용자 지정 헤더 를 사용 GET하거나 POST사용하지 않고 본문이 인 간단한 요청의 경우 text/plain라는 추가 헤더와 함께 요청이 전송됩니다 Origin. Origin 헤더에는 요청 페이지의 출처 (프로토콜, 도메인 이름 및 포트)가 포함되어 있으므로 서버가 응답을 제공해야하는지 여부를 쉽게 결정할 수 있습니다. 예제 Origin헤더는 다음과 같습니다.

Origin: http://www.stackoverflow.com

서버는 요청이 허용되어야한다고 결정하면 전송 된 Access-Control-Allow-Origin것과 동일한 출처 또는 *공용 자원인지 를 에코 하는 헤더를 보냅니다 . 예를 들면 다음과 같습니다.

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

이 헤더가 없거나 출처가 일치하지 않으면 브라우저가 요청을 허용하지 않습니다. 모두 정상이면 브라우저가 요청을 처리합니다. 요청이나 응답에는 쿠키 정보가 포함되지 않습니다.

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실행해야하는 보류중인 스크립트가 완료 될 때 대상 창에서 a 가 전달됩니다 (예 : 이벤트 처리기 window.postMessage에서 호출 된 경우 나머지 이벤트 처리기, 이전에 설정된 보류 시간 초과 등). 는 MessageEvent타입 메시지, 보유 data에 설치된 제 1 인수의 스트링 값으로 설정된 속성 window.postMessageAN, origin호출 윈도우 기본 문서의 원점에 대응하는 속성 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>

모든 윈도우는 윈도우에서 문서의 위치에 관계없이 언제든지 다른 윈도우에서이 메소드에 액세스하여 메시지를 보낼 수 있습니다. 결과적으로, 메시지 수신에 사용 된 모든 이벤트 리스너는 먼저 출처 및 가능하면 소스 특성을 사용하여 메시지 송신자의 신원을 확인해야합니다. 과소 평가할 수는 없습니다 . originsource속성 을 확인하지 못하면 사이트 간 스크립팅 공격이 가능합니다.

출처 : 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 19:38에

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.

이 방법의 흥미로운 특징 중 하나는 리버스 프록시가 여러 백엔드로 요청을 쉽게 분배하여 로드 밸런서 역할을한다는 것 입니다.


17

JSONP를 사용합니다.

기본적으로

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

귀하의 페이지에.

some_func ()가 호출되어 데이터가 있음을 알립니다.


7
JSONP에는 두 가지 문제가 있습니다. a) 대상 도메인에 스크립트 태그를 추가하고 있습니다. 일반 자바 스크립트 (XSS 공격)를 포함하여 무엇이든 되돌릴 수 있습니다. 따라서 나쁜 일을하거나 해킹 당하지 않도록 신뢰해야합니다. b) 다른 웹 페이지는 동일한 스크립트 태그를 추가하고 데이터를 훔칠 수 있으므로 개인 데이터에 JSONP를 사용하지 마십시오.
Erlend

1
@Erlend : 웹에서 제공되는 모든 정보는 적절한 인증이 필요한 경우를 제외하고 누구나 검색 할 수 있습니다. 정보가 제공되는 방식의 정확한 형식은 JSONP가 아니더라도 더 나쁘게 만들지 않습니다.
T-Bull

2
@ T-Bull : 문제는 JSONP에서 올바른 인증이 불가능하다는 것입니다. 사용자는 사이트 A에 로그인 한 다음 사이트 B로 이동하여 JSONP 스크립트 태그를 사용하여 A에서 데이터를로드합니다. 좋고 좋다. 그런 다음 사용자는 악의 사이트 C를 방문하도록 속이는데 JSONP 스크립트 태그를 사용하여 A에서 데이터를로드합니다. 따라서 사용자가 A로 인증되므로 C 소유자는 이제 A에서 사용자 데이터를 훔칠 수 있습니다. 사용자는 A로 인증하기 위해 2 단계 인증을 사용했습니다. 문제는 JSONP가 매우 안전하지 않다는 것입니다. 그리고 JSONP는 프레젠테이션이 아닙니다. 안전하지 않은 데이터 전송입니다.
Erlend

1
JSONP는 HTTP GET 만 지원합니다.
opyate

.js 파일이 나타내는 것은 무엇입니까?-> "http : //..../ someData.js .... 다른 사이트 클라이언트 측에서 dom을 읽으려고하는데 동일한 출처 정책을 우회해야합니다. .
CS_2013

13

AnyOrigin은 일부 https 사이트에서 제대로 작동하지 않으므로 https 와 잘 작동하는 whateverorigin.org 라는 오픈 소스 대안을 작성했습니다 .

github의 코드입니다 .


@DavidTitarenco-anyorigin의 뱃속에서 일어나는 일들을 이해하려고 미치게 만들었습니다. 운 좋게도 도움이되는 블로그 게시물을 찾았습니다. 이제 다음 사람이 필요한 경우 테스트 사이트를 운영하게됩니다.
ripper234

@neoascetic-사용법 수정 ... 이제 URL을 인코딩해야합니다.
ripper234

12

내가 찾은 동일한 출처 정책을 극복하는 가장 최근의 방법은 http://anyorigin.com/

사이트는 URL을 제공하기 위해 만들어졌으며 출처에 관계없이 html / data를 가져올 수있는 javascript / jquery 코드를 생성합니다. 즉, URL 또는 웹 페이지를 JSONP 요청으로 만듭니다.

나는 그것이 매우 유용하다는 것을 알았다 :)

다음은 anyorigin의 일부 자바 스크립트 코드입니다.

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

https 사이트에 문제가 있었지만 아래의 오픈 소스 대안을 확인하십시오. stackoverflow.com/questions/3076414/…
ripper234

13
즉, a) anyorigin은 전체를 통해 전송 된 모든 데이터를 읽을 수 있습니다. b) anyorigin은 사이트를 XSS하고, 사이트의 모든 데이터를 읽고, 악성 코드를 사용자에게 제공 할 수 있습니다 (anorigin이 해킹되면 어떻게됩니까?)
Erlend

@Erlend-Whateverorigin을 포크하고 자신의 서버에서 호스팅하십시오. 코드는 사소한 것이기 때문에 코드를 검토하여 숨겨진 익스플로잇이 숨겨져 있지 않은지 확인할 수 있습니다.
ripper234


3

JSONP는 마음에 온다 :

JSONP 또는 "패딩이있는 JSON"은 기본 JSON 데이터 형식을 보완하는 것으로, 기본 서버 이외의 서버에서 페이지가 JSON을 요청하고보다 의미있게 사용할 수 있도록하는 사용 패턴입니다. JSONP는 Cross-Origin Resource Sharing이라는 최신 방법의 대안입니다.


위의 JSONP에 대한 내 의견을 참조하십시오. 개인 데이터에는 적합하지 않습니다.
Erlend

1

개인적 window.postMessage으로 최신 브라우저에서 찾은 가장 안정적인 방법입니다. XSS 공격에 자신을 노출시키지 않으려면 약간 더 많은 작업을 수행해야하지만 이는 합리적입니다.

window.postMessage위에 설명 된 다른 방법을 사용하여 이전 브라우저와 유사한 기능을 제공 하는 랩핑 기능을 갖춘 인기있는 Javascript 툴킷 용 플러그인도 있습니다 .


1

글쎄, 나는 이것을 우회하기 위해 PHP에서 curl을 사용했다. 포트 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;

?>

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

내 HTML은 포트 80의 WAMP에서 실행됩니다. 이제 동일한 원산지 정책이 우회되었습니다 :-)



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.