Перейти к содержимому

Почему редиректа с Http на Https недостаточно и как защищает Hsts

"У нас есть редирект с HTTP на HTTPS". Почему для некоторых клиентов этого недостаточно

Мы закрывали замечание аудитора: часть внутреннего сервиса по-прежнему отвечала на HTTP-запросы. Команда добавила перенаправление на HTTPS, проверила, что сервер возвращает код 301, и аудит посчитали пройденным.

Через несколько недель я снова открыл этот сервис и посмотрел на механизм внимательнее. Оказалось, что редирект не устраняет сам факт небезопасного обращения. Запрос по HTTP уже успевает уйти на сервер до того, как клиент получает ответ 301.

В таком запросе могут находиться путь, параметры, технические заголовки и Cookie. Сервер лишь отвечает: "теперь перейдите на HTTPS". Но содержимое первого запроса уже прошло по незашифрованному соединению.

Кто всё ещё обращается по HTTP

Можно предположить, что проблема возникает главным образом тогда, когда пользователь вручную вводит адрес сайта без указания протокола. Однако современные браузеры в большинстве случаев пытаются сразу открыть HTTPS. Chrome делает это автоматически уже несколько лет, аналогичное поведение реализовано в Firefox и Safari.

Тем не менее HTTP-запросы никуда не исчезли. Их могут отправлять:

- старые браузеры и устройства;
- командные утилиты вроде curl;
- скрипты и фоновые интеграции;
- встроенные браузерные компоненты мобильных приложений;
- старые закладки и ссылки с явно указанным `http://`;
- письма, инструкции и документация, где сохранился старый адрес;
- автоматические системы, настроенные на HTTP много лет назад;
- сценарии отката, когда HTTPS оказался недоступен.

Именно для таких случаев нужны HSTS и, при необходимости, предварительное включение домена в список браузеров.

Что может утечь через HTTP

Даже если сервер мгновенно возвращает 301, первый запрос всё равно может раскрыть значительный объём информации.

Полный URL

Наблюдатель в сети увидит не только домен, но и путь с параметрами. Адрес вроде `/orders/48213/invoice` может раскрывать номер заказа, тип документа, идентификатор клиента или характер операции.

Cookie без Secure

Cookie с флагом `Secure` браузер не отправляет по обычному HTTP. Если этот атрибут не установлен, сессионный идентификатор или другая чувствительная Cookie может попасть в открытый запрос.

Сам факт обращения

Домен виден сетевому наблюдателю и при HTTPS, однако по зашифрованному соединению путь, параметры и содержимое запроса скрыты. При HTTP раскрывается гораздо больше.

Подмена ответа

Проблема не ограничивается чтением данных. Открытый Wi-Fi, заражённый роутер или промежуточный узел могут перехватить запрос и вернуть собственную страницу вместо ответа сервера.

До установления TLS клиент ещё не может проверить подлинность ответа. Поэтому злоумышленник способен показать фальшивую форму авторизации, предложить вредоносный файл или перенаправить пользователя на похожий домен.

Как работает HSTS

Заголовок `Strict-Transport-Security` сообщает браузеру, что сайт необходимо открывать только через HTTPS. В нём указывается срок действия правила.

Например:

```http
Strict-Transport-Security: max-age=31536000
```

Значение `31536000` означает один год. После успешного подключения по HTTPS браузер сохраняет настройку и в дальнейшем самостоятельно заменяет HTTP на HTTPS ещё до отправки запроса.

В результате пользователь, набравший старый адрес, не отправляет открытый запрос: браузер сразу формирует защищённое обращение.

Однако HSTS начинает работать только после первого успешного HTTPS-визита. Если это новое устройство, другой браузер или профиль после очистки данных, правило ещё неизвестно клиенту. Поэтому первый контакт с сайтом остаётся уязвимым.

Почему важна директива includeSubDomains

Параметр `includeSubDomains` распространяет HSTS на дочерние домены:

```http
Strict-Transport-Security: max-age=31536000; includeSubDomains
```

Без этой директивы правило применяется только к конкретному хосту. Например, защита `example.com` не означает, что `mail.example.com` тоже работает исключительно через HTTPS.

Но включать `includeSubDomains` следует осторожно. Под действие политики попадут все поддомены, в том числе забытые, тестовые и те, которые будут созданы позднее. Если хотя бы один из них не поддерживает HTTPS, он может стать недоступным.

Перед активацией нужно составить полный перечень поддоменов, проверить сертификаты, настройки балансировщиков, CDN, API, панели администрирования и старые внутренние сервисы.

Что даёт preload

Предварительная загрузка решает проблему первого визита. Специальный список доменов встраивается непосредственно в браузеры, поэтому правило HTTPS известно клиенту заранее.

При обращении к домену из такого списка браузер не пытается открыть HTTP вообще. Даже на новом устройстве или после очистки локальных данных запрос сразу направляется по защищённому протоколу.

Для включения в список обычно требуются следующие условия:

- HTTPS работает на основном домене и всех нужных поддоменах;
- сервер возвращает HSTS с `max-age` не менее одного года;
- присутствует `includeSubDomains`;
- в заголовке указана директива `preload`;
- сертификат действителен и корректно обновляется;
- обращения к 80-му порту перенаправляются на HTTPS того же хоста;
- HTTP-версия не ведёт на другой домен и не использует нестандартную логику.

Последнее требование часто становится причиной отказа. Недостаточно просто отправить пользователя на HTTPS: перенаправление должно быть предсказуемым и соответствовать требованиям механизма.

Почему с preload не стоит торопиться

Предварительная загрузка - это не обычная настройка сервера, которую можно мгновенно отменить. Список распространяется вместе с обновлениями браузеров. Поэтому после добавления домена изменения могут сохраняться у пользователей длительное время.

Если компания внезапно решит отказаться от HTTPS, перенести сервис на другой адрес или вернуть HTTP для старого поддомена, пользователи могут продолжать автоматически обращаться по HTTPS. Удаление домена из списка также требует отдельной процедуры и ожидания обновлений браузеров.

Перед подачей заявки необходимо убедиться, что:

1. все поддомены действительно поддерживают HTTPS;
2. сертификаты выпускаются и продлеваются автоматически;
3. старые устройства не являются критически важными клиентами;
4. нет интеграций, завязанных на HTTP;
5. тестовые и служебные домены не входят в область `includeSubDomains`;
6. редиректы не образуют циклы;
7. приложение корректно работает за прокси и балансировщиками;
8. внешние API и webhook-адреса также доступны по HTTPS.

Как проверить состояние домена

Статус домена в сервисе проверки предварительной загрузки обычно отображается одним из нескольких значений:

- `preloaded` - домен уже присутствует в списке;
- `pending` - заявка принята, но изменения ещё не попали в браузеры;
- `unknown` - домен отсутствует в списке.

Статус `pending` не означает, что защита уже работает для всех пользователей. Пока браузеры не получили обновлённый список, часть клиентов всё ещё может отправить первый HTTP-запрос.

Что проверить в инфраструктуре

Одной настройки заголовка недостаточно. Стоит отдельно проверить ответы всех виртуальных хостов, включая IPv4 и IPv6, балансировщики, CDN и резервные площадки.

Важно убедиться, что:

- HTTP не отдаёт содержимое страницы до редиректа;
- код перенаправления стабилен и не зависит от Cookie;
- HTTPS не содержит смешанного контента;
- все формы отправляют данные только на HTTPS;
- Cookie авторизации имеют флаги `Secure`, `HttpOnly` и подходящий `SameSite`;
- сертификат покрывает нужные имена;
- автоматическое продление сертификата не требует HTTP-доступа;
- мониторинг отслеживает ошибки TLS и срок действия сертификатов;
- документация и письма больше не содержат старых HTTP-ссылок.

Практический порядок перехода

Безопаснее двигаться поэтапно. Сначала следует включить HTTPS на всех сервисах, затем настроить корректные редиректы и проверить приложения. После этого можно отправлять HSTS с небольшим сроком действия, постепенно увеличивая `max-age`.

Когда инфраструктура стабильно работает, добавляют `includeSubDomains`. И только после длительного периода наблюдений стоит рассматривать preload.

Если домен уже предварительно загружен, быстрый откат невозможен. Обычно сначала убирают директиву `preload`, затем прекращают действие политики, подают запрос на исключение и ждут, пока изменения распространятся через обновления браузеров.

Главный вывод прост: редирект защищает дальнейший переход, но не первый запрос. HSTS закрывает уязвимость после первого успешного HTTPS-сеанса, а preload устраняет и это начальное окно. Однако цена ошибки при его включении высока, поэтому сначала нужно проверить всю доменную зону и связанные сервисы, а уже затем включать максимально строгий режим.

Прокрутить вверх