본문 바로가기
CS

CORS, CSRF

by 이건 뭐야 2024. 3. 4.

CORS

Cross Origin Resource Sharing - 웹페이지의 리소스가 다른 도메인(다른 출처)의 요청(공유)에 대한 허용/비허용 정책

 

출처(Origin)

Protocol Host Path Query String Fragment

 

 

브라우저에서는 보안적인 이유로 cross-origin HTTP 요청들을 제한한다. cross-origin 요청을 하려면 서버의 동의가 필요하다.

서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절한다. 이런 메커니즘은 HTTP-header를 이용해서 가능한 것인데 이것을 CORS라고 한다.

 

cross-origin (다음 중 한가지라도 다른 경우를 뜻한다.)

프로토콜 ex) http vs https
도메인 ex) domain.com vs other-domain.com
포트 번호 ex) 8080포트 vs 3000포트

 

 

다른 출처로 리소스를 요청할 때 SOP(Same-Origin Policy) 정책을 위반한 것이 되고, SOP의 예외 조항인 CORS 정책까지 지키지 않을 경우 아예 다른 출처의 리소스를 사용할 수 없게 된다.

 

출처가 다른 두 개의 어플리케이션이 마음대로 소통하는 환경은 굉장히 위험한 환경이다.

특히 웹에서 돌아가는 클라이언트 어플리케이션의 경우 사용자의 공격에 매우 취약하다. => 개발자의 도구를 열어도 DOM이 어떻게 작성되어 있는지, 어떤 서버와 통신하는지, 리소스의 출처 등의 정보를 열람할 수 있다.

 

이런 상황에서 다른 출처의 어플리케이션이 서로 통신하는 것에 대해 아무런 제약이 존재하지 않는다면, CSRF나 XSS(Cross-Site Scripting)와 같은 방법을 사용하여 기존 사이트와 완전히 동일하게 동작하도록 하여 악의적으로 사용자의 정보를 탈취하기 쉬워진다.

 

 

CORS 동작 방식

브라우저는 본 요청을 보내기 전 예비 요청을 먼저 보내고, 요청의 유효성을 검사한다.

 

 

기본 동작 방식

웹 클라이언트 어플리케이션이 다른 출처의 리소스를 요청할 때 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 요청 헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아 보낸다.

 

 

Preflight Request 방식

일반적으로 웹 애플리케이션을 개발할 때 가장 많이 마주친다.

브라우저는 요청을 한 번에 보내지 않고 예비 요청과 본 요청으로 나누어서 서버로 전송한다. 이때 브라우저가 본 요청을 보내기 전에 보내는 예비 요청을 Preflight라고 부르며, 이 예비 요청에는 HTTP 메서드 중 OPTIONS 메서드가 사용된다. 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 이 요청을 보내는 것이 안전한지 확인한다.

 

1. 자바스크립트의 fetch API를 사용하여 브라우저에게 리소스를 받아오라는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내주게 된다.

2. 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 허용 정책을 비교한 후, 이 요청을 보내는 것이 안전하다고 판단되면 같은 엔드포인트로 다시 본 요청을 보내게 된다. 이후 서버가 이 본 요청에 대한 응답을 하면 브라우저는 최종적으로 이 응답 데이터를 자바스크립트에게 넘겨준다.

 

 

Simple Request 방식

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

 

 

Credentialed Request 방식

인증된 요청을 사용하는 방법이다. CORS의 기본적인 방식보다는 다른 출처 간의 통신에서 보안을 강화하고 싶을 때 사용하는 방법이다.

 

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

옵션 값 설명
same-origin(기본값) 같은 출처 간 요청에만 인증 정보를 담을 수 있다.
include 모든 요청에 인증 정보를 담을 수 있다.
omit 모든 요청에 인증 정보를 담지 않는다.

 

 

CORS 해결 방법

Access-Control-Allow-Origin 세팅

Webpack Dev Server로 리버스 프록싱

 


 

CSRF

Cross Site Request Forgery - 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 하는 것

 

 

CSRF 공격을 위한 조건

1. 사용자는 보안이 취약한 서버로부터 이미 로그인되어 있는 상태여야 한다.

2. 쿠키 기반의 서버 세션 정보를 획득할 수 있어야 한다.

3. 공격자는 서버를 공격하기 위한 요청 방법에 대해 미리 파악하고 있어야 한다. 예상하지 못한 요청 매개변수가 없어야 한다.

 

 

위의 조건이 만족되어야 다음 과정을 통해 CSRF 공격을 할 수 있다.

 

 

CSRF 공격 방식

1. 사용자는 보안이 취약한 서버에 로그인한다.

2. 서버에 저장된 세션 정보를 사용할 수 있는 session ID가 사용자의 브라우저 쿠키에 저장된다.

3. 공격자는 사용자가 악성 스크립트 페이지를 누르도록 유도한다.

4. 사용자가 악성 스크립트가 작성된 페이지 접근 시 웹 브라우저에 의해 쿠키에 저장된 session ID와 함께 서버로 요청된다.

5. 서버는 쿠키에 담긴 session ID를 통해 해당 요청이 인증된 사용자로부터 온 것으로 판단하고 처리한다.

 

 

CSRF 대응 방법(사용자)

1. 의심이 되는 URL은 함부로 클릭하지 않고, 의심이 되는 메일을 열어보지 않는 것이 중요하다.

2. 자동 로그인 기능을 사용하지 않는 것이 좋다.

 

 

CSRF 대응 방법(사용자)

1. Referer 검증

HTTP 요청 헤더(request header) 정보에서 Referrer 정보를 확인한다. 보통의 경우 호스트(host)와 Referrer 값이 일치하므로 둘을 비교한다.

CSRF 공격의 대부분 Referrer 값에 대한 검증만으로도 많은 수의 공격을 방어할 수 있다. Java servlet을 사용한다면 intercepter 클래스를 만들어서 모든 요청에 대해 referer check 할 수 있도록 방어가 가능하다.

2. CAPTCHA 도입

3. CSRF 토큰 사용

 

 

 

 

 

참조

CORS는 왜 이렇게 우리를 힘들게 하는걸까? - Evans Library

CORS란 무엇인가? - 한윤석 님

CSRF란, CSRF 동작원리, CSRF 방어방법 - devscb 님

CSRF(Cross Site Request Forgery)란? - 티베트 모래여우 님

 

'CS' 카테고리의 다른 글

OSI 7계층  (1) 2024.04.12
CI/CD  (0) 2024.02.15
DevOps(데브옵스)  (0) 2024.02.13
Component(컴포넌트)  (1) 2024.02.11
Mock Data  (1) 2024.02.08