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

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

Content-Security-Policy

Основной цель. этого заголовка - защита от XSS. Т.е. от выполнения любых скриптов и файлов вне зоны что вы указали. Например:

Content-Security-Policy: script-src 'self'; img-src *

Директива 'self' означает что выполнение скриптов ограничено только самим сайтом. Но можно добавить любые домены, которые вы считаете для своего сайта доверенными. По умолчанию, если этого заголовка нет, сайт выполняет любые скрипты, и если каким то образом злоумышленник сможет внедрить код (например через комментарий) то ничего не помешает развивать атаку.

Strict-Transport-Security

Заголовок отвечающий за безопасность соединения. Его наличие гарантирует что соединение с сайтом будет зашифровано HTTPS.

Strict-Transport-Security: max-age=

Это полезный заголовок который обязателен для приложений что получают/отправляют чувствительную информацию. Но если сервис внутренний или работает только по http то такой заголовок будет только мешать.

X-Frame-Options

X-Frame-Options: SAMEORIGIN

Ограничивает использование frame или iframe другими сайтами. Это помогает против ситуаций когда злоумышленник использует ваш сайт в окне поверх своего. Если хотите этого избежать лучше его использовать, или использовать директиву "frame-ancestors" в CSP:

Content-Security-Policy: frame-ancestors 'self';

Это тоже самое.

X-Content-Type-Options

Заголовок защиты от атаки MIME sniffing, это когда сайт отдает файл с одним расширением, а браузер обрабатывает его по-другому, например как скрипт.

X-Content-Type-Options: nosniff

Этот заголовок защищает от такого и прямо запрещает чтение MIME-типов браузером. В современных условиях этот вектор атаки не такой опасный, но если вы приняли решение его использовать, следует предварительно протестировать в безопасной среде, т.к. неправильное выставление этого заголовка может нарушить работу веб-приложения.

X-XSS-Protection

Современные браузеры не поддерживают. Ставить не рекомендуется, кроме совсем специфичных сценариев (например старый веб-интерфейс камеры, который работает только на internet explorer).

Referrer-Policy

Заголовок приватности, при переходе на другой сайт (например по ссылке рекламы) регулирует то что увидит последний сайт. Это домен, страница и иногда параметры что оставлены в URL. Советую его оставлять таким:

Referrer-Policy: no-referrer

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

Referrer-Policy: strict-origin-when-cross-origin

Permissions-Policy

Продвинутая настройка безопасности сайта. Через этот заголовок можно настраивать доступ к камере, микрофону, геолокации.

Permissions-Policy: camera=(), microphone=(), geolocation=(self), fullscreen=*

Очень полезный заголовок, расширяющий возможности защиты для конечных пользователей. Рекомендуется для крупных проектов с широкой пользовательской базой. Но не всеми браузерами поддерживается, на момент написания статьи в Firefox не работает.

CORS

Заголовки CORS - это отельная тема безопасности и конфиденциальности. Cross-Origin Resource Sharing - механизм безопасности, который регулирует как и какую информацию один ресурс может передавать другому. Без него возможна такая атака:

  1. Вы залогинены в своем банке bank.com. В браузере сохранены ваши Cookie (файлы сессии).
  2. Вы случайно заходите на злоумышленный сайт attacker.com (например, через спам-ссылку).
  3. На сайте attacker.com выполнятеся JavaScript-код, типа такого:
    fetch('https://bank.com', {
      method: 'POST',
      body: JSON.stringify({ amount: 1000, to: 'hacker-id' })
    });
  1. Если бы не было защиты: браузер отправил этот запрос вместе с вашими куками банка. Банк увидел родные куки и перевел деньги.

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

Access-Control-Allow-Origin: https://examlpe-app.com
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400

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

Cross-Origin-Resource-Policy

Это заголовок безопасности, который работает аналогично CORS или CSP, с той лишь разницей, что он блокирует даже сам факт загрузки ресурса. Это помогает против атак, которые могут обойти стандартную CSP политику через уязвимости памяти.

Cross-Origin-Resource-Policy: same-origin

Cross-Origin-Opener-Policy

Этот заголовок заставляет браузер разделить память между окнами и запустить их в разных изолированных процессах. Заголовок связан с механизмом Cross-Origin Isolation и что бы его обойти и нужен заголовок.

Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Embedder-Policy Заголовок что так же ограничивает загрузку контента для браузера пользователя но в связке с Cross-Origin-Resource-Policy.

Вариант заголовка когда запрещается загрузка всего, если это не указано в CORS или заголовке Cross-Origin-Resource-Policy.

Cross-Origin-Embedder-Policy: require-corp

Довольно полезный вариант заголовка который разрешает отправление всего, на браузер пользователя но без учетных данных и куки. Быстро и удобно.

Cross-Origin-Embedder-Policy: credentialless

Clear-Site-Data

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

Х-Permitted-Cross-Domain-Policies

Пример устаревшего заголовка что использовался для Flash. Некоторые сканеры могут показывать отсутствие подобных заголовков как проблему безопасности, чем по факту не является.

Вывод

Основная функция заголовков безопасности веб-приложений - это безопасность пользователей. Их установка не спасёт ваш сервер от SSRF или RCE. Злоумышленнику это никак не помешает, эти заголовки нужны только для того что бы защитить пользователей и (в редких случаях) межсервисное взаимодействие. Кроме того, следует понимать что заголовки безопасности это последний эшелон защиты, если вы установили и правильно настроили Content-Security-Policy это не значит что ваш сайт неуязвим к XSS. По факту, это просто рекомендуемая практика, мера предосторожности на случай если хакер сможет внедрить вредоносный код на страницу вашего сайта, но лучше этого вообще не допускать.

Регулярно обновлять CMS, зависимости, следовать практикам безопасности и экранировать пользовательские данные.

Как настраивать эти заголовки и надо-ли? Зависит от сайта:

  • Одностраничный сайт-визитка, статический сайт, любой сайт без взаимодействия с пользователем - можно не настраивать или настраивать в последнюю очередь
  • Небольшой сайт с личным кабинетом, сайт c аутентификацией во внутренней корпоративной сети, маленький интернет магазин - рекомендуется настроить хотя бы базовые заголовки (SCP, X-Frame-Options). Возможно, в вашем случае будет проще везде поставить SAMEORIGIN и реализовать загрузку всех ресурсов только с домена вашего сайта.
  • Веб-приложение сервис с чувствительными пользовательскими данными - настройка заголовков обязательна, CORS, документирование межсервисных взаимодействий и гранулированные настройки безопасности.