brunch

You can make anything
by writing

C.S.Lewis

by 테크유람 Mar 28. 2021

HTTPS를 강제하는 HSTS 사용하기

HSTS(HTTP Strict Transport Security)의 쓰임

최근에 개발된 웹 사이트들은 보안성을 위해 대부분 HTTPS를 사용하고 있습니다. 이제 HTTPS는 선택이 아니라 거의 강제(?)에 가까운 옵션이라 할 수 있습니다.


많은 브라우저들이 HTTP만을 지원하는 웹 사이트를 위험성이 있는 페이지로 표시하고, 검색 엔진 서비스 또한 HTTPS를 적용한 사이트를 우선 검색 결과에 노출하고 있습니다. 적잖은 가격으로 부담이 되었던 TLS/SSL 인증서는 Let's Encrypt와 같은 무료 인증서, AWS나 Cloudflare와 같은 클라우드 업체들이 제공하는 무료 인증서 등을 적용한다면 얼마든지 사용할 수 있게 되었습니다.


HTST는 무엇인가?

HSTS(HTTP Strict Transport Security, RFC 6797)는 웹 사이트 접속 시 HTTPS만 사용하도록 강제하는 기술입니다. HSTS가 적용된 웹 사이트의 웹 서버는 클라이언트에게 HTTPS만을 사용할 수 있음을 알려주고, HSTS를 지원하는 브라우저는 이를 해석하고 적용합니다.


대부분 최신 버전의 브라우저들은 모두 HSTS를 지원하고 있습니다.


<caniuse.com에서 HSTS 지원 여부 검색하기>


일반적인 HTTPS로의 접속 유도 방법

일반적인 브라우저 사용자들은 다음과 같은 방법으로 웹 사이트에 접속합니다.


① www.example.com을 주소창에 타이핑하고 엔터를 친다.

② 브라우저는 www 앞에 http://를 자동으로 붙이고 http://www.example.com 주소로 접속한다.

③ 웹 서버는 HTTP 접속에 대해 보통 301이나, 302 응답으로 HTTPS 사이트로 페이지를 재전송한다.

④ https://www.example.com로 접속하여 비로소 안전한 통신을 시작한다.


위의 과정 ①번에서 사용자는 이미 HTTP 접속 요청을 하였기 때문에 사용자와 같은 네트워크 상에서 사설 Proxy나 해킹 도구를 운영하는 해커들은 중간자 공격의 형태로 사용자의 HTTP 패킷을 몰래 캡처하고 Cookie, SessionID 등 사용자의 민감한 데이터를 엿볼 수 있습니다.


HTST를 적용하는 방법

HSTS를 적용한 도메인은 사용자가 처음으로 웹 서버에 접속할 때 응답 헤더에 Strict-Transport-Security라는 헤더를 내려보내고 HSTS를 지원하는 브라우저라면 추후 접속부터는 HTTPS로만 접속합니다.


Strict-Transport-Security 응답 헤더는 다음과 같이 설정합니다.

Strict-Transport-Security: max-age=<적용 주기> 
max-age값은 초(second) 단위 값으로 해당 시간 동안 HSTS 응답을 받은 웹 사이트에 대해 HTTPS 접속만을 허용한다는 의미

Strict-Transport-Security: max-age=<적용 주기>; includeSubDomains
HSTS가 해당 도메인의 서브 도메인에도 적용되고 있음을 알려줌

Strict-Transport-Security: max-age=<적용 주기>; preload
브라우저의 Preload List에 해당 도메인을 추가할 것을 알려줌


HSTS가 적용된 Facebook을 예제로 위의 내용을 살펴보겠습니다. 먼저 Facebook에 HTTP로 접속해 봅니다.


HSTS가 적용된 웹 사이트지만 HTTP로 접속하면 Strict-Transport-Security 헤더는 보이지 않고, 그냥 HTTPS가 적용된 페이지로 재전송하는 로직이 보일 뿐입니다. HTTP는 안전한 프로토콜이 아니고 전달 중간에 응답이 변조될 수 있기 때문에 일반적으로 HSTS 응답 헤더는 HTTPS 요청에 대해서만 설정합니다.


Facebook에 HTTPS로 접속하면, 예제의 마지막 라인처럼 Strict-Transport-Security 헤더를 볼 수 있습니다. 이 헤더가 바로 HSTS를 적용하겠다는 웹 서버의 응답 헤더이며, HSTS를 지원하는 브라우저는 이를 해석하고 적용합니다.


Strict-Transport-Security: max-age=15552000; preload


max-age란 HSTS를 언제까지 적용할 것인가에 대한 설정값입니다. Facebook은 15552000초로 설정되었네요. 180일(days)에 해당하는 값입니다. preload 지시자는 HSTS Preload List를 적용하겠다는 의미입니다.


이제부터 HSTS 응답 헤더를 받은 브라우저는 180일 동안 Facebook에 HTTPS로만 접속하게 됩니다. 만약 브라우저가 Facebook을 HTTP로 접속하려 한다면 브라우저는 다음과 같이 307 Internal Redirect 응답으로 HTTPS가 적용된 페이지로 내부(internal) 재전송합니다.


<HSTS 적용된 사이트에 HTTP 접속 시 307 응답 과정>

본래 307 응답은 Temporary Redirect 의미를 가지고 있습니다. 위 예제에서 Status Code 헤더와 Non-Authoritative-Reason 헤더의 값을 통해 HSTS 설정은 별도의 DNS 접속 없이, 외부 인터넷 접속 없이 HTTPS로 재전송을 함을 알 수 있습니다. 즉 보안적으로 위험한 브라우저와 웹 서버 간 HTTP 통신이 아예 제거되었습니다.


HTST Preload List란 무엇인가?

HSTS Preload List란 HSTS가 적용된 웹 사이트의 명단을 모아둔 리스트 정보입니다. 사이트 운영자는 자신이 운영하는 웹 사이트에 HTTPS 적용을 완료하고 HSTS Preload List에 등록할 수 있는 아래 가이드를 준수하면 자동으로 등록됩니다.


1. 유효한 SSL 인증서를 사용한다.

2. 80 포트를 사용한다면 HTTP 접속 시, 동일한 호스트의 HTTPS로 재전송되는 로직을 사용한다.

3. 모든 하위 도메인들도 HTTPS를 사용한다.
4. HTTPS 요청 시, HSTS 관련 헤더들은 다음 값을 준수한다.

max-age는 최소 31536000초(1년) 이상이어야 한다.

includeSubDomains 지시자가 정의되어야 한다.

preload 지시자가 정의되어야 한다.

HTTPS 사이트에서 또 다른 재전송 로직이 있다면 역시 HSTS 헤더 값이 있어야 한다.


HSTS Prelist List에 포함된 사이트들은 그 사이트를 처음 접속하는 브라우저라도, 즉 사전에 Strict-Transport-Security 응답 헤더를 받은 적이 없다 해도 HTTPS로만 접속합니다. 한 번이라도 접속해야만 적용 가능한 HSTS를 첫 방문부터 적용하여 HTTPS 만으로 접속하기 위해 만들어진 리스트입니다.


구글이 운영하는 hstspreload.org는 크롬(Chrome) 브라우저의 HTST Preload List를 서비스합니다. 여기에 등록된 사이트는 크롬 브라우저 내부에 하드 코딩(hard coded) 되어 HTTPS로만 접속 가능합니다. Safari, IE, Edge 브라우저들도 hstspreload.org에 기반한 HTST Preload List를 운영합니다.


hstspreload.org는 어떤 도메인이 리스트에 포함되었는지를 조회할 수 있는 기능을 제공합니다. 네이버(Naver.com)의 경우, HTST Preload List에는 포함되어 있지 않습니다.

<hstspreload.org에서 네이버를 검색한 화면>

리스트에는 없지만 서비스를 살펴보면, HSTS가 적용되어 관련 응답 헤더가 존재합니다. HSTS를 사용하지만 리스트 명부에는 없는 상태입니다.

$curl -v -https://www.naver.com/
...
< HTTP/1.1 200 OK
< Server: NWS
< Content-Type: text/html; charset=UTF-8
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< P3P: CP="CAO DSP CURa ADMa TAIa PSAa OUR LAW STP PHY ONL UNI PUR FIN COM NAV INT DEM STA PRE"
< X-Frame-Options: DENY
< X-XSS-Protection: 1; mode=block
< Strict-Transport-Security: max-age=63072000; includeSubdomains


네이버의 HSTS 적용 주기는 63072000초(730일)이며, includeSubdomains 옵션으로 naver.com의 서브 도메인들(예: cafe.naver.com, blog.naver.com,...)은 모두 HSTS 적용이 되도록 설정되어 있습니다.


HTST Preload List에 등록되지 않은 이유로는 http://naver.com 접속 시, https가 아닌, http://www.naver.com으로 페이지가 재전송되기 때문이라고 설명이 있습니다. 네이버 측은 이를 알면서도 HTST Preload List에 등록하지 않는 나름의 이유가 있을 것입니다.


실제로 HTST Preload List에 일단 등록이 되면, HTTPS 문제가 생기면 (SSL 인증서 만료 등) 지원 없이는 서비스에 아예 접속을 못하고, HTTP 프로토콜로 다운그레이드를 하려고 리스트에서 도메인을 삭제하는 것도 많은 시간이 걸리기 때문에 도메인 관리자는 List 등록 여부를 신중하게 결정해야 합니다.


Facebook은 HTST Preload List에 포함되어 있습니다.

<hstspreload.org에서 페이스북을 검색한 화면>


Akamai나 Cloudflare와 같은 CDN 서비스들은 브라우저 사용자들이 인터넷 네트워크상에서 접속하는 첫 번째 endpoint이기 때문에 HTTPS 적용이 매우 중요합니다. 따라서 쉽게 HSTS를 적용할 수 있는 기능을 제공하고 있습니다.

<Akamai의 HSTS 설정 메뉴>
<Cloudflare의 HSTS 설정 메뉴>


                                  직접 웹 사이트를 운영 중이고 HTTPS를 적용했지만, HSTS 혹은 HSTS Preload List를 아직 적용하지 않았다면 지금이라도 적용 여부를 고민해보시길 권고합니다.




브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari