Как работает Политика безопасности контента?
Я получаю кучу ошибок в консоли разработчика:
Отказался оценить строку
Отказался выполнять встроенный скрипт, поскольку он нарушает следующую директиву Content Security Policy
Отказался от загрузки скрипта
Отказался от загрузки таблицы стилей
О чем это все? Как работает Политика безопасности контента? Как я могу использовать Content-Security-Policy
HTTP заголовок?
В частности, как...
- ... разрешить несколько источников?
- ... использовать разные директивы?
- ... использовать несколько директив?
- ... обрабатывать порты?
- ... обрабатывать разные протоколы?
- ...разрешать
file://
протокол? - ... использовать встроенные стили, сценарии и теги
<style>
а также<script>
? - ...разрешать
eval()
?
И наконец:
- Что именно делает
'self'
имею в виду?
3 ответа
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
определяет действительные источники для файлов JavaScriptstyle-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 - это зло" и наиболее вероятная причина наступающего конца света. Эти люди будут неправы. Конечно, вы можете определенно пробить основные дыры в безопасности вашего сайта с помощью eval, но он имеет вполне допустимые варианты использования. Вы просто должны быть умны в использовании. Вы позволяете это так:
content="script-src 'unsafe-eval'"
9. Что именно делает 'self'
имею в виду?
Вы могли бы взять 'self'
означать localhost, локальную файловую систему или что-нибудь на одном хосте. Это не значит ничего из этого. Это означает, что источники имеют ту же схему (протокол), тот же хост и тот же порт, что и файл, в котором определена политика контента. Обслуживание вашего сайта по HTTP? Никаких https для вас тогда, если вы не определите это явно.
Я использовал 'self'
в большинстве примеров, поскольку обычно имеет смысл включать его, но это ни в коем случае не обязательно. Оставьте это, если вам это не нужно.
Но подожди минутку! Я не могу просто использовать content="default-src *"
и покончим с этим?
Нет. В дополнение к очевидным уязвимостям безопасности, это также не будет работать так, как вы ожидаете. Хотя некоторые документы утверждают, что это разрешает все, это не так. Он не позволяет вставлять или убивать, поэтому, чтобы действительно сделать ваш сайт более уязвимым, вы должны использовать это:
content="default-src * 'unsafe-inline' 'unsafe-eval'"
... но я верю, что ты не будешь.
Дальнейшее чтение:
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/
Информация из исторических тем устарела, поэтому хочу обновить ...
Лучшие практики Content-Security-Policy в 2021 году:
1. Всегда начинайте со строгой политики планирования своего сайта.
Большинство разработчиков напрямую устанавливают Content-Security-Policy
http-заголовок, ломающий весь ваш сайт. Начните с использованияContent-Security-Policy-Report-Only
который будет имитировать блокировку и отправлять отчеты о нарушениях на ваш конечная точка.
2. Никогда не используйте тег для установки политики.
Обслуживание CSP через мета-заголовок html считается устаревшим и имеет некоторые недостатки с несколькими крайними случаями браузера. Настройка CSP только через HTTP-заголовки запроса.
Больше информации на
<head>
ошибки
3. Не пытайтесь реконструировать зависимости сторонних сервисов - вместо этого используйте CSP-пакеты Crowdsourced.
Большинство отчетов CSP, отправляемых на ваш report-uri, на самом деле не являются частью вашего кода, а являются частью служб, используемых вашим сайтом. Это может быть невозможно самостоятельно реконструировать, поэтому используйте пакеты CSP Crowdsourced , которые активно поддерживаются.
Добавление директив, необходимых вашей третьей стороне, приведет к:
- Уберите шум , предоставив вам возможность принимать решения только по фактическому пользовательскому коду на вашем сайте.
- Сэкономьте кучу денег на бесполезных запросах, так как большинство
report-uri
поставщики услуг взимают плату "за запрос" ...
4. Поддерживайте версии вашего CSP.
Без поддержки правильных версий очень сложно контролировать CSP в масштабе и понимать, какой CSP создал какой отчет. Подумайте о поддержке кода без надлежащего контроля версий ...
5. Применяйте постепенно, используя две отдельные политики!
Рекомендуется запускать несколько политик:
- Более строгая политика
Report-Only
режим (чтобы вы получали сообщения о подозрительных нарушениях и действовали соответственно. - Менее строгая политика, которая соблюдается и имеет меньше шансов взломать законные части вашего сайта.
6. Используйте хороший генератор CSP.
Используйте мощный генератор политик безопасности контента, такой как RapidSec, который поддерживает вышеуказанные требования, а также:
- Имеет плагины автоматического развертывания. Это позволит развернуть CSP из пользовательского интерфейса и передать копипасту. Пример Wordpress плагин СНТ, Node.js СНТ модуль
- Автоматическое определение пакетов. Чтобы вам не приходилось выбирать их вручную
- Обнаружение угроз / Аналитика. Разберитесь, какой из заблокированного контента является шумом, что интересно, а что критично.
Полное раскрытие информации: я связан с RapidSec, поэтому я все это знаю.
7. Повышайте уровень до Nonces.
Как только вы будете довольны своим CSP списка разрешений, вы можете инвестировать в дополнительную политику безопасности контента на основе nonce, которая должна работать как отдельный заголовок. Обратите внимание, что для этого потребуется рефакторинг кода, а иногда и настраиваемая обслуживающая инфраструктура (для генерации одноразовых номеров), поэтому рекомендуется начинать с одноразовых номеров, когда у вас уже есть подходящие политики для работы.
У службы безопасности Google есть отличные разговоры о CSP на основе nonce.