[Web Server] Browser security, CORS
Browser security
CORS
Browser security
브라우저가 위협을 받는 이유는 브라우저가 자바스크립트를 구동하며, 자바스크립트로 할 수 있는 것들이 많기 때문이다.
XSS
- 클라이언트가 서버를 신뢰하기 때문에 발생하는 이슈.
- 서버가 Script 태그 사이에 코드를 넣고 (script injection) 브라우저로 보내면 브라우저는 그 코드를 실행하게 된다.
- 기본적인 XSS 공격은 브라우저에서 막아 준다.
CSRF
- 서버가 클라이언트를 신뢰하기 때문에 발생하는 이슈.
- 서버는 인증정보를 가지고 오면 믿는다. 사용자는 인증 정보를 가진 체로 해커의 링크를 누르면, 해커는 인증정보를 가로채서 서버에 요청을 보내 버린다.
CORS
Cross-Origin Resource Sharing
CORS 는 HTTP header 을 사용하는 메커니즘으로, 서로 다른 origin(서버) 간에 HTTP reqeust 가 가능하도록 해 주는 표준(standard)이다.
HTTP request 는 기본적으로 Cross-Site HTTP Request 가 가능하다. 이는
<img src="other-domain.com">
,
<script src="other-domain.com/script.js">
와 같이 웹 사이트가 다른 도메인에 존재하는 리소스(이미지, 스크립트)를 참조할 수 있음을 뜻한다.
하지만 보안상의 이유로 브라우저에서는 <script></script>
로 둘러쌓여 있는 스크립트에서 생성된 cross-origin HTTP request 를 제한하고 있다. 예를 들어 XMLHttpRequest 나 Fetch API 는 Same-Origin Policy 를 따르기 때문에 올바른 CORS Header 를 포함하지 않는 한 다른 origin 에 request 를 할 수 없다.
예를 들어 스크립트를 통해 사용자를 악성 사이트로 리디렉션해줄수도 있는데, 브라우저는 기본적으로 same-origin policy 이기 때문에 자동으로 차단된다.
때문에 서버 개발자는 CORS 를 이해하고 스펙을 따라 HTTP request 에 응답을 해야 한다.
옛날에는 한 웹사이트는 하나의 서버(back-server)만 사용했으나, 현대에 이르러 AJAX(React) 가 나오면서 front-server 를 사용하게 되어 2개의 서버를 사용하게 되었다. CORS 가 필요하게 되었다.
같은 서버의 기준
http://mozila.org:8080
Protocol(http
), domain(mozila.org
), port(8080
) 가 같으면 같은 서버(origin)다.
CORS 의 작동 방식
CORS 표준은 HTTP header 에 새로운 header 를 추가하여 서버가 자신의 정보를 사용할 수 있는 서버 목록을 가지도록 한다.
또한 CORS 표준은, 만약에 어떤 HTTP request 가 서버에 side effect 를 일으키는 요청이라면(주로 GET 이외의 요청), 해당 요청을 보내기 전에 브라우저가 "preflight" 이라는 요청을 먼저 보내도록 강제하고 있다.
이 요청의 이름은 OPTIONS
인데, 이 요청을 통해 서버에 어떤 HTTP 메소드를 요청을 보낼 수 있는지 물어보는 작업이다.
서버가 답을 보내주면, 그 이후에 실제 요청을 하게 된다.
또한 서버는 클라이언트에 요청에 인증(쿠키, HTTP 인증 등)이 포함되어야 하는지도 알려줄 수 있다.
만약에 서버가 요청을 허락하지 않으면 에러를 보내게 되는데, 보안상의 이유로 자바스크립트로 에러에 접근할 수 없게 만들었다. 코드상으로는 그냥 에러가 났다는 사실만을 알 수 있다.
에러의 디테일을 알고 싶다면 브라우저의 콘솔로 확인할 수 밖에 없다.
CORS 작동 시나리오
1. Simple requests
CORS preflight 요청이 일어나지 않는 요청을 심플 리퀘스트라고 한다. 다음 조건을 만족하면 간단한 리퀘스트가 된다:
method : GET
, HEAD
, POST
Content-Type : application/x-www-form-urlencoded
, multipart/form-data
, text/plain
다른것도 있는데 생략.
https://foo.example
라는 웹사이트(서버)가 https://bar.other
라는 서버에 요청을 보내면:
그럼 서버는 response 를 보내게 되는데, 헤더에
Access-Control-Allow-Origin: *
식의 헤더가 들어가있다.
위의 저 헤더의 뜻은 서버의 리소스를 모든 서버가 다 사용할 수 있다는 뜻이다. (*
는 모두의 뜻)
만약에 리소스의 접근을 제한하고 싶다면 *
대신에 url 을 넣어주면 된다.
2. Preflight requests
프리플라잇 리퀘스트는 브라우저가 먼저 OPTIONS
라는 메소드로 미리 리퀘스트를 날려서 앞으로 보낼 요청을 보내도 괜찮은지를 서버에게 물어보는 것이다. 만약 METHOD 나 Content-Type 이 위 심플 리퀘스트 조건에 만족하지 않으면 브라우저는 자동으로 프리플라이트를 요청을 보낸다.
아래 MDN 예제는 POST
, X-PINGOTHER
, Content-Type : application/xml
인 요청을 보내기 때문에 먼저 preflight 요청을 보내본다.
Access-Control-Allow-Origin: http://foo.example // 허용할 origin
Access-Control-Allow-Methods: POST, GET, OPTIONS // 허용할 method
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type // 허용할 header
Access-Control-Max-Age: 86400
// preflight request 를 cache 에 저장할 수 있는 시간 (단위: 초)
3. Request w/ credentials
later
Author And Source
이 문제에 관하여([Web Server] Browser security, CORS), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jhoryong/Web-Server-기초저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)