Content Security Policy (CSP)

Content Security Policy (CSP) - это дополнительный уровень безопасности, позволяющий распознавать и устранять определенные типы атак, таких как Cross Site Scripting (XSS) и атаки внедрения данных. Спектр применения этих атак включает, но не ограничивается кражей данных, подменой страниц и распространением зловредного ПО.

CSP разрабатывался с возможностью полной обратной совместимости (за исключением CSP version 2, в которой были намеренно определены некоторые противоречия блокирующие обратную совместимость; с деталями можно ознакомиться здесь, в пункте 1.1). Браузеры, которые не поддерживают CSP, все еще могут работать с серверами, которые поддерживают CSP, и наоборот: браузеры, в которых поддержка CSP отсутствует, будут ее игнорировать, продолжая работу в соответствии со стандартными правилами ограничения домена для загрузки контента. В случае, если сайт не предоставляет CSP-заголовки, браузеры, в свою очередь, будут использовать стандартные правила ограничения домена.

Для того чтобы включить CSP, необходимо настроить сервер так, чтобы в ответах он использовал HTTP-заголовок Content-Security-Policy (в различных примерах и документации можно встретить вариант заголовка X-Content-Security-Policy. Он является устаревшим и определять его не нужно).

В качестве альтернативы настройке сервера, вы можете сконфигурировать CSP с помощью элемента <meta>. Например, так: <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Угрозы

Межсайтовый скриптинг

Основная цель создания CSP заключается в устранении XSS атак и сборе данных о попытках. XSS атаки эксплуатируют доверие браузера к контенту полученному с сервера. Зловредные скрипты исполняются в браузере жертвы, поскольку браузер доверяет источнику, даже когда скрипт поставляется не оттуда, откуда кажется.

CSP дает возможность администраторам серверов снизить или полностью устранить вектора, по которым злоумышленники могут провести XSS, с помощью определения доменов, которые браузер клиента должен считать доверенными источниками исполняемых скриптов. В таком случае, браузер, совместимый с CSP, будет исполнять только те скрипты, которые были получены из списка разрешенных источников, и игнорировать прочие (в т.ч. встраиваемые скрипты и обработчики событий, указанные непосредственно в HTML-атрибутах).

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

Пакетный сниффинг

В дополнение к ограничению количества доверенных доменов, с которых разрешается получать контент, можно также ограничить список используемых протоколов; например (в идеале и это крайне желательно с точки зрения обеспечения безопасности), сервер может поставить ограничение на получение контента только по HTTPS. Завершенная стратегия защиты передачи данных должна включать в себя не только принуждение к использованию HTTPS, но также и пометку всех кук с помощью специального флага, а также перенаправление запросов с HTTP на HTTPS. Сайты также могут использовать Strict-Transport-Security HTTP-заголовок, чтобы обеспечить подключение к ним браузеров только по защищенному каналу.

Использование CSP

Настройка  CSP включает в себя добавление на страницу HTTP-заголовка Content-Security-Policy и его настройку в соответствии со списком доверенных источников, из которых пользователь может получать контент. Например, страница, на которой происходит загрука и отображение изображений может разрешать их получение из любых источников, но ограничить отправку данных формы конкретным адресом. При правильной настройке, Content Security Policy поможет защитить страницу от атак межсайтового скриптинга. Данная статья описывает как правильно настроить необходимые заголовки и примеры, как это сделать.

Определение политики

Вы можете начать настройку Content-Security-Policy с определения HTTP-заголовка и указания какую политику использовать:

Content-Security-Policy: policy

Где policy - это строка, содержащая директивы, описывающие вашу Content Security Policy.

Создание политики

Политика описывается с помощью специальных директив, каждая из которых отвечает за отдельный вид ресурсов или policy area. Политика обязательно должна содержать директиву default-src, которая будет использоваться для тех ресурсов, для которых не будет описано отдельных правил (полный список вы можете найти в описании директивы default-src). Для того чтобы предотвратить исполнение встраиваемых скриптов и заблокировать использование eval(), необходимо определить директиву default-src или script-src. Также использование директивы default-src или style-src позволит ограничить использование встраиваемых стилей как в style-атрибутах, так и в тэгах <style>.

Примеры: Распространённые случаи применения

В данном разделе приводятся наиболее распространенные сценарии использования CSP.

Пример 1

Вы хотите ограничить источники контента только исходным сервером (исключая поддомены)

Content-Security-Policy: default-src 'self'

Пример 2

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

Content-Security-Policy: default-src 'self' *.trusted.com

Пример 3

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

Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com

При такой настройке, весь контент доступен для получения только с исходного домена, со следующими исключениями:

  • Изображения могут быть получены из любого источника (источник - "*").
  • Другие медиа-файлы доступны только с media1.com и media2.com (но не с их поддоменов).
  • Имсполняемый код доступен только с userscripts.example.com.

Пример 4

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

Content-Security-Policy: default-src https://onlinebanking.jumbobank.com

При данной настройке сервер будет позволять загрузку страниц только по HTTPS и только из одного источника - onlinebanking.jumbobank.com.

Пример 5

Для просмотра писем в почтовом клиенте вы хотите разрешить использование HTML внутри письма, а также позволить загрузку изображений из любых источников, но запретить использование любого JavaScript-кода и прочий потенциально опасный контент.

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *

Заметьте, что в настройке политики отсутствует директива script-src; при такой настройке CSP при загрузке скриптов будут использоваться настройки, определяемые директивой default-src, следовательно все скрипты могут быть загружены только с исходного домена.

Тестирование настройки политики

Для облегчения развертывания можно настроить развертывание CSP в режиме report-only. Таким образом, политика не будет ограничивать загрузку, но будет сообщать обо всех нарушениях на указанный в заголовке URI. Кроме того, заголовок report-only может использоваться для тестирования новой политики без полноценного развертывания.

Для определения вашей политики вы можете использовать заголовок Content-Security-Policy-Report-Only следующим образом:

Content-Security-Policy-Report-Only: policy 

В случае, если оба заголовка (Content-Security-Policy-Report-Only и Content-Security-Policy) были определены одновременно в одном ответе сервера, обе политики будут обработаны. Политики, описанные в заголовке Content-Security-Policy будут применены, в то время как политики, описанные в заголовке Content-Security-Policy-Report-Only, создадут отчеты, но применены не будут.

Настройка отправки отчетов

По умолчанию, отправка отчетов не производится.  Для того чтобы включить отправку отчетов, необходимо в вашей политике определить директиву report-uri и указать как минимум один URI, куда будут направляться отчеты:

Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

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

Синтаксис отчета о происшествиях

Объект отчета в формате JSON содержит следующие поля:

blocked-uri
URI ресурса, заблокированного в соответствии с настройками политики. Если заблокированный адрес отличается от адреса страницы, то он будет сокращен до схемы, хоста и порта.
disposition
Принимает значения "enforce" или "reporting" в зависимости от того, какой заголовок используется Content-Security-Policy-Report-Only или Content-Security-Policy.
document-uri
URI страницы, на которой произошло нарушение.
effective-directive
Директива, исполнение которой привело к нарушению.
original-policy
Исходная политика, описываемая в заголовке Content-Security-Policy.
referrer
Реферер, который привел к нарушению.
script-sample
Первые 40 символов встроенного скрипта или стиля, спровоцировавшего нарушение.
status-code
The HTTP status code of the resource on which the global object was instantiated.
violated-directive
Директива, которая была нарушена.

Пример отчета о происшествии

Возьмём страницу, расположенную по адресу http://example.com/signup.html. Для неё используется следующая политика, запрещающая загрузку всего кроме CSS-файлов с cdn.example.com.
Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports
HTML-код страницы signup.html выглядит следующим образом:
<!DOCTYPE html>
<html>
  <head>
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    ... Content ...
  </body>
</html>
Можете заметить ошибку? CSS разрешено загружать только с cdn.example.com, в то время как веб-сайт пытается загрузить его используя основной домен (http://example.com). Браузер поддерживающий CSP отправит отчёт о нарушении политики в POST-запросе к http://example.com/_/csp-reports в момент обращения к странице (signup.html):
{
  "csp-report": {
    "document-uri": "http://example.com/signup.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
  }
}

Как видите, отчёт включает полный путь к ресурсу нарушающему политику в blocked-uri. Правда, это не всегда так. К примеру, когда signup.html попытается загрузить CSS с http://anothercdn.example.com/stylesheet.css, браузер не будет включать полный путь, а ограничится лишь доменом (http://anothercdn.example.com). Спецификация CSP поясняет это странное поведение. В целом, это делается для предотвращения утечек чувствительной информации о перекрестных ресурсах

Совместимость с браузерами

Update compatibility data on GitHub
КомпьютерыМобильные
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung Internet
Content-Security-PolicyChrome Полная поддержка 25
Полная поддержка 25
Полная поддержка 14
Альтернативное имя
Альтернативное имя Использует нестандартное имя: X-Webkit-CSP
Edge Полная поддержка 14Firefox Полная поддержка 23
Полная поддержка 23
Полная поддержка 4
Альтернативное имя
Альтернативное имя Использует нестандартное имя: X-Content-Security-Policy
IE Полная поддержка 10
Замечания Альтернативное имя
Полная поддержка 10
Замечания Альтернативное имя
Замечания Only supporting 'sandbox' directive.
Альтернативное имя Использует нестандартное имя: X-Content-Security-Policy
Opera Полная поддержка 15Safari Полная поддержка 7
Полная поддержка 7
Полная поддержка 6
Альтернативное имя
Альтернативное имя Использует нестандартное имя: X-Webkit-CSP
WebView Android Полная поддержка ДаChrome Android Полная поддержка ДаFirefox Android Полная поддержка 23Opera Android Полная поддержка ДаSafari iOS Полная поддержка 7.1
Полная поддержка 7.1
Полная поддержка 5.1
Замечания
Замечания X-Webkit-CSP
Samsung Internet Android Полная поддержка Да

Легенда

Полная поддержка  
Полная поддержка
Смотрите замечания реализации.
Смотрите замечания реализации.
Использует нестандартное имя.
Использует нестандартное имя.

Для некоторых версий Safari существует специфическая невсовместимость реализации CSP. Если установить заголовок Content Security Policy без заголовка Same Origin, то браузер начнет блокировать и создавать ложно-положительные отчеты о нарушении политики для всего контента, как с запрашеваемого источника, так и из внешних источников.

Смотрите также: