[Web] SOP와 CORS

Narcoker·2023년 6월 5일
0

Web

목록 보기
5/11

SOP(Same Origin Policy)

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

SOP의 탄생 배경

리소스에 접근하기 위해서 인증 토큰이 필요한 서버, target.com 이 있다고 가정하자.

해커는 사용자에게 서버의 리소스를 변조하는 스크립트가 담긴 링크, hack.com
사용자에게 이메일 등으로 보내 피싱한다.

사용자는 인증 토큰을 쿠키에 가지고 있는 상태에서 hack.com 링크를 클릭하게 된다면
target.com 의 리소스를 성공적으로 변조할 수 있을 것이다.

위 상황은 리소스를 가지고 있는 출처와 다른 출처에서 접근하는 상황이다.
SOP는 이와 같은 상황을 방지하기 위해 나온 보안 방식이다.

CSRF

용어 설명

출처(Origin)

URL 구조에서 Protocol, Host, Port를 합친 것을 말한다.

즉, 이 세 요소가 같아야, 같은 출처(Same Origin)라고 볼 수 있는 것이다.

URI, URL, URN

URI(Uniform Resourse Identifier)

인터넷 상의 리소스 자원 그 자체를 식별하는 문자열 시퀀스
URI 의 하위 개념으로 URL 과 URN 이 있다.

URI = 자원의 식별자

URL(Uniform Resource Locator)

네트워크 상에서 리소스의 위치를 나타내기 위한 규약이다.

URL = 자원의 위치

URN(Uniform Resourse Name)

리소스에 이름을 부여하는 것을 말한다.

예시

http://www.naver.com/index.html?page=1232950&id=776 를 살펴보자
http://www.naver.com/ 서버에 위치한 index.html 페이지는
query string인 page의 값에 따라 여러가지 화면 결과(자원)를 나타나게 된다.

따라서
자원의 위치를 나타내는 URLhttp://www.naver.com/index.html 까지가 되고
자원의 식별자를 나타내는 URIhttp://www.naver.com/index.html?page=1232950&id=776이 된다.

아래의 두 주소는 같은 URL 이면서 다른 URI 가 되는 것이다.
http://www.naver.com/index.html?page=1232950&id=776
http://www.naver.com/index.html?page=9923145&id=122

퀴즈

Q. http://localhost와 동일 출처인 것은?
1. https://localhost
2. http://locolhost:80
3. http://127.0.0.1
4. http://localhost/api/cors

Answer 2, 4

1 은 프로토콜이 다른다.
3 은 localhost의 ip 주소는 127.0.0.1 이니깐 맞긴하지만
브라우저에서 비교할때 String Value 로 비교를 해서 다른 출처라고 판단한다고 한다.

"localhost" == "127.0.0.1" ?? -> False!!!

CORS(Cross-Origin Resource Sharing)

추가 HTTP 헤더를 사용하여
내 리소스를 다른 출처에서 접근이 가능하도록 권한을 부여하고
이를 브라우저에게 알려주는 체제이다.

CORS 접근제어 시나리오

Preflight Request

OPTIONS 메서드를 통해 다른 도메인에 요청이 가능한지 확인하는 작업
요청이 가능하다는 응답을 받으면 그때 부터 실제 요청(ACTUAL REQUEST)을 보낸다.

위 그림은 preflight 요청을 보냈는데 권한이 없다고 응답이 온 경우이다.

Preflight Request

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

Preflight Response

  • Access-Control-Allow-Origin : 서버 측에서 허가한 다른 출처
  • Access-Control-Allow-Methods : 서버 측에서 허가한 메서드
  • Access-Control-Headers : 서버 측에서 허가한 헤더
  • Access-Control-Max-Age : Preflight 응답 캐시 시간, 초단위
    • 매번 Preflight 하는 것은 비효율적이기 때문에 빠른 요청을 위한 캐싱을 위함이다.
Preflight의 탄생 배경

CORS 가 나타나기 이전에 만들어진 서버들은
SOP(Same origin policy) request만 가능하다는 전제하에 만들어졌다.

CORS 가 나타나면서 보안적인 문제를 발생시킬 수 있게됐는데 이를 위함이다.

CORS 는 클라이언트에서만 나타나는 로그이다.
Preflight 가 없다면 허용하지 않은 다른 출처에서 서버의 리소스를 접근하는 요청을 보냈을 때
요청을 처리하면 안되는데 처리를 하고 CORS 관련 에러 상태 코드를 클라이언트로 보내게 된다.

이러한 이유로 Preflight가 탄생하게 되었다.

단순 요청(Simple Request)

Preflight 요청 없이 바로 요청을 보낸다.
Access-Control-Allow-Origin: *은 와일드 카드로 모든 다른 출처를 허용한다는 뜻이다.

조건

  • METHOD : GET, POST, HEAD 만 가능
  • Content-Type :
    application/x-www-form-urlencoded | multipart/form-data | text/plain 만 가능
  • Header : Accept | Accept-Language | Content-Language | Content-Type 만 가능

인증정보 포함 요청(Credentialed Request)

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

클라이언트 측
credentials: include

서버 측
Access-Control-Allow-Credentials : true
-> Access-Control-Allow-Origin: * 과 같이 쓰면 에러가 발생한다.

CORS 우회 및 허용 방법

우회

프론트 단에서 프록시 서버 설정(개발 환경)

react 라이브러리(0.2.3 이상)를 사용하는 경우,
package.json 에 "proxy": "http://localhost:8080" 를 추가한다.

허용방법

직접 헤더 설정

서버에서 CORS 허용

CORS 정책을 설정해줄 Controller에 @CrossOrigin 어노테이션을 활용한다.
모든 것을 허용하려면 모든 컨트롤러에 어노테이션을 써야한다.

참고

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글