웹 개발을 진행해본 사람은 한 번쯤 CORS에러를 마주쳤을 겁니다. 보통 다른 도메인에 정보를 요청할 때 발생하는데요. 이번 포스트에는 RFC 문서를 바탕으로 왜 이 에러가 발생하는지 알아보도록 하겠습니다. RFC 문서를 참고하여 최대한 올바른 정보를 토대로 작성했습니다.

1. SOP

첫 번째 이유는 아주 간단합니다. 브라우저는 기본적으로 SOP(Same-Origins Policy)를 준수하기 때문입니다. 그렇다면 SOP는 무엇일까요? 이 내용은 RFC 6454에 잘 명시되어 있습니다. 먼저 Origin이라는 용어의 의미부터 알아보겠습니다.

1.1. Origins

3.2. Origin
...
user agents group URIs together into protection domains called "origins". Roughly speaking, two URIs are part of the same origin (i.e., represent the same principal) if they have the same scheme, host, and port. (See Section 4 for full details.)

User-agent(ex. 브라우저)가 같은 보호 규칙과 도메인을 가지고 있는 URI들을 그룹화한 것이 "Origins"입니다. 구체적으로, 같은 스키마, 호스트 그리고 포트 주소를 가지는 경우 하나의 Origins이라고 말할 수 있습니다. 예를 들어, 아래의 URI들은 같은 Origins입니다. 도메인, 프로토콜 그리고 포트 주소가 같기 때문이죠.

http://example.com/
http://example.com:80/
http://example.com/path/file

하지만 아래의 URI들은 같은 Origins라고 할 수 없습니다. 도메인, 프로토콜 그리고 포트번호가 하나 이상  다르기 때문입니다.

http://example.com/
http://example.com:8080/
http://www.example.com/
https://example.com:80/
https://example.com/
http://example.org/
http://ietf.org/

1.2. Same-Origins Policy

SOP(Same-Origins Policy)는 처음 스크립트를 요청한 도메인과 같은 Origins을 가진 URI만 요청할 수 있다는 정책입니다. 만약 http://example.com/ 페이지에 접속해서 스크립트를 요청했다면 위에서 언급한 같은 Origins을 가진 URI만 요청할 수 있습니다. 

2. 왜 SOP가 필요할까?

2.1 좋은 서버와 나쁜 서버

1. Introduction
User agents interact with content created by a large number of authors. Although many of those authors are well-meaning, some authors might be malicious. To the extent that user agents undertake actions based on content they process, user agent implementors might wish to restrict the ability of malicious authors to disrupt the confidentiality or integrity of other content or servers.

As an example, consider an HTTP user agent that renders HTML content retrieved from various servers. If the user agent executes scripts contained in those documents, the user agent implementor might wish to prevent scripts retrieved from a malicious server from reading documents stored on an honest server, which might, for example, be behind a firewall.

사용자가 만약 여러개의 서버에서 스크립트를 받아서 실행한다고 생각해봅시다. 서버는 신뢰성이 높은 좋은 서버도 있겠지만 바이러스를 퍼트리거나 불법으로 데이터를 수집하려는 악의적인 서버가 존재할 수 있습니다. 만약 좋은 서버와 나쁜 서버의 스크립트를 브라우저에서 동시에 실행시키면 어떻게 될까요? 좋은 서버의 데이터나 사용자 정보가 나쁜 서버에 의해 악의적으로 사용되거나 아예 프로그램을 망쳐버릴 수도 있습니다. 그럼 각각의 URI에 서로 다른 보안 정책을 사용하는 건 어떨까요? 그렇다면 나쁜 서버의 기능을 방지하면서 서로 다른 도메인에 데이터를 요청할 수 있으니까요! 

3.2. Origin
In principle, user agents could treat every URI as a separate protection domain and require explicit consent for content retrieved from one URI to interact with another URI. Unfortunately, this design is cumbersome for developers because web applications often consist of a number of resources acting in concert.

아쉽지만, 이를 구현하는 것은 쉽지 않습니다. 웹 어플리케이션은 수많은 컴퓨팅 리소스들로 구성되어 있기 때문에 이를 URI 마다 제한하는 기능을 추가하는 것은 매우 복잡하기 때문입니다.

그래서, User-agent(ex. 브라우저)는 같은 신뢰성을 가진 서버에게만 스크립트를 요청하기로 결정했습니다. 이렇게 하면 다른 나쁜 서버의 스크립트가 실행되는 것을 원천적으로 차단할 수 있으니까요.

3. SOP의 예외

물론 SOP에도 예외가 존재합니다. 위 글을 자세히 읽어보셨다면 오직 스크립트만 같은 서버에 요청했다고 말씀드렸는데요, 그 말은 즉 이미지나 CSS 등의 데이터는 SOP의 대상이 아닙니다. 좀 더 일반적으로 말하면 권한(Authority)이 없는 데이터는 SOP의 대상이 아닙니다.

3.3. Authority
Although user agents group URIs into origins, not every resource in an origin carries the same authority (in the security sense of the word "authority", not in the [RFC3986] sense). For example, an image is passive content and, therefore, carries no authority, meaning the image has no access to the objects and resources available to its origin. By contrast, an HTML document carries the full authority of its origin, and scripts within (or imported into) the document can access every resource in its origin.

권한(Authority)은 리소스에 접근하는 기능이 있는 것을 의미합니다. 스크립트는 당연히 코드를 통해서 리소스에 접근하고 이를 조작, 전송할 수 있습니다. 하지만, 이미지나 CSS는 이러한 기능이 없기 때문에 권한이 없다고 할 수 있습니다.

4. 결론 및 요약

  1. 웹에는 신뢰성이 있는 서버와 악의적인 서버가 존재합니다.
  2. 신뢰성이 있는 서버와 악의적인 서버의 스크립트를 같이 요청하면 신뢰성이 있는 서버의 정보나 리소스가 악용될 수 있습니다.
  3. 서로 다른 Origin마다 보안 규칙을 적용할 수 있지만, 이를 구현하는 것은 매우 복잡한 일입니다.
  4. 그래서, 같은 신뢰성을 가진 서버에서만 스크립트를 요청할 수 있습니다. 
  5. 그러므로 서로 다른 Origin에 요청을 보낼 경우 교차 출처 리소스 공유 (Cross-origin resource sharing) 에러가 발생합니다.
  6. 하지만 이미지나 CSS 처럼 리소스 접근권한이 없는 경우는 다른 Origin에 요청이 가능합니다.

 

+ Recent posts