엄범

 

Same-origin Policy와 CORS

 

Same-origin Policy란?
  • 스크립트에 적용되는 정책이며, 스크립트 내에서 다른 리소스를 요청할 때 요청지가 Same-origin이 아니면 막는 정책
  • 현재 리소스(스크립트)를 가져온 출처와 (프로토콜, 호스트, 포트)가 동일한 출처를 Same-origin으로 판단한다.
    • 이는 브라우저가 `` document.domain``을 보고 판단함.

 

좀 더 정확히는, Cross-origin read를 막는다.
  • https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy#교차_출처_네트워크_접근
    • 교차 출처 쓰기는 보통 허용합니다.
      • Cross-origin으로의 링크, 리다이렉트, form submit 등
    • 교차 출처 삽입은 보통 허용합니다.
      • HTML 태그로 가져오는 항목(<script> 등), 글꼴(@font-face)
    • 교차 출처 읽기는 보통 불허 (ajax 등)
      • 하지만, 종종 교차 출처 삽입 과정에서 읽기 권한이 누출됩니다.
      • 예를 들면 삽입한 이미지의 크기나 삽입한 `` <script>``의 행동 등을 읽을 수 있습니다.
        • (*그래서 JSONP로 우회가 가능한 것)

 

왜 script에서 Cross-origin read를 막는가?
  • 단순히 Cross-origin으로 데이터 보내는걸 막고자 했다면 form submit도 막았어야 한다. 이건 아니고.
  • 마찬가지로 Cross-origin에서 데이터 가져오는 것 자체를 막고자 했다면, submit이나 삽입도 막았어야 한다. 이 것도 아니고.

 

왜 읽기만 불허할까?
  • 읽기를 불허한다는건, script 내에서 ajax 등을 이용해서 페이지 이동 없이 Cross-origin에서 데이터 받는 것을 막겠다. 라는 의미인데...
  • 사실은 브라우저가 여러 도메인에 동시에 접속 가능하다는 것과 관련이 있다.

 

생각해보면 다음과 같은 시나리오가 가능함.
  • 상황
    • 내가 1탭에는 구글을, 2탭에는 악성사이트를 띄워 둔 상태.
    • 2탭의 악성사이트 js에서는 접속자의 구글 계정 정보를 알아내고 싶어 한다.
    • 구글 계정 정보는 www.google.com/account로 요청을 보내야정보를 얻을 수 있음.
  • 2탭의 js에서 form submit 요청을 보낸다면? www.google.com/account로 요청을 보낼 수는 있겠지만, 해당 정보를 악성사이트 개발자가 가져오지는 못한다. submit 하면서 페이지 이동이 발생하니 단순히 브라우저 상에서 유저가 클릭해서 들어간 것과 별 차이가 없으니까. 공격으로서 아무런 의미가 없음.
  • 반면 Same-origin Policy가 없어서 www.google.com/account로 ajax 요청이 가능하다고 가정해보자.
  • 2탭의 js에서 ajax로 www.google.com/account로 요청 보내서 계정 정보 가져오고, 이 정보를 악성사이트로 submit하거나 또 다시 ajax로 보낼 수 있음!

 

즉, 악성사이트가 정상사이트의 유저 세션(쿠키)을 이용해 정상사이트로부터 중요 정보를 획득하는 것을 막기 위해서

js 내에서 Cross-origin으로 read 요청을 보내는 것을 브라우저단에서 막아주는 것이 Same-origin policy.

라고 정리할 수 있다.

e.g., ) `` XMLHttpRequest`` 객체는 js 파일을 가져왔던 서버하고만 통신할 수 있다.

 

그럼 Cross-origin read가 필요한 경우 어떻게 해결할 수 있는가?
  • 클라이언트 사이드에서 JSONP
    • 가져오는 데이터가 JSON이어야만 한다는 제약이 있기는 함
    • 흔히 사용하는 ``html <script src=" (.js OR .json)"></script>`` 가 바로 JSONP다.
    • jQuery는 ``js $.ajax({dataType: 'jsonp'..``로 XHR 리퀘스트 형식처럼 사용할 수 있도록 지원한다.
    • front / back 둘 다 개발한다면 CORS를 사용하는 편이 더 낫겠지. 이건 약간 기믹같은 느낌이 들어서
  • 클라이언트가 직접 타 도메인에서 받아오는게 아니라, 서버 사이드에서 대신 타 도메인에 접근해 데이터를 받아온 다음, 이를 클라이언트에게 내려주는 방식도 있음.
  • 기타 등등! https://en.wikipedia.org/wiki/Same-origin_policy#Relaxing_the_same-origin_policy

 

Cross-origin 접근 막기

https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy#교차_출처_접근_막기

  • 교차 출처 쓰기를 방지하려면 추측 불가능한 토큰을 요청에 포함하세요. 교차 출처 요청 위조(Cross-Site Request Forgery, CSRF) 토큰이라고 부릅니다. 토큰을 요구하는 페이지의 교차 출처 읽기도 막아야 합니다.
  • 리소스의 교차 출처 읽기를 방지하려면 삽입 불가하도록 설정하세요. 리소스 삽입 과정에서 일부 정보가 새어 나가므로 방지해야 합니다.
  • 교차 출처 삽입을 방지하려면, 리소스가 위에 나열한 삽입 가능 형태로 읽히지 않도록 해야 합니다. 브라우저는 Content-Type 헤더를 준수하지 않을 수도 있습니다. 즉, <script> 태그가 HTML 문서를 가리키도록 설정하는 경우, 브라우저는 HTML을 JavaScript로 분석하려고 시도합니다. 방지하려는 리소스가 사이트의 진입점이 아닌 경우 CSRF 토큰을 사용하는 것도 삽입 방지의 방법입니다.

 

'Languages & Frameworks > Front-end' 카테고리의 다른 글

SameSite Cookie  (0) 2020.06.15
Same-origin Policy, CORS  (0) 2020.06.14
HTML5 data-* attribute  (0) 2018.11.23
[HTML] form tag, input 태그 속성  (0) 2017.06.10
[Front-end] Ajax  (0) 2017.05.28
CSS Selector  (0) 2017.05.24