HSTS(HTTP Strict Transport Security)로 HTTPS 강제하기

HSTS(HTTP Strict Transport Security)로 HTTPS 강제하기

HSTS란?

HSTS(HTTP Strict Tranport Security, RFC 6797)는 HTTP 대신 HTTPS만을 사용해 통신할 수 있도록 웹사이트가 브라우저에게 알리는 보안 기능입니다. 사용자가 실수로 HTTP protocol을 사용하여 웹사이트에 접속할 경우 생길 수 있는 보안 문제를 방지하기 위해 사용되며 최신 브라우저 대부분이 지원하고 있습니다. 쉽게 말하면, 웹사이트 접속 시 HTTPS만 사용하도록 강제하는 기술입니다.

HSTS를 사용하는 이유

대부분의 사용자는 편의를 위해 혹은 해당 웹사이트가 HTTPS를 지원하는지 알지 못하기 때문에 https:// 프로토콜을 입력하지 않고 www.example.com과 같이 도메인 이름만 주소창에 입력하여 접속을 시도합니다. 이 때 브라우저는 www 앞에 http://를 자동으로 추가하여 http://www.example.com으로 접속하고, 해당 도메인이 HTTPS만 지원한다면 웹서버는 "301 Redirect" 또는 "302 Redirect" 응답을 통해 웹브라우저로 하여금 HTTPS로 다시 접속하도록 지시합니다. 브라우저는 다시 https://www.example.com으로 연결되어 비로소 안전한 통신을 시작하게 됩니다.

하지만 처음 "http://"로 요청을 하는 과정에서 해커와 같은 공격자가 중간에 Proxy Server를 두고 통신 정보를 탈취할 수 있는 위험이 있습니다. 이러한 공격을 SSL Scripting 공격이라 부르는데, 사용자와는 HTTP 통신을 하고 실제 사이트와는 HTTPS 통신을 하여 HTTP 패킷을 캡쳐하고 Session ID, Cookie 등 민감한 데이터를 탈취하는 공격 방법입니다. HSTS는 이러한 SSL Scripting과 같은 공격을 방지하기 위한 목적으로 사용되고 있습니다.

SSL Scripting

image.png

HSTS List

웹브라우저는 HSTS가 적용된 웹사이트 리스트를 가지고 있기 때문에 한 번이라도 접속해야만 적용가능한 HSTS를 첫 방문부터 적용할 수 있습니다. 이 도메인 목록을 HSTS List라 하며 구글이 운영하는 hstspreload.org에 신청하면 Preloaded HSTS List로 등록되어 브라우저에 기본적으로 내장됩니다. 사용자가 직접 특정 도메인을 추가 및 삭제할 수도 있습니다. 크롬 브라우저의 경우 chrome://net-internals/#hsts에 접속하여 확인할 수 있습니다.

스크린샷 2022-11-14 오후 9.52.33.png

HSTS의 동작 방식

1. HSTS List에 포함된 경우

사용자가 주소창에 도메인 이름을 입력하거나 http://를 사용하여 주소를 입력하면 브라우저는 HSTS List를 확인하고, 리스트에 포함되어 있는 도메인은 https://를 사용하여 접속합니다.

2. HSTS List에 없지만 HSTS 기능이 설정된 경우

  1. HSTS List에 포함되지 않은 웹 사이트에 HTTP로 접속합니다.

  2. 301 Response를 통해 다시 HTTPS로 접속합니다.

  • Strict-Transport-Security 헤더가 없습니다.

  • HTTP는 안전한 프로토콜이 아니고 전달 중간에 응답이 변조될 수 있기 때문에 일반적으로 HSTS 응답헤더는 HTTPS 요청에 대해서만 설정합니다.

  1. 웹 서버는 HTTPS Reply Message에 HSTS Policy를 넣어서 보냅니다
  • Strict-Transport-Security 헤더를 볼 수 있습니다

  • HSTS를 지원하는 브라우저는 Strict-Transport-Security 헤더를 해석 및 적용하고 HSTS List를 구성합니다

  • Max Age, Subdomain 적용 여부, Preloaded List 추가 여부 값을 함께 전달합니다.

// HSTS response header Syntax
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload
  • max-age: 이 사이트가 HTTPS로만 접근되어야 한다고 기억되어야 하는 시간(초)

  • includeSubDomain: 모든 서브도메인 규칙 적용 여부

  • preload: 브라우저의 Preload List에 해당 도메인 추가 여부

  1. HSTS 응답 헤더를 받은 브라우저는 max-age 기간동안 HTTPS로만 접속하게 됩니다.

  2. HTTP로 접속 시도할 경우 307 internal redirect 응답을 통해 HTTPS가 적용된 페이지로 내부 재전송합니다.

  • 별도의 DNS 접속 없이, 외부 인터넷 접속 없이 HTTPS로 재전송합니다.

  • 즉, 보안적으로 위험한 브라우저와 웹서버 간 HTTP 통신이 아예 제거됩니다.

HSTS 기능을 사용하려면 웹 서버와 웹 브라우저 둘 다 기능을 지원해야하며 HSTS 기능을 지원하는 웹 서버를 HSTS enabled server라고 부릅니다. Strict-Transport-Security는 웹서버에서 응답해주는 헤더에 최초 포함되어 있기 때문에 웹서버에서 설정해주어야 합니다.

Nginx 적용 방법

다음과 같이 add_header를 추가한 후 재시작합니다.

add_header Strict-Transport-Security "max-age=63072000;";

AWS CloudFront 적용 방법

CloudFront > 동작 > 응답 헤더 정책 > SecurityHeadersPolicy 선택

스크린샷 2022-11-14 오후 10.17.49.png

HSTS List에도 등록되지 않았습니다.

스크린샷 2022-11-15 오전 4.52.45.png

스크린샷 2022-11-12 오후 4.19.01.png

HSTS List에도 추가되었습니다.

스크린샷 2022-11-15 오전 4.51.35.png

이후 접속은 307 internal redirect 응답을 통해 HTTPS가 적용된 페이지로 내부 재전송합니다.

스크린샷 2022-11-12 오후 5.04.27.png