Оценка заголовков безопасности

Шесть коротких строк в ответе сервера говорят браузеру, насколько осторожно обращаться с вашей страницей. Эта проверка читает их, оценивает по шкале из 100 баллов и пишет за вас недостающие.

Или попробуйте github.com, wikipedia.org

Заголовки: это инструкции, а не содержимое

Каждый раз, когда браузер запрашивает страницу, сервер отвечает в двух частях. Вторая часть: это сама страница. Первая: список заголовков, коротких строк «имя и значение», которых посетитель никогда не видит, например тип файла, сколько его хранить в кэше и какие cookie сохранить.

Несколько таких строк: это инструкции по безопасности. Сервер от них не становится труднее взломать. Они включают защиту, которая уже встроена в каждый современный браузер и остаётся выключенной, пока сайт её не попросит. Сайт, который не отправляет ни одной из них, работает нормально. Он просто оставляет бесплатную броню в коробке.

Шесть заголовков, которые оценивает проверка

ЗаголовокБаллыЧто предотвращает
Strict-Transport-Security25Тихий перевод посетителя на незашифрованный http:// во враждебной сети Wi-Fi. После первого визита браузер отказывается от обычного HTTP для вашего домена на срок, указанный в max-age.
Content-Security-Policy25Внедрённые скрипты. Вы публикуете список мест, откуда можно загружать код, а всё остальное блокируется, даже если злоумышленнику удалось подсунуть тег <script> в комментарий или поле формы.
X-Frame-Options15Кликджекинг, когда другой сайт загружает ваш в невидимой рамке и обманом заставляет людей нажимать ваши кнопки. Современный аналог: frame-ancestors внутри CSP, и эта проверка тоже его принимает.
X-Content-Type-Options15Угадывание типа. С nosniff файл, загруженный как изображение, не может выполниться как скрипт только потому, что браузеру «показалось, что он похож на скрипт».
Referrer-Policy10Утечку полных адресов страниц, включая всё личное в URL, на каждый сайт, на который вы ссылаетесь.
Permissions-Policy10Запросы встроенного стороннего содержимого к камере, микрофону или местоположению от вашего имени.

Вес каждого заголовка зависит от того, какой ущерб он предотвращает. Два заголовка по 25 баллов останавливают атаки, которые действительно опустошают счета. Те, что по 10 баллов, касаются приватности и хороших манер.

Как читать оценку

Заголовок засчитывается полностью, только если его значение делает своё дело. В трёх случаях баллы засчитываются частично:

  • HSTS короче шести месяцев. max-age в один день годится на время тестов, но защищает вернувшихся посетителей всего один день.
  • CSP, разрешающая 'unsafe-inline' или 'unsafe-eval' без nonce или хешей. Это та самая дверь, которую политика должна была закрыть.
  • CSP в режиме Report-Only. Она наблюдает и сообщает, но пока ничего не блокирует. Это правильный первый шаг, если на нём не останавливаться.

Проверка также перечисляет каждый cookie, который устанавливает страница, и есть ли у него Secure, HttpOnly и SameSite. Эти флаги в оценку не входят, но cookie сессии без них сводит на нет многое из того, чего добиваются заголовки.

Оценка A здесь значит, что защита на стороне браузера включена для этого одного ответа. Она ничего не говорит о паролях, плагинах или обновлениях сервера. К тому же разные страницы одного сайта могут отправлять разные заголовки, поэтому проверяйте важные страницы: вход, оформление заказа, личный кабинет.

Где их добавить

Заголовки задаются там, где формируются ответы, и побеждает уровень, ближайший к посетителю:

CDN или прокси (Cloudflare, Fastly, пограничный узел хостинга)
Обычно это правило «заголовок ответа» или «трансформация» в панели управления. Одно правило покрывает весь сайт, включая кэшированные страницы.
Apache
В .htaccess или в виртуальном хосте: Header always set X-Content-Type-Options "nosniff". Слово always применяет его и к страницам ошибок.
nginx
add_header X-Content-Type-Options "nosniff" always; в блоке server. Одна ловушка: add_header внутри блока location заменяет заголовки уровнем выше, а не добавляется к ним.
Приложение
Фреймворки и плагины CMS умеют отправлять заголовки, но только на страницах, которые они генерируют. Статические файлы, которые веб-сервер отдаёт напрямую, останутся без них.

Начните с четырёх, которые ничего не могут сломать: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy и Permissions-Policy. Добавьте HSTS, когда все поддомены будут работать по HTTPS. Content-Security-Policy оставьте напоследок и сначала включите её в режиме report-only, потому что ошибочная CSP заблокирует ваши собственные скрипты.

Частые вопросы

Не сломают ли заголовки безопасности мой сайт?

Четыре из шести можно добавить не глядя. Осторожности требуют два: HSTS и Content-Security-Policy. HSTS привязывает посетителей к HTTPS на заданный срок, поэтому при includeSubDomains у каждого поддомена уже должен быть действительный сертификат. CSP блокирует всё, чего нет в вашем списке. Проверьте её через Content-Security-Policy-Report-Only в течение недели-двух, прежде чем включать всерьёз.

Помогают ли заголовки безопасности SEO?

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

Почему в списке нет X-XSS-Protection?

Браузеры убрали фильтр, которым он управлял. Chrome отказался от него в 2019 году, а в Firefox его никогда не было. Сейчас советуют не указывать его или ставить 0 и полагаться на Content-Security-Policy.

Какой max-age ставить для HSTS?

Обычная цель: один год (max-age=31536000), и это минимум для списков предзагрузки браузеров. Начните с нескольких минут, убедитесь, что ничего не сломалось, затем повышайте ступенями. Эта проверка ставит полный балл начиная с шести месяцев.

Мой сайт за Cloudflare. Чьи это заголовки?

Те, что получает посетитель, а важны именно они. Если ваш исходный сервер задаёт заголовок, а CDN его удаляет или переопределяет, оценка отражает версию CDN.