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

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

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

Отказано в выполнении встроенного script, поскольку оно нарушает следующую директиву политики безопасности содержимого

Отказано в загрузке script

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

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

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

  • ... разрешить несколько источников?
  • ... использовать разные директивы?
  • ... использовать несколько директив?
  • ... обрабатывать порты?
  • ... обрабатывать разные протоколы?
  • ... разрешить протокол file://?
  • ... использовать встроенные стили, скрипты и теги <style> и <script>?
  • ... allow eval()?

И наконец:

  1. Что означает 'self'?

Ответ 1

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' чтобы обозначить локальный хост, локальную файловую систему или что-либо на том же хосте. Это не означает ни одного из них. Это означает, что источники, которые имеют одну и ту же схему (протокол), один и тот же хост и тот же порт, что и файл, в котором определяется политика содержимого. Обслуживание вашего сайта через 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

Ответ 2

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/