1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
---
title: Content Security Policy (CSP)
slug: Web/HTTP/CSP
tags:
- Безопасность
- Справка
translation_of: Web/HTTP/CSP
---
<div>{{HTTPSidebar}}</div>
<p class="summary"><strong>Content Security Policy</strong> ({{Glossary("CSP")}}) - это дополнительный уровень безопасности, позволяющий распознавать и устранять определённые типы атак, таких как Cross Site Scripting ({{Glossary("XSS")}}) и атаки внедрения данных. Спектр применения этих атак включает, но не ограничивается кражей данных, подменой страниц и распространением зловредного ПО.</p>
<p>CSP разрабатывался с возможностью полной обратной совместимости (за исключением CSP version 2, в которой были намеренно определены некоторые противоречия блокирующие обратную совместимость; с деталями можно ознакомиться <a href="https://www.w3.org/TR/CSP2">здесь</a>, в пункте 1.1). Браузеры, которые не поддерживают CSP, все ещё могут работать с серверами, которые поддерживают CSP, и наоборот: браузеры, в которых поддержка CSP отсутствует, будут её игнорировать, продолжая работу в соответствии со стандартными правилами ограничения домена для загрузки контента. В случае, если сайт не предоставляет CSP-заголовки, браузеры, в свою очередь, будут использовать стандартные <a href="/ru/docs/Web/Security/Same-origin_policy" title="En/Same origin policy for JavaScript">правила ограничения домена</a>.</p>
<p>Для того чтобы включить CSP, необходимо настроить сервер так, чтобы в ответах он использовал HTTP-заголовок {{HTTPHeader("Content-Security-Policy")}} (в различных примерах и документации можно встретить вариант заголовка <code>X-Content-Security-Policy</code>. Он является устаревшим и определять его не нужно).</p>
<p>В качестве альтернативы настройке сервера, вы можете сконфигурировать CSP с помощью элемента {{HTMLElement("meta")}}. Например, так: <code><meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';"></code></p>
<h2 id="Угрозы">Угрозы</h2>
<h3 id="Межсайтовый_скриптинг">Межсайтовый скриптинг</h3>
<p>Основная цель создания CSP заключается в устранении XSS-атак и сборе данных об их попытках. XSS-атаки используют доверие браузера к контенту, полученному с сервера. Зловредные скрипты исполняются в браузере жертвы, поскольку браузер доверяет источнику, даже когда скрипт поставляется не оттуда, откуда кажется.</p>
<p>CSP даёт возможность администраторам серверов снизить или полностью устранить вектора, по которым злоумышленники могут провести XSS, с помощью определения доменов, которые браузер клиента должен считать доверенными источниками исполняемых скриптов. В таком случае, браузер, совместимый с CSP, будет исполнять только те скрипты, которые были получены из списка разрешённых источников, и игнорировать прочие (в т.ч. встраиваемые скрипты и обработчики событий, указанные непосредственно в HTML-атрибутах).</p>
<p>В качестве крайней меры защиты, сайты, которые хотят запретить исполнение скриптов, могут настроить это поведение глобально, с помощью соответствующей опции.</p>
<h3 id="Пакетный_сниффинг">Пакетный сниффинг</h3>
<p>В дополнение к ограничению количества доверенных доменов, с которых разрешается получать контент, можно также ограничить список используемых протоколов; например (в идеале и это крайне желательно с точки зрения обеспечения безопасности), сервер может поставить ограничение на получение контента только по HTTPS. Завершённая стратегия защиты передачи данных должна включать в себя не только принуждение к использованию HTTPS, но также и пометку всех <a href="/ru/docs/Web/HTTP/%D0%9A%D1%83%D0%BA%D0%B8">кук с помощью специального флага</a>, а также перенаправление запросов с HTTP на HTTPS. Сайты также могут использовать {{HTTPHeader("Strict-Transport-Security")}} HTTP-заголовок, чтобы обеспечить подключение к ним браузеров только по защищённому каналу<strong>.</strong></p>
<h2 id="Использование_CSP">Использование CSP</h2>
<p>Настройка CSP включает в себя добавление на страницу HTTP-заголовка {{HTTPHeader("Content-Security-Policy")}} и его настройку в соответствии со списком доверенных источников, из которых пользователь может получать контент. Например, страница, на которой происходит загрузка и отображение изображений может разрешать их получение из любых источников, но ограничить отправку данных формы конкретным адресом. При правильной настройке, Content Security Policy поможет защитить страницу от атак межсайтового скриптинга. Данная статья описывает как правильно настроить необходимые заголовки и примеры, как это сделать.</p>
<h3 id="Определение_политики">Определение политики</h3>
<p>Вы можете начать настройку {{HTTPHeader("Content-Security-Policy")}} с определения HTTP-заголовка и указания какую политику использовать:</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: <em>policy</em></pre>
<p>Где policy - это строка, содержащая директивы, описывающие вашу Content Security Policy.</p>
<h3 id="Создание_политики">Создание политики</h3>
<p>Политика описывается с помощью специальных директив, каждая из которых отвечает за отдельный вид ресурсов или policy area. Политика обязательно должна содержать директиву {{CSP("default-src")}}, которая будет использоваться для тех ресурсов, для которых не будет описано отдельных правил (полный список вы можете найти в описании директивы {{CSP("default-src")}}). Для того чтобы предотвратить исполнение встраиваемых скриптов и заблокировать использование <code>eval()</code>, необходимо определить директиву {{CSP("default-src")}} или {{CSP("script-src")}}. Также использование директивы {{CSP("default-src")}} или {{CSP("style-src")}} позволит ограничить использование встраиваемых стилей как в <code>style</code>-атрибутах, так и в тэгах {{HTMLElement("style")}}.</p>
<h2 id="Примеры_Распространённые_случаи_применения">Примеры: Распространённые случаи применения</h2>
<p>В данном разделе приводятся наиболее распространённые сценарии использования CSP.</p>
<h3 id="Пример_1">Пример 1</h3>
<p>Вы хотите ограничить источники контента только исходным сервером (исключая поддомены)</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'self'</pre>
<h3 id="Пример_2">Пример 2</h3>
<p>Вы хотите разрешить получение контента с доверенного домена и всех его поддоменов (доверенный домен не обязательно должен совпадать с тем, на котором настраиваются CSP.)</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'self' *.trusted.com</pre>
<h3 id="Пример_3">Пример 3</h3>
<p>Вы хотите разрешить пользователям приложения вставлять в создаваемый ими контент картинки из любого источника, но при этом ограничить источники аудио- и видео-файлов списком доверенных провайдеров. Получение скриптов должно происходить только с конкретного сервера, содержащего доверенный код.</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com</pre>
<p>При такой настройке, весь контент доступен для получения только с исходного домена, со следующими исключениями:</p>
<ul>
<li>Изображения могут быть получены из любого источника (источник - "*").</li>
<li>Другие медиа-файлы доступны только с media1.com и media2.com (но не с их поддоменов).</li>
<li>Исполняемый код доступен только с userscripts.example.com.</li>
</ul>
<h3 id="Пример_4">Пример 4</h3>
<p>Вы хотите удостовериться, что весь получаемый контент для онлайн-банкинга идёт по SSL и атакующий не сможет обрабатывать запросы:</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src https://onlinebanking.jumbobank.com</pre>
<p>При данной настройке сервер будет позволять загрузку страниц только по HTTPS и только из одного источника - onlinebanking.jumbobank.com.</p>
<h3 id="Пример_5">Пример 5</h3>
<p>Для просмотра писем в почтовом клиенте вы хотите разрешить использование HTML внутри письма, а также позволить загрузку изображений из любых источников, но запретить использование любого JavaScript-кода и прочий потенциально опасный контент.</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *</pre>
<p>Заметьте, что в настройке политики отсутствует директива {{CSP("script-src")}}; при такой настройке CSP при загрузке скриптов будут использоваться настройки, определяемые директивой {{CSP("default-src")}}, следовательно все скрипты могут быть загружены только с исходного домена.</p>
<h2 id="Тестирование_настройки_политики">Тестирование настройки политики</h2>
<p>Для облегчения развёртывания можно настроить развёртывание CSP в режиме report-only. Таким образом, политика не будет ограничивать загрузку, но будет сообщать обо всех нарушениях на указанный в заголовке URI. Кроме того, заголовок report-only может использоваться для тестирования новой политики без полноценного развёртывания.</p>
<p>Для определения вашей политики вы можете использовать заголовок {{HTTPHeader("Content-Security-Policy-Report-Only")}} следующим образом:</p>
<pre class="syntaxbox notranslate">Content-Security-Policy-Report-Only: <em>policy</em> </pre>
<p>В случае, если оба заголовка ({{HTTPHeader("Content-Security-Policy-Report-Only")}} и {{HTTPHeader("Content-Security-Policy")}}) были определены одновременно в одном ответе сервера, обе политики будут обработаны. Политики, описанные в заголовке <code>Content-Security-Policy</code> будут применены, в то время как политики, описанные в заголовке <code>Content-Security-Policy-Report-Only</code>, создадут отчёты, но применены не будут.</p>
<h2 id="Настройка_отправки_отчётов">Настройка отправки отчётов</h2>
<p>По умолчанию, отправка отчётов не производится. Для того чтобы включить отправку отчётов, необходимо в вашей политике определить директиву {{CSP("report-uri")}} и указать как минимум один URI, куда будут направляться отчёты:</p>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi</pre>
<p>Кроме того, необходимо настроить свой сервер на получение этих отчётов; вы можете хранить и обрабатывать эти отчёты как считаете нужным.</p>
<h2 id="Синтаксис_отчёта_о_происшествиях">Синтаксис отчёта о происшествиях</h2>
<p>Объект отчёта в формате JSON содержит следующие поля:</p>
<dl>
<dt><code>blocked-uri</code></dt>
<dd>URI ресурса, заблокированного в соответствии с настройками политики. Если заблокированный адрес отличается от адреса страницы, то он будет сокращён до схемы, хоста и порта.</dd>
</dl>
<dl>
<dt><code>disposition</code></dt>
<dd>Принимает значения <code>"enforce"</code> или <code>"reporting"</code> в зависимости от того, какой заголовок используется {{HTTPHeader("Content-Security-Policy-Report-Only")}} или <code>Content-Security-Policy</code>.</dd>
<dt><code>document-uri</code></dt>
<dd>URI страницы, на которой произошло нарушение.</dd>
<dt><code>effective-directive</code></dt>
<dd>Директива, исполнение которой привело к нарушению.</dd>
<dt><code>original-policy</code></dt>
<dd>Исходная политика, описываемая в заголовке <code>Content-Security-Policy</code>.</dd>
<dt><code>referrer</code></dt>
<dd>Реферер, который привёл к нарушению.</dd>
<dt><code>script-sample</code></dt>
<dd>Первые 40 символов встроенного скрипта или стиля, спровоцировавшего нарушение.</dd>
<dt><code>status-code</code></dt>
<dd>The HTTP status code of the resource on which the global object was instantiated.</dd>
<dt><code>violated-directive</code></dt>
<dd>Директива, которая была нарушена.</dd>
</dl>
<h2 id="Пример_отчёта_о_происшествии">Пример отчёта о происшествии</h2>
<div>Возьмём страницу, расположенную по адресу <code><a class="external" href="http://example.com/signup.html" rel="freelink">http://example.com/signup.html</a></code>. Для неё используется следующая политика, запрещающая загрузку всего кроме CSS-файлов с <code>cdn.example.com</code>.</div>
<div>
<pre class="syntaxbox notranslate">Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports</pre>
</div>
<div>HTML-код страницы <code>signup.html</code> выглядит следующим образом:</div>
<pre class="brush: html notranslate"><!DOCTYPE html>
<html>
<head>
<title>Sign Up</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
... Content ...
</body>
</html></pre>
<div>Можете заметить ошибку? CSS разрешено загружать только с <code>cdn.example.com</code>, в то время как веб-сайт пытается загрузить его используя основной домен (<code>http://example.com</code>). Браузер поддерживающий CSP отправит отчёт о нарушении политики в POST-запросе к <code><a href="http://example.com/_/csp-reports" rel="freelink">http://example.com/_/csp-reports</a></code> в момент обращения к странице (<code>signup.html</code>):</div>
<pre class="notranslate">{
"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"
}
}</pre>
<p>Как видите, отчёт включает полный путь к ресурсу нарушающему политику в <code>blocked-uri</code>. Правда, это не всегда так. К примеру, когда <code>signup.html</code> попытается загрузить CSS с <a href="http://anothercdn.example.com/stylesheet.css"><code>http://anothercdn.example.com/stylesheet.css</code></a>, браузер <em>не </em>будет включать полный путь, а ограничится лишь доменом (<code>http://anothercdn.example.com</code>). Спецификация CSP <a href="http://www.w3.org/TR/CSP/#security-violation-reports">поясняет</a> это странное поведение. В целом, это делается для предотвращения утечек чувствительной информации о перекрёстных ресурсах</p>
<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
<p>{{Compat("http.headers.csp")}}</p>
<p>Для некоторых версий Safari существует специфическая несовместимость реализации CSP. Если установить заголовок Content Security Policy без заголовка Same Origin, то браузер начнёт блокировать и создавать ложно-положительные отчёты о нарушении политики для всего контента, как с запрашиваемого источника, так и из внешних источников.</p>
<p>Смотрите также:</p>
<ul>
<li>{{HTTPHeader("Content-Security-Policy")}}</li>
<li>{{HTTPHeader("Content-Security-Policy-Report-Only")}}</li>
<li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy">Content Security in WebExtensions</a></li>
<li>
<p><a href="/en-US/docs/Tools/GCLI/Display_security_and_privacy_policies">Display security and privacy policies In Firefox Developer Tools</a></p>
</li>
</ul>
|