SOP란?
동일 출처 정책(Same Origin Policy)의 약자 → Origin에서 로드된 문서 또는 스크립트가 다른 Origin의 리소스와 상호 작용할 수 있는 방법을 제한하는 중요한 보안 메커니즘, 즉 출처가 동일해야만 서로 상호작용이 가능하다는 의미이다.
SOP가 동작하지 않는다면 다음과 같은 CSRF 공격 시나리오가 가능하다.
1.
<iframe src="http://mail.naver.com" width="0" height="0"></iframe>공격자는 상대방의 메일 정보를 탈취하기 위해 abc.com 사이트에 네이버 메일로 접속하는 iframe 태그를 삽입한다.
2.
피해자가 abc.com 사이트에 접속했을 때 네이버에 로그인되어 있다면 피해자의 브라우저에 저장된 쿠키로 인해 자동적으로 로그인되어 iframe에서 네이버 메일로 접속된다. iframe 크기는 0이므로 피해자는 해킹 사실을 인지하지 못한다.
3.
SOP가 존재한다면 abc.com과 mail.naver.com이 다른 origin이므로 mail.naver.com을 읽지 못한다.하지만 SOP가 없다면 저 메일을 그대로 읽어들여 공격자 서버로 전송하게 된다.웹 브라우저는 SOP가 적용되기 때문에 상위 문서에서 iframe 내부의 문서를 참고하게 될 때 orgine이 다르므로 참조할 수 없다. 따라서 이러한 해킹 공격을 방어할 수 있다.
출처란?
두 URL의 프로토콜, 포트(명시한 경우), 호스트가 모두 같아야 동일한 출처!!
•
http의 기본포트 - 80, https의 기본포트 - 443
URL | 결과 | 이유 |
https://kyun2da.github.io/dir2/other.html | 성공 | 경로만 다름 |
https://kyun2da.github.io/dir/inner/another.html | 성공 | 경로만 다름 |
http://kyun2da.github.io/secure.html | 실패 | 프로토콜 다름 |
https://kyun2da.github.io:81/dir/etc.html | 실패 | 포트 다름 (https://는 443이 기본값) |
https://kyun2da.github.com/dir/other.html | 실패 | 호스트 다름 |
CORS란?
교차 출처 리소스 공유(Cross Origin Resource Sharing)의 약자, 추가 HTTP header를 사용하여, 한 출처에서 실행 중인 웹 리소스가 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.
SOP처럼 교차 출처의 접근을 막는다면 보안상에선 유리하나, 과거와 달리 최근 웹의 생태계는 Frontend 서버와 BackEnd 서버를 따로 관리하는 경우가 대부분이라 주소가 서로 다른 경우가 많다.
이런 상황에서 교차 출처의 접근을 허용하기 위해서 CORS가 도입됨.
CORS의 동작 방식
Simple Request(단순 요청)
HTTP 요청 시, 아래 3가지 항목이 모두 충족되면 브라우저는 이를 Simple Request 로 판단하고 동작한다.
1.
요청 메소드가 GET, HEAD, POST 중 한가지여야 한다.
2.
요청 헤더가 'Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width' 만 사용한다.
3.
Content-Type 값은 'application/x-www-form-urlencoded, multipart/form-data, text/plain' 만 사용한다.
•
응답에는 Access-Control-Allow-Origin 헤더가 포함이 되어야 Simple Request의 응답으로 인식한다.
위 사항이 적용되지 않은 경우, 브라우저는 에러를 발생시키고 응답은 무시한다.
1.
HTTP 통신 헤더인 Origin 헤더에 요청을 보내는 곳의 정보를 담고 서버로 요청을 보낸다.
2.
이후 서버는 Access-Control-Allow-Origin 헤더에 허용된 Origin이라는 정보를 담아 보낸다.
3.
클라이언트는 헤더의 값과 비교해 정상 응답임을 확인하고 응답을 받는다.
Preflight Request(예비 요청)
메인 요청을 하기 전, 브라우저가 서버에 예비 요청을 보내 통신을 위해 어떤 옵션이 적용되어 있는지 확인하는 동작 방식이다.
Simple Request 와 Credentialed Request 를 제외한 나머지 경우, 브라우저가 Preflight Request 를 보낸다.
Preflight Request 에 대한 응답을 받으면 브라우저는 허용 정책들을 비교 후, 확인이 완료되면 메인 요청을 합니다.
정책에 위반되는 경우, 브라우저는 에러를 발생시키고 메인 요청을 보내지 않습니다.
1.
OPTIONS 메서드로 서버에 예비 요청을 먼저 보낸다.
2.
서버는 예비 요청에 대한 응답으로 Access-Control-Allow-Origin 헤더를 포함한 응답으로 클라이언트에 보낸다.
3.
Simple Request 와 같은 방법으로 수행한다.(요청과 응답을 주고받음.)
Credentialed Request(인증 요청)
XMLHttpRequest 혹은 Fetch 에 자격증명(쿠키, authorization, 인증서..)를 포함하는 요청을 하는 방식.
Preflight Request 같은 요청을 보내는데, 사전 요청에 다음과 같은 필드가 포함되어야 한다.
Credentialed Request 에 대한 응답에는 다음과 같은 필드가 포함되어야 한다.
•
Access-Control-Allow-Origin는 와일드카드(*) 가 아닌 출처가 반드시 지정되어야 한다.
위 사항이 적용되지 않은 경우, 브라우저는 에러를 발생시키고 응답은 무시한다.