본문 바로가기
MAKESITE
무료 스캔 문의하기 로그인

점검 항목 · 보안

HSTS 헤더 미설정

다른 보안 헤더는 잘못 켜면 지우면 됩니다. 이것 하나만 브라우저가 기억하기 때문에, 켜는 방법보다 되돌리는 방법을 먼저 아셔야 합니다.

심각도 높음 보안 무료 스캔 판정 항목 /check/hsts

01DEFINITION

한 줄로 말하면

https 로 넘기는 리다이렉트를 걸어 두어도 첫 요청 한 번은 http 로 나갑니다. 그 한 번을 가로채는 것이 SSL 스트립 공격이고, HSTS 는 "이 도메인은 앞으로 https 로만 접속하라"를 브라우저에 기억시켜 그 틈을 없앱니다. 한 번 선언하면 지정한 기간 동안 되돌리기가 까다로우니, 모든 하위 경로가 https 에서 정상인지 확인하고 짧은 기간부터 올립니다.

02RISK

없으면 무슨 일이 생기나

방문자가 주소창에 도메인만 치면 브라우저는 관습적으로 http 로 먼저 요청을 보냅니다. 우리 서버가 그것을 https 로 넘겨 주니 결과적으로는 안전해 보이지만, 그 첫 왕복 한 번은 암호화 없이 나갔습니다. 공격자가 같은 네트워크에 있다면 그 요청을 가로채 자기 서버로 응답하고, 이후 방문자는 우리 사이트처럼 보이는 http 페이지를 계속 보게 됩니다. 이것이 SSL 스트립입니다.

이 공격이 무서운 이유는 방문자가 눈치챌 단서가 거의 없다는 데 있습니다. 자물쇠가 없다는 것 하나뿐인데, 화면 내용은 우리 사이트와 똑같고 주소도 우리 도메인입니다. 로그인 폼에 아이디와 비밀번호를 그대로 칩니다. HSTS 가 켜져 있었다면 브라우저는 http 요청 자체를 만들지 않았을 것이고, 가로챌 요청이 없으니 공격도 성립하지 않습니다.

03CHECK IT YOURSELF

직접 확인하는 방법

아래는 저희를 거치지 않고 지금 해 보실 수 있는 방법입니다. 결과를 저희에게 보내실 필요도 없습니다.

  1. 01
    응답 헤더를 본다

    https 로 요청해야 합니다. http 응답에 붙은 HSTS 헤더는 브라우저가 무시하도록 규격에 정해져 있습니다. max-age 값이 초 단위 기간이고, 31536000 이 1년입니다.

    $ curl -sI https://example.com/ | grep -i strict-transport
    strict-transport-security: max-age=31536000; includeSubDomains
  2. 02
    브라우저가 실제로 기억하고 있는지 본다

    크롬 주소창에 아래 내부 페이지를 열고 도메인을 조회하면 그 브라우저에 저장된 정책이 나옵니다. 헤더를 켠 뒤 실제로 적용됐는지 확인할 때 씁니다.

    chrome://net-internals/#hsts
  3. 03
    서브도메인까지 볼 것인지 정한다

    includeSubDomains 를 붙이면 모든 하위 도메인에도 같은 규칙이 걸립니다. 사내용으로만 쓰는 서브도메인이 http 로 돌고 있다면 그 순간 접속이 끊기므로, 붙이기 전에 하위 도메인 목록을 확인하십시오.

04HOW TO FIX

고치는 방법

서버 환경에 따라 적을 자리가 다릅니다. 아래는 가장 흔한 구성 기준이고, 적용 전에 현재 설정을 백업하십시오.

짧은 기간으로 먼저 켠다

5분이나 1시간처럼 짧게 시작합니다. 문제가 있으면 그 시간만 지나면 원상복구되기 때문에 안전합니다. 이 상태로 전 경로가 https 에서 정상인지 확인하십시오.

Header always set Strict-Transport-Security "max-age=300"
이상이 없으면 기간을 올린다

며칠 관찰한 뒤 1년으로 올립니다. 하위 도메인까지 확인이 끝났다면 includeSubDomains 를 함께 붙입니다.

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
nginx 에서는 always 를 빠뜨리지 않는다

add_header 에 always 를 붙이지 않으면 오류 응답에는 헤더가 붙지 않습니다. 404 페이지에서 정책이 갱신되지 않는 상태가 됩니다.

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
preload 는 마지막에, 그리고 신중하게

preload 목록에 등록하면 브라우저가 처음 방문하기 전부터 이 도메인을 https 전용으로 취급합니다. 가장 강한 형태지만 목록에서 빼는 데 몇 달이 걸리므로, 도메인 구조가 확정되고 모든 서브도메인이 https 로 도는 것이 확인된 뒤에만 하십시오.

주의. http 로 내보내는 HSTS 헤더는 브라우저가 무시합니다. 인증서가 없거나 443 이 준비되지 않은 상태에서 이 헤더만 먼저 켜는 것은 아무 효과가 없습니다. 순서는 인증서 발급, https 강제, 그다음이 HSTS 입니다.

05FAQ

자주 묻는 질문

https 강제 리다이렉트를 이미 걸었는데 왜 또 필요한가요

리다이렉트는 요청이 서버에 도착한 뒤에 동작합니다. 즉 첫 http 요청은 이미 네트워크를 지나간 뒤입니다. HSTS 는 브라우저가 요청을 보내기 전에 스스로 https 로 바꾸게 하므로, 가로챌 요청 자체가 생기지 않습니다. 두 설정은 겹치는 것이 아니라 다른 지점을 막습니다.

HSTS 를 켰다가 문제가 생기면 바로 끌 수 있나요

헤더를 지워도 이미 방문한 브라우저는 지정한 기간 동안 기억하고 있습니다. max-age 를 0 으로 내보내면 그 값을 받아 간 브라우저부터 해제되지만, 그동안 다시 방문하지 않은 사람에게는 옛 정책이 남아 있습니다. 그래서 짧은 기간부터 시작하는 것입니다.

includeSubDomains 는 꼭 붙여야 하나요

붙이는 쪽이 안전하지만 확인이 먼저입니다. 개발 서버, 사내 도구, 옛 서비스가 서브도메인에 http 로 남아 있는 경우가 많고, 이 옵션을 붙이면 그것들이 전부 접속 불가가 됩니다. 하위 도메인 목록을 먼저 정리하십시오.

preload 목록에 꼭 올려야 하나요

필수는 아닙니다. 일반 HSTS 만으로도 두 번째 방문부터는 보호되고, 실질적인 위험의 대부분이 사라집니다. preload 는 첫 방문까지 막아 주는 대신 되돌리기가 매우 어려우므로, 도메인 운영 방침이 확정된 사이트에서만 권합니다.
여기까지는 항목 일반론입니다. 무엇이고 왜 문제이며 어떻게 고치는지는 감출 이유가 없어 그대로 적었습니다. 리포트에 들어가는 것은 귀사 사이트에서 실제로 어떤 값이 나왔는지 — 어느 주소의 어느 응답인지, 그 환경에서 어떤 순서로 적용해야 하는지, 예상 공수가 얼마인지입니다. 이 페이지만 보고 직접 고치셔도 되고, 실제로 그러시라고 적어 두었습니다.

GET STARTED

내 사이트는
이 항목을 통과할까요

주소만 넣으시면 이 항목을 포함해 25가지를 판정해 점수와 실패 개수를 보여 드립니다. 로그인도, 소유 확인도 필요 없습니다 — 전부 밖에서 관찰만 하는 항목이기 때문입니다.