본문 바로가기
기타 CS

기술 면접 준비 - SOP(Same-Origin Policy) 그리고 CORS (Cross-Origin Resource Sharing)

by 밝지 2023. 2. 23.
728x90
반응형

SOP

Same-Origin Policy의 약자이다. RFC6454에서 처음 등장한 보안 정책으로 "같은 출처에서만 공유할 수 있다."는 규칙을 가진 정책이다.

 

 

CORS

Cross-Origin Resource Sharing의 약자이다. 오픈된 공간인 웹에서 사실상 같은 출처에서만 리소스를 공유(SOP)하는 것은 불가능하기 때문에 몇 가지 조항을 두고 이 조항에 해당하는 리소스 요청은 출처가 다르더라도 허용하는 정책을 만들었는데 그것이 바로 CORS 정책이다. CORS 정책을 위반한 경우 CORS 에러가 발생하는 것이다. 

[출처(Origin)는 무엇인가?]

-> URL 구성 요소 중 Protocol, Host, Port 세 가지를 합친 것이 출처다. 따라서 같은 출처라는 것은 프로토콜, 호스트, 포트 세 가지가 동일한 것이다.  (포트 번호의 경우 출처에 포트 번호가 명시적으로 포함된 경우에만 포트 번호까지 모두 일치해야 같은 출처로 인정된다.)

[CORS가 필요한 이유]

-> 웹 애플리케이션(브라우저)은 공격에 매우 취약하다.

-> 다른 출처의 통신에 대해 규약이 없다면 악의적으로 XSS(Cross-Site-Scriping: 공격자가 클라이언트 코드에 악의적인 스크립트를 주입하는 것. 주로 쿠키, 세션 정보 등을 빼가거나 자신들이 의도한 페이지로 리다이렉트 시키거나 악성코드 다운로드를 시작함), CSRF(Cross-Site Request Forgery: 공격자가 사용자의 동의 없이/인지하지 못하는 상황에서 브라우저로 하여금 서버에 어떤 요청을 보내도록 하는 것. XSS로 탈취한 정보를 이 때 사용할 수 있음) 등으로 사용자의 정보를 탈취하기가 쉬워진다. 

[CORS 동작 방식]

  1. 웹은 다른 출처의 리소스를 요청할 때 HTTP 프로토콜을 사용하여 요청을 보낸다. 이 때 브라우저는 요청 헤더(request header)의 Origin 필드에 요청을 보내는 출처를 담아 전송한다.
  2. 서버는 요청에 대한 응답 헤더(Response Header)의 Access-Control-Allow-Origin 이라는 값에 "이 리소스를 접근하는 것이 허용된 출처"를 내려준다.
  3. 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin 과 서버가 보내준 응답의 Access-Control-Arrow-Origin을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정한다. 

[CORS 에러]

CORS 에러는 브라우저에서 발생하는 것이다. CORS 정책은 서버에 저장되어 있으며 저장된 CORS 정책을 브라우저에 보내주는 일을 서버에서 하고 있기는 하지만, 그 CORS 정책을 보내달라고 서버에 요청하는 것은 브라우저다. 

  1. 브라우저에서 HTTP 요청이 발생했을 때 CORS 검증을 해야하는 상황인지 판단한다.
  2. 검증이 필요한 상황이면 CORS 검증을 서버에 요청한다.
  3. 응답 결과에 따라 브라우저는 HTTP 요청을 취소하고 에러를 뱉는다. 

 

 

 

CORS 시나리오

 

Preflight Request

브라우저는 본 요청을 보내기 전에 예비 요청을 먼저 보내 요청의 유효성(CORS 정책 위반 여부)을 검사한다.

  1. 클라이언트가 fetch 또는 XMLHttpRequest API를 사용하여 브라우저에 리소스를 받아오라는 명령을 내리면, 브라우저는 서버에 예비요청(preflight)을 먼저 보낸다.
  2. 서버는 예비 요청에 대한 응답으로 CORS 정보를 응답 헤더에 담아서 보내준다.
  3. 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아 보내준 허용 정책을 비교한 후, 요청이 안전하다고 판단하면 같은 엔드포인트로 본 요청을 보낸다.
  4. 서버가 본 요청에 대한 응답을 하면 브라우저는 최종적으로 이 응답 데이터를 클라이언트에 넘겨준다.

 

Simple Request

예비 요청을 보내지 않고 서버에 본 요청을 바로 보내는 방식이다. 서버가 응답으로 헤더에 Access-Control-Allow-Origin 값을 보내주면 그 때 브라우저가 CORS 정책 위반 여부를 검사한다. 하지만 예비 요청을 보내지 않고 본 요청을 보내는 경우는 한정적이다. 

  • 요청 메소드는 GET, HEAD, POST 만 가능
  • Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안된다.
  • 만약 Content-Type을 사용ㅎ는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.

 

Credentialed Request

인증된 요청을 사용하는 방식으로 이 시나리오는 CORS의 기본적인 방식이라기 보다는 다른 출처 통신간에 보안을 강화하고 싶을 때 사용하는 방법이다. 기본적으로 브라우저가 제공하는 비동기 리소스 요청 API인 fetch와 XMLHttpRequest는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 요청에 담지 않는다. 이 때 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 credentials 옵션이다. 옵션은 세 가지를 사용할 수 있다.

  • same-origin : 기본값으로 같은 출처간 요청만 인증 정보를 담을 수 있다.
  • inclue : 모든 요청에 인증 정보를 담을 수 있다.
  • omit : 모든 요청에 인증 정보를 담지 않는다.

 

 

728x90
반응형