웹개발/웹 개념

CORS (Cross-Origin Resource Sharing, 교차 출처 리소스 공유)와 SOP (Same-Origin Policy)란?

lukeit 2024. 8. 25. 20:52

CORS (Cross-Origin Resoruce Sharing)

  • WB에서 악의적인 웹 요청 (CSRF)에 대한 부분적 방어 정책
    • 부분적: 완벽하게 CSRF를 방어하지 못한다
      • WB에서만 유용하고 Application에서는 유용하지 않다
      • POST는 방어할 수 있는데 FORM 요청은 방어할 수 없다
      • CSRF (Cross Site Reequest Forgery, 사이트 간 요청 위조)
        • 타 사이트에 대한 의도하지 않은 요청
        • ex.) A 사이트의 유저가 의도하지 않았는데 B 사이트에 의도하지 않은 요청이 보내지는 것
        • 형태: JS실행을 통해 의도하지 않은 요청이 다른 서버에 전송된다
  • WB는 JS를 동작시키는 엔진을 가지고 있다 = 해커가 JS를 통해 다양한 공격이 가능하다!
    • 그래서 WB는 보안에 매우 예민할 수 밖에 없다
      • W3C (World Wide Web Consortium: develops standards and guidelines of Web)은 가장 먼저 SOP (Same-Origin Policy)라는 정책을 표준 도입하여 WB에서 단단하게 방어하도록 했다
      • API 호출을 아예 막아버렸다
        • 개발자들이 추가정책인 CORS을 도입하여 특정 조건하에서 API 호출을 자유롭게 하였다
  • "부분적 방어에 그친다, WB에서 방어할 수 잇는 방법이기 때문에 Native 앱에서는 방어가 불가능하여 토큰을 사용하여 AJAX가 아닌 FORM을 통한 POST요청을 할 시에 방어가 불가능하다."

Domain vs Origin vs Site

  • Domain: naver.com
  • Origin: https:://naver.com:8080
  • Site: admin.naver.com

AJAX (Asynchronous Javascript and XML, 비동기적 정보 교환 기법)

  • AJAX 를 통한 타 사이트 웹 서버에 대한 요청 방어를 위한 WB의 정책
  • 비동기 요청
    • 주고받을 때 XML을 사용한다
      • Rerendering이 필요하지 않다!
  • AJAX == XHR (XML 객체 반환 = 페이지 Rendering이 필요없다)
    • XHR (XMLHttpRequest): W3C 표준이 아니다
      • 화면이 없는 내장 Browser으로서, HTML문서를 받을 필요가 없고, 데이터를 XML로 주고받는다
      • 대부분의 주요 WB는 서버에 데이터를 요청(API)하기 위해 XHR를 사용한다

SOP (Same-Origin Policy)

  • 웹 브라우저에서 HTTP Resource를 가지고 오기 위한 모든 HTTP 요청은 기본적으로 SOP이다
    • WB는 SOP 정책을 가진다
    • WB는 이미지, 아이콘 같은 정보를 외부에서 가져오는 경우가 있다
  • SOP 정책은 부분적인 Cross-Origin을 허용한다
  • 3 가지 Cross-Origin 요청이 가능하다
    • 가져오기: 의도된 조회 = 서버 상태변경 불가
      • ex.) img tag, script tag, ...
    • 제출하기: 개발자가 설계한 의도된 제출 = 의도된 서버 상태 변경
      • ex.) FORM
    • 요청하기: 서버 상태 변경 가능 -> 이건 SOP에서도 안된다...
      • ex.) POST, DELETE,...: 서버 상태를 바꿀 수 있는 보안 위험성이 존재한다
      • 불가능한 요청이다
      • 하지만 API호출의 표준인 AJAX를 막으면 개발이 불가능하다 = AJAX는 필수다...!
        • 그래서 CORS라는 정책을 만들었다
          • AJAX에 대한 예외적 허용을 위한 추가 보안 정책
          • AJAX는 CORS 정책에 맞을 시에만 조건부 허용
      • WB에서 처리하는 것이기 때문에 Server - Server 통신시에는 CORS 이슈가 전혀 발생하지 않는다
        • ex.) React에서 CORS가 발생할시 Proxy 설정을 통해 서버끼리 통신하도록 만들면 CORS 해결이 가능하다!
          • "중간 서버를 두어 문제 (CSRF)를 방지한다"
          • WB -> Proxy Server (= Same Origin) -> WS (Server -> Server) = No Problem!
          • WB -> BFF (Backend-for-Frontend) = Same Orogin -> WS (Server -> ServeR) = No Problem
  • CORS 서버 측 적용 방법
    • "CORS는 WB 정책이다"
      • 하지만 설정은 Server에서 한다
        • Just like Cache and Cookie
      • CORS의 3가지 헤더 설정으로 WS는 WB의 어떤 요청만 허용하는지 호출가능 요청을 제약한다
        1. 허용된 Origin
          • (a) Origin을 브라우저가 요청할때 보낸다
          • (b) Access-Control-Allow-Origin을 서버가 응답할때 보낸다
          • WB가 a (브라우저가 보낸 요청) 과 b (서버가 보낸 결과)를 비교해 유효성을 검사한다
            • 유호성 검사: Origin 과 Access-Control-Allow-Origin이 동등한지 비교한다
              • 서버가 "설정"한걸로 브라우저가 "판단"한다
        2. 허용된 Method
          • ex.) GET, HEAD만 허용하고 POST, DELETE는 제외한다
          • Browser: Access-Control-Request-Method
          • Server: Access-Control-Allow-Method
          • WB가 두개를 비교해 유효성을 검증한다
        3. 허용된 Header
          • WB가 요청시 자격증명 Header전달을 허용한다
            • 자격증명: Cookie, Authorization Headers, 또는 TLS Client 인증을 위한 정보들
            • Browser: 자격증명 요청 시 allowCredentials = true 혹은 credentials:"include
              • 요청에 자격증명과 관련된 정보를 담을 수 있게 해주는 옵션이다
                • credentials: 최신 JS Fetch()를 활용한 API 호출 시
                • allowCredentials: 구식 JS
            • Server: 본 헤더 설정을 통해 자격 증명이 담긴 요청을 받을 수 있게 해주는 옵션
              • Access-Control-Allow-Credentials = true
              • 사용시 Access-Control-Allow-Origin 헤더의 제약이 존재한다
                • Spring Security에서 Access-Control-Allow-Origin='*'이 되면 안되는 강력한 제약 사항이 생긴다
                  • 제약 사항: *를 사용한다면 모든 Client에서 자격증명을 받을 수 있게 된다...
  • WS가 Allow-Origin 세팅을 통해 Response Header에 담아서 반환한다
    • WB는 Header를 받고 CORS 정책으로 요청의 결과를 쓸지 버릴지 고민한다
      • 즉, WS는 반환을 하고, WB가 CORS 정책에 의거, 반환된 값을 쓸지 말지 정한다

CORS 검증 방법

  • 두가지가 있다
    • Simple Request: 서버 상태 조회
      • 요청 (WB) -> (처리) -> 응답 (WS) -> 검증 (WB): 처리 후에 검증이 발생한다!
        • 서버 상태 조회 (Safe Method: GET, HEAD)면 상관 없다
        • 서버 상태 변경 (Non-Safe Method)면 처리 후에 검증이 의미가 없다!
          • 그래서 서버는 결과와 함께 CORS 헤더를 같이 보내준다
          • WB는 CORS 헤더가 요청에 부합하지 않으면 반환된 결과를 폐기한다
    • Preflight Request (OPTION Method): 서버 상태 변경
      • (요청(WB) -> 응답 (WS) = 조건부 요청 (검증의 목적)) -> 검증 (WB) -> 요청 (WB) -> (처리) -> 응답(WS)
        • 브라우저가 서버에게 임시 요청 (Preflight Request)를 보내면 서버는 CORS Header만 보내준다
          • WB는 CORS 헤더가 요청에 부합하지 않으면 원 요청을 보내지 않는다
반응형