CORS 란

Khan·2022년 7월 23일
0
post-thumbnail
post-custom-banner

SOP (Same Origin Policy)

정의

  • 다른 출처의 리소스를 사용하는 것에 제한 하는 보안 방식

origin

  • URL의 Protocol, Host, Port를 통해 같은 출처인지 다른 출처인지 판단할 수 있다.
  • ex) http://github.com:443 : http : 프로토콜, github.com : 호스트, 443 : 포트

why use SOP

  • 예시
    1. 클라이언트가 페이스북에 로그인(토큰 발급)을 한다.
    2. 해커가 클라이언트에게 http://hacker.ck라는 URL을 보냄.
    3. 클라이언트가 해커가 보낸 링크가 흥미로워서 클릭함.
    4. 해커가 보낸 페이지에는 클라이언트의 토큰을 이용하여 개인정보를 탈취하는 스크립트가 포함되어 있음.

만약 페이스북 서버가 토큰만으로 사용자를 판단한다면 클라이언트와 해커의 요청을 구분하기 힘들 것이다. 그래서 개인정보를 탈취하여 악의적으로 사용 할 가능성이 있음

반면에 요청 URL을 확인한다면 클라이언트의 출처는 http://www.facebook.com/~ 이고 해커의 출처는 http://hacker.hc 일테니 서로 다른 출처라는 것을 확인하여 악의적인 요청을 방지할 수 있다.

위와 같은 상황, 요청의 출처가 다르다면 Cross Origin SOP에 위반이라고 한다.
하지만 외부 라이브러리도 사용해야 하는데 요청과 리소스를 매번 동일한 출처로만 받을 수는 없다.

이 때 필요한 것이 CORS이다.

CORS (Cross Origin Resource Sharing)

CORS 란

CORS는 다른 출처의 자원을 공유하는 것이다.

교차 출처 리소스 공유(CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 어플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에게 알려주는 체제이다.
출처 : MOZILLA

CORS 접근제어 시나리오

  • 사전 요청 (Preflight Request)

  • 단순 요청 (Simple Request)

  • 인증 요청 (Credentialed Request)

사전 요청 (Preflight Request)

사전 요청은 OPTIONS 메서드를 통해 다른 도메인 리소스에 요청이 가능한지 확인하는 작업이다.
요청이 가능한 것을 확인하면 실제 요청을 보낸다.

  • 순서

    1. 자바스크립트의 fetch API를 이용해 브라우저에게 리소스를 받아오라는 명령을 내린다.
    2. 브라우저는 서버에게 예비 요청을 먼저 보내게 된다.
    3. 서버는 이 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용하고 금지하는지에 대한 정보를 응답 헤더에 담아 브라우저에게 다시 보내주게 된다.
    4. 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 허용 정책을 비교한 후 요청을 보내도 안전하다고 판단되면 같은 엔드포인트로 다시 본 요청을 보내게 된다.
    5. 서버가 본 요청에 대한 응답을 하면 브라우저는 최종적으로 응답 데이터를 자바스크립트에게 넘겨준다.
  • Preflight Request

    • Origin : 요청 출처
    • Access-Control-Request-Method : 실제 요청의 메서드
    • Access-Control-Request-Headers : 실제 요청의 추가 헤더
  • Preflight Response

    • Access-Control-Allow-Origin : 허가 출처
    • Access-Control-Allow-Methods : 허가 메서드
    • Access-Control-Allow-Headers : 허가 헤더
    • Access-Control-Max-Age : Preflight 응답 캐시 시간
  • 특징

    • Preflight Response의 응답 코드는 200대여야한다
    • Body는 비어있는 것이 좋다.
  • 왜 필요할까?

    Preflight가 왜 있는가에 대해서는 쉽게 말해서 CORS spec이 생기기 이전에 만들어진 서버들은 브라우저의 SOP(same origin policy) request만 가능하다는 가정하에 만들어졌는데, cross-site request가 CORS로 인해서 가능해졌기 떄문에 이런 서버들은 cross-site request에 대한 security mechanism이 없다보니 보안적으로 문제가 생길수 있으니 이런 서버들을 보호하기 위해 CORS spec에 preflight request를 포함한겁니다. Preflight request로 서버가 CORS를 인식하고 핸들할수있는지 먼저 확인을 함으로써 CORS를 인식하지 못하는 서버들을 보호할수있는 매커니즘 입니다.

단순 요청 (Simple Request)

Preflight 요청 없이 바로 요청을 보낸다.

단순 요청은 예비 요청을 보내지 않고 바로 서버에게 본 요청부터 때려박은 후, 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다. 즉, 프리플라이트와 단순 요청 시나리오는 전반적인 로직 자체는 같되, 예비 요청의 존재 유무만 다르다.

Simple Request는 아래와 같은 조건을 만족해야한다.

  • 메서드 : GET, POST, HEAD
  • Content-Type은 아래 셋 중 하나여야 한다.
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 헤더 : Accept, Accept-Language, Content-Language, Content-Type 만 허용 한다.

인증 요청 (Credentialed Request)

인증 관련 헤더를 포함할 때 사용하는 요청이다.

  • 클라이언트

    • 쿠키 또는 JWT 토큰을 담아 보낼 경우 credentials : include 를 포함하여 보낸다.
  • 서버

    • Access-Control-Allow-Origin 헤더의 값에는 * 이 오면 안되고 http://foo.origin 과 같은 구체적인 도메인이 와야 합니다.
    • Access-Control-Allow-Credentials : true 해야 클라이언트의 인증 포함 요청에 허용이 가능하다.
  • 만약 Credentials 옵션은 true로 줬는데 Access-Control-Allow-Origin의 값을 * 로 주면 에러가 발생합니다.

참조

[10분 테코톡] 🌳 나봄의 CORS
evan-moon님 : CORS는 왜 이렇게 우리를 힘들게 하는걸까?

post-custom-banner

0개의 댓글