티스토리 뷰

반응형

단순 요청인 Simple Request와 프리플라이트 요청이라 불리는 Preflighted Request는 무슨 차이가 있을까?

Pre- 접두사가 붙은 것을 보아 미리 뭔가를 더 하겠다는 느낌을 받는다.

단순 요청과 프리플라이트 요청에 차이를 둔 이유와 

보안적으로는 어떤 부분이 다른지의 관점 위주로, 이번에는 간단하게 비교해서 정리한다.

 

 

가정

http://www.example.com에서 http://api.example.com으로 Ajax GET 요청을 통해 데이터를 받아온다.

 

🔊 Simple Request

  Request   Response
  GET /data HTTP/1.1

  Host: api.example.com
  Origin: http://www.example.com
  HTTP/1.1 200 OK

  Access-Control-Allow-Origin: http://www.example.com

https://www.bugbountyclub.com/pentestgym/view/60

> http://www.example.com은 자신의 도메인을 값으로 하는 Origin 헤더를 추가하여 Request한다.

> http://api.example.comAccess-Control-Allow-Origin 헤더(ACAO)를 추가하여 Response한다.

이는 요청된 데이터에 http://www.example.com이 접근하는 것을 허용하게 된다.

API가 공개 서버(개인정보 미포함, 접근제어 불필요)라면

ACAO를 *로 두어 무조건적으로 허용할 수 있다.

 

 

🔈 Preflighted Request

  Request   Response
  OPTIONS /data HTTP/1.1

  Host: api.example.com
  Origin: http://www.example.com 
  Access-Control-Request-Method: GET
  Access-Control-Request-Headers: X-Custom-Header
  HTTP/1.1 200 OK

  Access-Control-Allow-Origin: http://www.example.com
  Access-Control-Allow-Method: GET
  Access-Control-Allow-Headers: X-Custom-Header

https://www.bugbountyclub.com/pentestgym/view/60

> http://www.example.com은 위와 같이 OPTIONS 메서드(safe 메서드)로 요청을 일단 보낸다. api 서버에 GET 메서드와 커스텀 헤더를 사용해 Request 하겠다는 의미이다.

> http://api.example.comhttp://www.example.com이 이 GET 메서드와 커스텀 헤더를 사용할 수 있음(허용함)을 Response한다.

> 만약 서버에 이러한 CORS 헤더가 설정되어 있지 않으면 브라우저는 '이 서버는 이 요청을 허용하지 않는다.'고 간주하고 Request를 하지 않는다.

이렇듯 Preflighted Request는 Simple Request와 대조해 단순히 사전 합의 과정이 하나 더 있는 것이다.

API가 일부 공개 서버라면

ACAO, ACAM 등의 Response 헤더에 허용하고자 하는 조건을 명시한다.

 

 

어떤 경우에 어떤 요청이 사용될까?

그래서 어떨 때 Simple Request이고, 어떨 때 Preflighted Request가 사용될까? 😤

Preflighted Request가 왜 생겨났는지를 이해하려면 이 부분을 먼저 알아야 한다.

MDN을 참고하면 Simple Request에 대한 상세 조건이 설명되어 있다.

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS#%EB%8B%A8%EC%88%9C_%EC%9A%94%EC%B2%ADsimple_requests

 

교차 출처 리소스 공유 (CORS) - HTTP | MDN

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라

developer.mozilla.org

 

Preflighted Request를 trigger하지 않는(발생시키지 않는) 요청이 있는데,

그 요청의 의미가 바로 Simple Request나 다름없다.

즉 아래 메서드 중 하나여야 하며 && 헤더가 아래 종류만 존재하며 && etc 조건이 충족되어야 Simple Request 처리된다.

표로 주요한 부분만 정리해보았다.

메서드 헤더
  • GET
  • POST
  • HEAD

    예를 들어 Cross-site Request의 DELETE 메서드 요청은 Simple Request가 아닌 Preflighted Request로 처리한다.
  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

 

 

⭐ Preflighted Request는 왜 생겨났을까?

🔥 먼저 CORS는 SOP를 위한 완화, 예외 정책이라고 했었다.

즉 SOP가 생겨난 후 일정 기간이 지나고 CORS가 생겨난 것이다.

 

🔥 CORS spec이 생기기 전 레거시 서버들은 당연히 SOP 요청만 받을 수 있는 시대에 태어났는데,

서버들이 Cross-site 요청을 그냥 받게된다면 보안적으로 매우 위험하다고 보았다.

(이런 서버를 non-CORS-aware server라고 한다.)

CORS를 인식 가능하며 헤더 설정이 적절히 되어있는 서버에는 Preflighted Request에 대한 이점이 없다는 것을 의미하기도 한다. 굳이 Preflighted Request가 아니더라도 명시된 헤더 조건에 따라 허용하지 않을 수 있기 때문이다.

 

🔥 CORS는 브라우저(클라이언트 단) 구현 스펙이라고 하였다.

브라우저는 Preflighted Request를 통해 서버가 CORS를 인식하는지 미리 확인하여

레거시 서버에서 발생 가능한 보안 위협(서버 데이터의 변경, 서버에서의 실행)을 방어 및 보호하고자 하였다.

-> 발생 가능한 보안 위협이라는 것은 'Preflighted Request'가 없었다고 가정할 때, CORS 미지원 서버는 Cross-origin Request에 대해 대응할 정책이 없으므로 서버에 모든 요청을 받아들이게 된다는 것이다. 이를테면 원래는 Same-origin에서만 GET, POST, DELETE를 사용할 수 있었는데 이제는 Cross-origin에서도 해당 요청을 보낼 수 있는 브라우저 스펙이 생겨난 것이다. 다행히도 CORS 스펙의 draft에서 Preflighted Request를 같이 내놓음으로써, 브라우저는 위 '어떤 경우에 어떤 요청이 사용될까?'의 내용처럼 특정 조건에서는 Preflighted Request를 트리거하도록 하여, CORS 지원 및 미지원 서버에 모두 부정적 문제가 없도록 하였다.

 

 

오늘 작성한 내용은 이해하는 데에 오래 걸렸지만 

SOP, CORS, Simple Request, Preflighted Request를

각각 분리되지 않은 하나의 이어지는 개념으로 이해할 수 있어 뿌듯했다.

앞으로 취약점 진단 시 origin 헤더에 대한 부분을 좀 더 면밀하게 확인할 수 있을 것 같다.

 

반응형
댓글
반응형
Recent Post.
Recent Reply.
Thanks for comming.
오늘은
명이 방문했어요
어제는
명이 방문했어요