SOP, CORS
Last updated
Last updated
동일 출처 정책
동일한 출처의 리소스만 상호작용하는 정책이다.
웹 페이지에서 실행되는 스크립트가 다른 도메인의 웹 페이지에 있는 리소스에 접근할 수 없도록 제한하는 정책이다.
출처 A(ex: service.example.com
)에서 온 문서가 출처 B(ex: api.example.com
)에서 가져온 리소스에 접근할 하는 것을 차단
SOP 정책은 웹 브라우저에서 기본적으로 제공되며, 웹 개발자가 명시적으로 설정할 필요는 없다.
동일 출처와 교차 출처의 기준은 프로토콜, Host(도메인), Port 동일 여부이다. 이중 하나라도 Origin과 다르면 그 URL은 교차출처로 인식된다.
두 URL의 프로토콜, 호스트, 포트가 모두 같아야 동일한 출처로 인정되며 웹 사이트를 샌드박스화 하여 잠재적인 보안 위협으로부터 보호해주는 정책이다.
SOP 정책이 없는 상황이라고 가정해보자.
사용자가 악의적인 JavaScript
가 포함되어 있는 페이지 (ex:service.example.com
) 에 접속한다.
사용자가 악성 페이지에 (ex:service.example.com
) 접속하여 악의적인 JavaScript
가 실행된다.
악성 페이지 (ex:service.example.com
)는 사용자가 모르는 사이에 다른 사이트 (ex: portal.example.com
)에 임의의 요청을 보내어, 사용자의 개인 정보(사용자 IP 등)를 탈취할 수 있다.
SOP 장점: CSRF, XSS 같은 보안 취약점 공격으로 부터 안전하다.
SOP 단점: 제한된 정책 때문에 외부에서 데이터를 불러오지 못한다.
교차 출처 리소스 공유
보안도 중요하지만 기능 상 어쩔 수 없이 다른 도메인에 있는 리소스에 접근해야 하는 경우가 발생한다.
이러 경우를 대비 하기 위해 SOP의 예외 정책으로 CORS 정책이 만들어졌다. CORS를 사용하면 SOP의 제약을 받지 않는다.
CORS의 요청 방식에는 크게 2가지 방식이 있다.
Simple Request
Preflight Request
HTTP Method 가 GET
, POST
, HEAD
중 하나
Content Type 이 application/x-www-form-urlencoded
, multipart/form-data
, text/plain
중 하나
CORS-safelisted request-header
를 포함하는 경우
XMLHttpRequest.upload
에 이벤트 핸들러, 리스너가 등록되지 않은 경우
ReadableStream
객체가 포함되지 않은 경우
클라이언트가 요청 헤더에 자신의 Origin
을 실어서 서버로 요청
서버는 요청 메시지 헤더의 Origin
을 확인한다
CORS 요청이 유효하다면 서버는 응답 헤더에 Access-Control-Allow-Origin
헤더를 추가해 사용자에게 응답한다.
service.example.com
-> api.example.com
사이트의 리소스를 가져오기 위해 JavaScript에서 HTTP 요청 메시지를 전송한다.
HTTP 요청 메시지는 아래와 같이 전송된다.
service.example.com
사이트의 프로토콜, 호스트, 포트 정보가 Origin 헤더를 통해 전송된다.
서버는 HTTP 요청 메시지의 Origin 헤더를 보고 어느 사이트를 통해 요청 메시지가 전송되었는지 확인할 수 있다. 해당 요청에 대한 HTTP 응답 메시지는 아래와 같다.
서버는 Access-Control-Allow-Origin
헤더를 통해 응답해야 한다.
Access-Control-Allow-Origin: *
= 모든 도메인에서 접근을 허용한다.
Access-Control-Allow-Origin: https://service.example.com
= https://service.example.com
의 요청에서만 리소스에 대한 접근을 허용한다.
만약 Access-Control-Allow-Origin
헤더가 없거나, 해당 헤더에 명시된 출처가 요청을 보낸 페이지의 출처와 일치하지 않는 경우, 브라우저는 SOP 정책에 따라 응답을 차단한다.
Simple Request
의 조건을 만족하지 못할시 브라우저가 자동으로 생성한다
Simple Request
와 달리 OPTIONS
메서드를 통해 다른 Origin
의 리소스로 HTTP 요청을 미리 보내(preflight
) 실제 요청이 전송하기에 안전하지 확인한다
브라우저는 안전하다고 판단되면 이를 통해 실제 요청을 보낸다. CORS 요청의 경우, 유저 데이터에 영향을 줄 수 있기 때문에 이와 같이 미리 전송한다
Origin
현재 자신의 URL 정보를 포함
Access-Control-Request-Method
Preflight Request
에서 사용되며 어떤 Method를 사용할지 서버에게 알리기 위해 사용되는 헤더(POST, GET, DELETE 등이 포함)
Access-Control-Request-Headers
Preflight Request
에서 사용되며 어떤 Header를 사용할 것인지 서버에게 알리기 위해 사용되는 헤더 (X-PINGOTHER, Content-Type 등이 포함)
Access-Control-Request-*
헤더의 경우 실제 POST 요청시에는 포함되지 않고 OPTIONS 요청시에만 사용된다.
Access-Control-Allow-Origin
브라우저가 해당 Origin
이 리소스에 접근 가능하도록 허용할 때 사용되는 헤더
*
로 설정할 경우 브라우저는 credentials
옵션이 없는 요청에 한해 모든 Origin
이 해당 리소스에 접근 가능하도록 허용
Access-Control-Allow-Methods
Preflight Request
에 대해 리소스에 접근할 때 허용되는 Method
를 지정하기 위해 사용되는 헤더 (POST, GET, OPTIONS, *)
Access-Control-Allow-Headers
Preflight Request에 대해 해당 요청에서 사용할 수 있는 Header를 지정하기 위해 사용되는 헤더 (X-PINGOTHER, Content-Type 등)
Origin(https://www.example.com
)
비교
https://www.example.com/about
동일 출처
https://www.example.com/about?q=query
동일 출처
https://abc.example.com
교차 출처
http://www.example.com
교차 출처
https://www.example.com:8080
교차 출처