[공부]CORS 란?

allnight5·2023년 4월 7일
0

기술공부

목록 보기
19/33

목차
1. CORS 란?
2. CORS를 왜 사용하는가요?
3. CORS의 보안문제
4.CORS를 구현하는 방법
5.CORS에서 허용된 HTTP 9가지 요청 메서드
6.Simple Requests와Preflight Requests

1. CORS 란

목차로 이동
CORS는 Cross-Origin Resource Sharing의 약자로, 웹 브라우저에서 실행되는 JavaScript가 다른 도메인으로부터 리소스를 요청할 때 발생할 수 있는 보안 문제를 해결하는 방법입니다.

기본적으로 웹 브라우저는 보안상의 이유로 다른 도메인에서 가져온 리소스에 대한 접근을 제한합니다. 이것은 보안 상의 이유로 중요합니다. 그러나, 때로는 동일한 리소스를 다른 도메인에서 공유하고자 하는 경우가 있습니다. 이럴 때 CORS는 다른 도메인에서 자원에 접근할 수 있는 규칙을 제공합니다.

CORS는 일반적으로 HTTP 헤더를 사용하여 동작합니다. 예를 들어, Access-Control-Allow-Origin이라는 헤더를 사용하여 다른 도메인에서 리소스에 접근할 수 있는지 여부를 제어할 수 있습니다. 또한, Access-Control-Allow-Methods와 Access-Control-Allow-Headers와 같은 헤더를 사용하여 다른 도메인에서 요청할 수 있는 HTTP 메서드와 허용되는 헤더를 지정할 수 있습니다.

2. CORS를 왜 사용하는가요?

목차로 이동
CORS는 보안 상의 이유로 인해 브라우저에서 다른 도메인 간의 자원 공유를 제한하는 정책인 Same-Origin Policy(프로토콜, 호스트이름, 포트번호 가 같은지 확인)를 우회하기 위해 사용됩니다. 이를 통해 다른 출처의 서버에서 제공하는 리소스에 접근하고 데이터를 주고받을 수 있도록 합니다.

예를 들어, 웹 애플리케이션이 클라이언트와 서버 간에 AJAX 요청을 보내는 경우, 브라우저는 Same-Origin Policy에 따라 다른 도메인의 서버로부터 리소스를 받아올 수 없습니다. 이런 경우에 CORS를 사용하여 서로 다른 출처 간의 통신을 허용하도록 하여 이러한 문제를 해결할 수 있습니다.

3. CORS의 보안문제

목차로 이동
다른 출처에서 불러온 스크립트가 사용자 정보를 탈취하거나, CSRF(Cross-Site Request Forgery) 공격을 수행할 수 있습니다.

CORS에서 가장 큰 보안 문제는 CSRF(Cross-Site Request Forgery) 공격입니다.

CSRF 공격은 사용자가 자신의 의지와 무관하게 웹사이트에서 악성 요청을 보내는 것을 뜻합니다. 이를 방지하기 위해 브라우저는 쿠키와 같은 인증 정보를 요청과 함께 서버로 보내는데, 이 때 다른 출처의 웹사이트에서 요청을 보내면 보안상 문제가 발생할 수 있습니다.

CSRF 공격 예시로
사용자가 은행 계좌 이체를 위한 페이지에 로그인한 상태에서 악의적인 공격자가 메일이나 웹페이지에서 만든 피싱 링크를 클릭하게 하여 은행 계좌 이체를 위한 요청을 위조하는 경우를 생각해 볼 수 있습니다. 이렇게 위조된 요청은 해당 웹사이트에 이미 로그인한 상태이기 때문에 인증이 필요하지 않으며, 원래 사용자의 권한으로 요청이 수행됩니다.

CORS는 이러한 보안 문제를 해결하기 위해 추가적인 보안 메커니즘을 제공합니다. 예를 들어, 사전 요청(preflight request)을 통해 요청을 보내기 전에 서버로부터 액세스 권한을 확인하고, 브라우저는 액세스 권한이 없는 경우에는 해당 요청을 차단합니다. 이를 통해 CSRF 공격을 예방할 수 있습니다.

서버쪽에서 CSRF를 막는방법들

CSRF 토큰 사용: 서버는 사용자가 보내는 모든 요청에 대해 랜덤하게 생성한 토큰을 추가하고 이 토큰은 사용자의 세션에 저장되어 있어야 하며, 서버는 요청을 받을 때마다 해당 토큰과 사용자 세션에 저장된 토큰을 비교하는데 만약 두 토큰이 일치하지 않으면 요청을 거부합니다.

SameSite 쿠키 사용: SameSite 쿠키를 사용하면 브라우저는 쿠키를 동일한 사이트에서만 보내도록 설정할 수 있으며 이 방법을 사용하면 공격자가 쿠키를 사용하여 요청을 위조하는 것을 방지할 수 있습니다.

HTTP Referer 검증: Referer 헤더를 검증하여 요청이 유효한 소스에서 온 것인지 확인할 수 있다. 그러나 Referer 헤더는 브라우저에서 수동으로 변경할 수 있으므로 이 방법은 완벽하지 않습니다.

Double Submit Cookies 패턴: CSRF 공격을 방지하기 위해 사용되는 패턴 중 하나로, CSRF 토큰을 쿠키에 저장하고, 이와 같은 CSRF 토큰을 요청의 쿼리 매개변수 또는 POST 데이터에도 포함시킵니다. 서버는 이 두 값이 일치하는지 확인하고, 다르다면 요청을 거부합니다.

CORS 설정: 서버에서는 적절한 CORS 설정을 통해 다른 도메인에서의 요청을 거부할 수 있습니다. 이 방법은 CSRF 공격을 완전히 방지하지는 않지만, 이를 어렵게 만듭니다.

4. CORS를 구현하는 방법

목차로 이동
CORS를 구현하는 방법에는 크게 두 가지가 있습니다.

서버 측에서 설정하기
서버에서 Access-Control-Allow-Origin 헤더를 설정하여 CORS를 구현할 수 있습니다. 이 헤더는 특정 출처(Origin)의 요청을 허용하도록 서버에 지시하는 역할을 합니다. 예를 들어, 모든 출처에서의 요청을 허용하려면 다음과 같이 헤더를 설정할 수 있습니다.

Access-Control-Allow-Origin: *

또한, 다른 CORS 관련 헤더인 Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials 등을 설정할 수 있습니다.

프록시 서버 사용하기
서버 측에서 CORS를 구현하는 것이 어려운 경우, 클라이언트 측에서 프록시 서버를 사용하여 CORS를 우회할 수 있습니다. 이 방법은 클라이언트에서 프록시 서버로 요청을 보내고, 프록시 서버에서 실제 서버로 요청을 중계하는 방식으로 동작합니다. 이를 통해, 프록시 서버에서 CORS 관련 헤더를 설정하여 CORS를 구현할 수 있습니다.

프록시 서버를 사용하는 방법은 클라이언트와 서버 사이에 추가적인 네트워크 트래픽과 지연 시간을 초래할 수 있으므로, 가능한 서버 측에서 직접 CORS를 구현하는 것이 좋습니다.

5. CORS에서 허용된 HTTP 9가지 요청 메서드

목차로 이동

1.GET
2.POST
3.PUT
4.DELETE
5.HEAD
6.CONNECT
7.OPTIONS
8.TRACE

  1. GET: 리소스를 요청할 때 사용합니다. 주로 서버로부터 데이터를 요청할 때 사용되며, 요청 파라미터를 쿼리 문자열로 전달합니다. 예를 들어, 게시글 목록을 가져올 때 사용됩니다.

  2. HEAD: GET과 동일한 요청을 하지만, 서버는 응답 본문을 포함하지 않고 응답 헤더만을 반환합니다. 이 메서드는 서버에서 자세한 정보를 제공하기 전에 요청이 유효한지 확인할 때 사용됩니다. 예를 들어, 파일이 존재하는지 확인하는 경우에 사용됩니다.

  3. CONNECT: HTTP 프록시 서버와의 터널링을 위해 사용됩니다. HTTPS 프록시 서버와의 연결을 설정할 때도 사용됩니다.

  4. OPTIONS: 요청을 보내기 전에 지원되는 메소드 목록, 헤더 유형 및 지원되는 요청 페이로드의 형식을 확인하는 데 사용됩니다. 또한, CORS에서도 사전 요청(Preflight Request)에서 OPTIONS 메서드를 사용하여 액세스 권한을 부여할지 거부할지 결정합니다.

  5. TRACE: 원격 서버로 전송된 요청 메시지를 받은 서버가, 해당 요청 메시지를 그대로 클라이언트에게 회신하여, 전송된 요청 메시지를 디버깅하거나 테스트하는 데 사용됩니다. 하지만, TRACE 메서드는 보안상의 이유로 일반적으로 사용하지 않습니다.

6. Simple Requests와Preflight Requests

목차로 이동

Simple Request

브라우저가 서버로 보내는 요청 중 가장 간단한 형태의 요청입니다. HTTP 메서드 중 GET, HEAD, POST 중 하나를 사용하며, Content-Type 헤더 값으로 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나를 사용합니다.
브라우저는 이러한 요청에 대해 바로 서버로 요청을 보내고, 서버는 응답을 반환합니다.

Preflight Request

브라우저가 서버로 보내는 요청 중 Simple Request에 해당하지 않는 요청입니다.

  • 예를 들어, HTTP 메서드 중 PUT, DELETE, PATCH와 같은 메서드를 사용하거나,
  • Content-Type 헤더 값으로 application/json 등이 사용될 경우 Preflight Request가 발생합니다.
  1. 브라우저는 먼저 사전 요청(preflight request)을 보내어 서버에서 이 요청을 처리할 수 있는지 확인합니다.
  2. 사전 요청은 OPTIONS 메서드를 사용하며, Access-Control-Request-Method와 Access-Control-Request-Headers 헤더를 포함합니다.
  3. 서버는 이 요청을 받아들이고, 요청한 리소스에 대한 액세스 권한을 부여할지 거부할지에 대한 응답을 보냅니다.
  4. 브라우저는 이 응답을 받아들이고, 권한이 부여된 경우에만 요청한 리소스를 사용할 수 있게 됩니다.

다음과 같은 상황에서 사용된다.

  • 요청 헤더가 표준 헤더 외에 사용자 정의 헤더를 포함하는 경우
  • Content-Type 헤더가 application/json, application/xml, text/plain 외의 다른 값을 가지는 경우
  • 자격 증명(Credentials)을 사용하는 경우 (예 : withCredentials가 true로 설정된 경우)

Simple Requests와Preflight Requests의 차이점

Simple Request와 Preflight Request의 가장 큰 차이점은 요청을 보내는 방법과 서버의 응답을 받는 방식입니다.
Simple Request는 바로 서버로 요청을 보내기 때문에 서버의 응답을 기다리지 않습니다. 하지만, Preflight Request는 먼저 사전 요청을 보내어 서버의 응답을 받아야 하기 때문에 처리 속도가 느릴 수 있습니다. 또한, Preflight Request는 추가적인 요청을 보내므로 서버 부하가 더 크게 발생할 수 있습니다.

이해돕기

Content-Type 헤더를 설정하지 않았다면, 브라우저는 PUT 요청을 보내기 전에 사전 요청을 보내게 됩니다 그래서 content-Type을 설정해주지 않고 요청을 한다면 가능한지 물어 봐야하니 Preflight Request타입이 되는것이고 설정해 놓고 요청을 한다면 Simple Request이다

GET, HEAD, POST 같은 경우 없어도 Simple Request로 적용 된다.

! 주의하기 넣었다고 다 Simple Request는 아니다.

만약 content-Type에 사용자 정의를 넣고 보내주면 Preflight Request타입이 되고
일반적으로 제공 되는 content-Type 타입들

application/x-www-form-urlencoded, multipart/form-data, text/plain

이러한 것들이 들어 있다면 Simple Request다.

번외

Credentialed Request

CORS에서 Credential Request란, 브라우저에서 Ajax 요청을 할 때 요청에 대한 인증 정보를 함께 보내는 것을 의미합니다. 이는 서로 다른 도메인 간의 통신에서 보안을 강화하기 위해 추가된 기능 중 하나입니다.

만약 CORS 요청이 Credential Request를 포함한다면, 서버는 Access-Control-Allow-Credentials 헤더를 true로 설정하여, 브라우저가 인증 정보를 전송할 수 있도록 허용해야 합니다. 또한, Access-Control-Allow-Origin 헤더에는 요청을 보내는 도메인의 주소가 명시되어야 합니다.

장점

Credential Request가 Simple Request와 Preflight Request보다 보안성이 높다.

하지만 Credential Request는 쿠키와 같은 사용자 정보를 공유하므로, 해당 정보가 탈취될 경우 보안 위협이 될 수 있습니다

단점

취약성: Credential Request는 쿠키를 사용하여 인증 정보를 저장하고, 이 쿠키는 보통 브라우저에서 관리됩니다. 따라서 브라우저에서 쿠키가 유출되거나 탈취될 경우 보안 위협이 발생할 수 있습니다.

오버헤드: Credential Request는 모든 요청에 대해 인증 정보를 전송해야 하므로 오버헤드가 발생할 수 있습니다. 또한, 인증 정보가 변경될 때마다 새로운 토큰을 발급해야 하기 때문에 서버의 부하가 높아질 수 있습니다.

사용성: Credential Request는 사용자가 매번 로그인해야 하는 번거로움이 있을 수 있습니다. 특히, 세션이나 토큰이 만료될 경우에는 자주 로그인을 해야 하므로 사용성이 저하될 수 있습니다.

Preflight Request는 보안상의 이유로 사용되고 실제로는 대부분의 웹 사이트에서 Simple Request를 사용한다.

profile
공부기록하기

0개의 댓글