Как работает Политика безопасности контента?

248

Я получаю кучу ошибок в консоли разработчика:

Отказался оценить строку

Отказался выполнять встроенный скрипт, поскольку он нарушает следующую директиву Content Security Policy

Отказался от загрузки скрипта

Отказался от загрузки таблицы стилей

О чем это все? Как работает Политика безопасности контента? Как мне использовать Content-Security-Policyзаголовок HTTP?

В частности, как ...

  1. ... разрешить несколько источников?
  2. ... использовать разные директивы?
  3. ... использовать несколько директив?
  4. ... обрабатывать порты?
  5. ... обрабатывать разные протоколы?
  6. ... разрешить file://протокол?
  7. ... использовать встроенные стили, сценарии и теги <style>и <script>?
  8. ... разрешить eval()?

И наконец:

  1. Что именно 'self'значит?
Schlaus
источник

Ответы:

557

Content-Security-PolicyМета-тег позволяет уменьшить риск XSS атак, позволяя определить , где ресурсы могут быть загружены из, предотвращая браузеры от загрузки данных из любых других мест. Это мешает злоумышленнику внедрить вредоносный код на ваш сайт.

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

Для краткости я не буду писать полный тег в каждом образце. Вместо этого я покажу только contentсвойство, поэтому пример, который говорит, content="default-src 'self'"означает следующее:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

1. Как разрешить несколько источников?

Вы можете просто перечислить ваши источники после директивы в виде списка, разделенного пробелами:

content="default-src 'self' https://example.com/js/"

Обратите внимание, что нет никаких кавычек вокруг параметров, кроме специальных , например 'self'. Кроме того, нет двоеточия (: после директивы ). Просто директива, затем разделенный пробелами список параметров.

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

https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js

Это, однако, не будет действительным:

http://example.com/js/file.js
^^^^ wrong protocol

https://example.com/file.js
                   ^^ above the specified path

2. Как использовать разные директивы, что они делают каждый?

Наиболее распространенные директивы:

  • default-src политика по умолчанию для загрузки JavaScript, изображений, CSS, шрифтов, запросов AJAX и т. д.
  • script-src определяет действительные источники для файлов JavaScript
  • style-src определяет действительные источники для CSS-файлов
  • img-src определяет действительные источники для изображений
  • connect-srcопределяет допустимые цели для XMLHttpRequest (AJAX), WebSockets или EventSource. Если предпринята попытка подключения к узлу, который здесь не разрешен, браузер выдаст 400ошибку

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

3. Как использовать несколько директив?

Вы определяете все свои директивы внутри одного мета-тега, заканчивая их точкой с запятой ( ;):

content="default-src 'self' https://example.com/js/; style-src 'self'"

4. Как обрабатывать порты?

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

content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"

Вышеуказанное приведет к:

https://ajax.googleapis.com:123
                           ^^^^ Not ok, wrong port

https://ajax.googleapis.com - OK

http://example.com/free/stuff/file.js
                 ^^ Not ok, only the port 123 is allowed

http://example.com:123/free/stuff/file.js - OK

Как я уже упоминал, вы также можете использовать звездочку, чтобы явно разрешить все порты:

content="default-src example.com:*"

5. Как обрабатывать разные протоколы?

По умолчанию разрешены только стандартные протоколы. Например, чтобы разрешить WebSockets, ws://вы должны разрешить это явно:

content="default-src 'self'; connect-src ws:; style-src 'self'"
                                         ^^^ web sockets are now allowed on all domains and ports

6. Как разрешить файловый протокол file://?

Если вы попытаетесь определить его как таковой, он не будет работать. Вместо этого вы позволите это с filesystemпараметром:

content="default-src filesystem"

7. Как использовать встроенные скрипты и определения стилей?

Если явно не разрешено, вы не можете использовать определения встроенного стиля, код внутри <script>тегов или в свойствах тегов, как onclick. Вы позволяете им так:

content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"

Вам также необходимо явно разрешить встроенные изображения в кодировке base64:

content="img-src data:"

8. Как разрешить eval()?

Я уверен, что многие скажут, что вы этого не сделаете, поскольку «eval is evil» и наиболее вероятная причина наступающего конца света. Эти люди будут неправы. Конечно, вы можете определенно пробить основные дыры в безопасности вашего сайта с помощью eval, но он имеет вполне допустимые варианты использования. Вы просто должны быть умны в использовании. Вы позволяете это так:

content="script-src 'unsafe-eval'"

9. Что именно 'self'означает?

Вы могли бы взять 'self' в виду localhost, локальную файловую систему или что-то на одном хосте. Это не значит, что-либо из этого. Это означает источники, которые имеют ту же схему (протокол), тот же хост и тот же порт, что и файл, в котором определена политика контента. Обслуживание вашего сайта по HTTP? Никаких https для вас тогда, если вы не определите это явно.

Я использовал 'self' в большинстве примеров, поскольку обычно имеет смысл включать его, но это ни в коем случае не обязательно. Оставьте это, если вам это не нужно.

Но подожди минутку! Разве я не могу просто использовать content="default-src *"и покончить с этим?

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

content="default-src * 'unsafe-inline' 'unsafe-eval'"

... но я верю, что ты не будешь.

Дальнейшее чтение:

http://content-security-policy.com

http://en.wikipedia.org/wiki/Content_Security_Policy

Schlaus
источник
6
Отличный пост. Одно: не очевидно, что происходит, когда указывается несколько директив; настройки style-src в примере 3 имеют приоритет над default-src? и т.д ...
track0
30
Итак, чтобы разрешить все, что угодно, содержание будетdefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Арнольд Роа
8
Важно знать, что content="default-src * 'unsafe-inline' 'unsafe-eval'"необходимо для работы некоторых приложений Angular.
Флангер001
2
@Mahesh Этот "блог" полон постов, скопированных с SO. Кажется маловероятным, что так много пользователей SO скопировали бы контент от неизвестного блоггера - я знаю, что я не сделал.
Шлаус
2
Краткое примечание относительно connect-srcпутей и путей: конечные косые черты обязательны, если вы хотите включить целый подпуть. Например: файл http://foo.com/files/bar.txtбудет заблокирован, если источник есть http://foo.com/files, но обслуживается, когда онhttp://foo.com/files/
Griddo
15

APACHE2 MOD_HEADERS

Вы также можете включить Apache2 mod_headers, в Fedora он уже включен по умолчанию, если вы используете Ubuntu / Debian, включите его так:

# First enable headers module for Apache2, 
# then restart the Apache2 service   
a2enmod headers
apache2 -k graceful

В Ubuntu / Debian вы можете настроить заголовки в файле /etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
# 
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

Примечание. Это нижняя часть файла, только последние 3 записи являются настройками CSP.

Первый параметр - это директива, второй - источники из белого списка. Я добавил аналитику Google и рекламный сервер, который у вас может быть. Кроме того, я обнаружил, что если у вас есть псевдонимы, например, www.example.com и example.com, настроенные в Apache2, вы должны также добавить их в белый список.

Встроенный код считается вредным, его следует избегать. Скопируйте все javascripts и css в отдельные файлы и добавьте их в белый список.

Пока вы это делаете, вы можете взглянуть на другие настройки заголовка и установить mod_security.

Дальнейшее чтение:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/

Эрик Хендрикс
источник
2
Я смог добавить те же директивы в мой файл .htaccess, поскольку у меня нет возможности редактировать конфигурации Apache на моем общем хосте. Я нашел отличные инструменты для настройки этих параметров на report-uri.io/home/tools .
Майкл Макгиннис,
Есть ли способ решить эту проблему с помощью Tomcat 7. Я пытался добавить фильтры и не работал.
Эльшан
0

Не забывайте о font-src, он работает так же, как и любой другой, но если вы используете шрифты, загруженные из других источников - обязательно добавьте его в метатег

Михаил Андрианов
источник