CORS

진영민·2022년 10월 12일
0

잡다한 상식

목록 보기
7/22

Origin

출처
URL에서 프로토콜, 도메인, 포트 번호를 합친 부분

SOP

Same Origin Policy, 동일 출처 정책
다른 Origin으로 요청을 보낼 수 없도록 금지하는 브라우저의 기본적인 보안 정책

하지만 기술이 발전합에 따라 다른 Origin끼리 데이터를 주고 받아야 하는 일이 많아졌고, SOP는 예회 사항을 두게 되었다.

script태그로 javascript를 실행하는 경우, 이미지를 렌더링 하는 경우, link태그로 스타일 시트 파일을 불러오는 경우, HTML문서를 화면에 보여주는 경우에는 다른 Origin으로의 허용을 요청한다.

CORS

Cross Origin Resource Sharing
다른 Origin으로 요청을 보내기 위해 지켜야 하는 정책, 원래대로라면 SOP에 의해 막히게 될 요청을 풀어주는 정책이다.

CORS는 브라우저의 정책이다.
브라우저가 자신이 보낸 요청 및 서버로부터 받은 응답의 데이터가 CORS정책을 지키는지 검사하여 안전한 요청을 보낸 건지 검사한다.
서버가 정상적으로 응답을 해줬더라도 안전한 요청이 아니라고 판단되면 해당 응답을 버린다.

SOP의 필요성

  1. 악의적인 마음을 품은 해커가 자신의 웹사이트를 구축해놓고, 이 웹사이트를 가리키는 링크를 담은 메일을 사용자에게 보낸다.
  2. 이 사용자는 A라는 웹사이트에 로그인이 되어 있어서 브라우저 단에 인증 정보가 존재한다고 해보자.
  3. 만약 그 사용자가 실수로 해당 링크를 클릭하여 해커의 웹사이트에 접속하면, 해커가 심어둔 JavaScript 코드가 실행되어 자기도 모르게 A 웹사이트로 개인 정보를 조회하는 API 요청을 보낸다.
  4. 이 사용자의 브라우저 단에는 인증 정보가 존재하기 때문에, 이것이 해당 요청에 함께 실어서 전송되면 서버는 인증된 요청이라 생각하여 개인 정보를 응답해줄 것이다.
  5. 그러고 나면 그 개인 정보를 해커가 빼돌릴 수 있게 된다. (이것이 바로 CSRF 공격이다.)

CORS 동작 원리

브라우저는 다른 Origin으로 요청을 보낼 때 Origin 헤더에 자신의 Origin을 설정하고, 서버로부터 응답을 받으면 응답의 Allow-Control-Allow-Origin헤더에 설정된 Origin의 목록에 요청의 Origin헤더 값이 포함되는지 검사한다.

이는 3가지로 구분이 가능하다.

단순 요청

조건이 매우 까다롭다. 하지만 이러한 조건을 만족하면 안전한 요청으로 취급되어 단 한번의 요청만을 전송한다.

메소드가 GET, HEAD, POST 중 하나여야 한다.
User Agent가 자동으로 설정한 헤더를 제외하면, 아래와 같은 헤더들만 사용할 수 있다.
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink (en-US)
Save-Data
Viewport-Width
Width

Content-Type 헤더에는 아래와 같은 값들만 설정할 수 있다.
application/x-www-form-urlencode
multipart/form-data
text/plain

요청에 사용된 XMLHttpRequestUpload 객체에는 이벤트 리스너가 등록되어 있지 않습니다. 이들은 XMLHttpRequest.upload 프로퍼티를 사용하여 접근합니다.

요청에 ReadableStream 객체가 사용되지 않습니다.

프리플라이트 요청

단순 요청의 범위에 벗어나는 요청의 경우실제 요청을 보내기 전에 프리플라이트 요청을 먼저 보내서 실제 요청이 전송하기에 안전한지 확인한다.

  • OPTIONS메서드를 사용한다.
  • Origin 헤더에 자신의 Origin을 설정한다.
  • Access-Control-Request-Method 헤더에 실제 요청에 사용할 메서드를 설정한다.
  • Access-Control-Request-Headers 헤더에 실제 요청에 사용할 헤더들을 설정한다.

서버의 응답은 다음과 같다

  • Access-Control-Allow-Origin 헤더에 허용되는 Origin들의 목록을 설정한다.
  • Access-Control-Allow-Methods 헤더에 허용되는 메서드들의 목록을 설정한다.
  • Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록을 설정한다.
  • Access-Control-Max-Age 헤더에 해당 프리플라이트 요청이 브라우저에 캐시 될 수 있는 시간을 초 단위로 설정한다.

이러한 응답을 받고 나면 브라우저는 정보를 자신이 전송한 요청과 비교하여 실제 요청의 안정성을 검사한다.

Credentialed request

인증 정보를 함께 보내야 하는 요청이다.
기본적으로 브라우저가 제공하는 비동기 리소스 요청 API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다.
요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 credentials옵션이다.

credentials옵션은 3가지 값을 사용할 수 있다.

  • same-origin : 같은 출처 간 요청에만 인증 정보를 담는다.
  • include : 모든 요청에 인증 정보를 담는다.
  • omit : 모든 요청에 인증 정보를 담지 않는다.

또한 credentialed request를 만족하려면 다음의 조건이 필요하다.
먼저 서버는 Access-Control-Allow-Origin에 *을 사용하지 않아야 한다.
또한 Access-Control-Allow-Headers에도 *을 사용하지 않아야 한다.
Access-Control-Allow-Methods 또한 *을 사용하지 않아야 한다.

profile
코린이

0개의 댓글