Простые политики безопасности контента для защиты от XSS-атак

 

За последние недели мы рассмотрели в блоге довольно много HTTP-заголовков, связанных с безопасностью, но главным из них должен быть Content-Security-Policy(CSP). Босс, как из-за уровня защиты, который он обеспечивает, так и, к сожалению, из-за сложности его правильной реализации с первого раза. Как и все правила управления трафиком flightPATH, о которых мы недавно говорили, мы сами используем их для защиты сайта edgeNEXUS и его посетителей.

Мы проделали тяжелую работу и почувствовали боль, так что Вам не придется этого делать, но нельзя отрицать, что перед реализацией необходимо немного подумать и спланировать. Однако оно того стоит. Концепция, лежащая в основе этого заголовка, довольно проста и в то же время мощна. В двух словах, с его помощью Вы определяете допустимое происхождение контента, который может быть загружен на Ваш сайт. Это обеспечивает надежную защиту от ряда атак с внедрением кода, распространенных во все более динамичном современном Интернете, таких как Cross Site Scripting (XSS) и Clickjacking.

Типы содержимого, которые можно контролировать, включают: JavaScript, CSS (да, CSS может быть опасен), HTML-фреймы, шрифты, изображения и встраиваемые объекты, такие как Java-апплеты. Здорово иметь столько возможностей, но именно здесь и возникают трудности. Современные веб-сайты (в том числе и наши) содержат множество типов контента из разных источников, и выявление и учет их всех в политике может оказаться довольно сложной задачей.

Прежде чем мы перейдем к этому, давайте рассмотрим элементы значения заголовка и то, как выглядит политика. Как Вы увидите, это, по сути, длинный список типов контента (в данном примере все они заканчиваются на -src) и разрешенных источников для каждого типа. Все это вместе называется директивами политики.

default-src “self” data:; script-src “self” “unsafe-inline”; connect-src “self”; img-src “self” data:; style-src “self” “unsafe-inline” data:; font-src “self” data:; child-src “self”

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

  • default-src — Значения по умолчанию для большинства (но не для всех) типов содержимого, если они не указаны позже
  • script-src — Разрешенные источники для скриптов (включая JavaScript)
  • connect-src — Разрешенные источники для соединений (такие как WebSockets и EventSource, используемые, например, в чат-приложениях)
  • img-src — Разрешенные источники для изображений
  • style-src — Разрешенные источники для CSS
  • font-src — Разрешенные источники для шрифтов
  • child-src — Разрешенные источники для фреймов и iframe

Эти типы содержимого и их значения отделяются друг от друга (разграничиваются) точкой с запятой. Каждый тип может иметь одно или несколько из следующих значений;

  • “none” — не разрешать этот тип содержимого
  • “self” — разрешите этот тип контента, если он исходит непосредственно с данного сайта (но не с поддоменов)
  • “unsafe-inline” — разрешить встроенный CSS и JavaScript (к сожалению, это очень часто встречается).
  • данные: — Разрешите встроенные источники данных (обычно используются для предоставления шрифтов и изображений в строке для повышения производительности)
  • https: — разрешайте этот тип содержимого только по HTTPS
  • “unsafe-eval” — разрешить разбор текста с использованием потенциально опасных методов, которые могут привести к выполнению кода
  • domain-name — разрешите этот тип содержимого, если он исходит от указанного domain-name (другими словами, удаленного домена) — этот параметр можно использовать несколько раз
  • * — любой домен

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

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

  • default-src “self” data: — Разрешить содержимое только с нашего собственного сайта, включая встроенные объекты
  • script-src “self” “unsafe-inline” — разрешить скрипты с нашего собственного сайта, включая встроенные.
  • connect-src “self” — разрешить соединения с/на наш собственный сайт
  • Данные img-src “self”: — разрешить изображения с нашего собственного сайта, включая встроенные
  • style-src “self” “unsafe-inline” data: — разрешить CSS с нашего собственного сайта, включая встроенные стили
  • font-src “self” data: — разрешить шрифты с нашего собственного сайта, включая встроенные

Полное значение заголовка достаточно короткое:

default-src “self” data:; script-src “self” “unsafe-inline”; connect-src “self”; img-src “self” data:; style-src “self” “unsafe-inline” data:; font-src “self” data:

Во-вторых, защищенный SSL/TLS сайт для выхода в Интернет, который использует Google Analytics (GA), встроенный CSS, шрифты и изображения, CSS с Вашего сайта и изображения с различных других сайтов. Давайте разберемся с тем, что нам нужно, по частям (это не очень отличается друг от друга);

  • default-src “self” data: https: — разрешить содержимое только с нашего собственного сайта, включая встроенные объекты, только по HTTPS
  • script-src “self” “unsafe-inline” https: — разрешить скрипты с нашего собственного сайта, включая встроенные, только по HTTPS
  • img-src “self” “unsafe-inline” \* https: — разрешить изображения с любого сайта, включая встроенные с нашего, только по HTTPS
  • style-src “self” “unsafe-inline” https: — разрешить CSS только с нашего собственного сайта, включая встроенные, только по HTTPS
  • font-src “self” “unsafe-inline” https: — разрешить шрифты только с нашего собственного сайта, включая встроенные, только по HTTPS

Добавьте все это вместе, и мы получим эту немного более длинную политику:

default-src “self” data: https:; script-src “self” “unsafe-inline” *.google-analytics.com https:; img-src “self” “unsafe-inline” * https:; style-src “self” “unsafe-inline” https:; font-src “self” “unsafe-inline” https:

Я бы сказал, что это довольно просто. В прошлом Google не был столь “дружелюбен” к CSP (значение этого заголовка раньше было как минимум в два раза длиннее), но, к счастью, в последнее время они добились больших успехов. Вы заметите, что нам не пришлось добавлять домен *.google-analytics.com в script-src в качестве значения типа содержимого, поскольку их код выполняется как встроенный скрипт.

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

Для тестирования и устранения неполадок я настоятельно рекомендую использовать Инструменты разработчика Google Chrome. Перейдите на нужный сайт, затем нажмите F12, щелкните Сеть, убедитесь, что галочка Отключить кэш установлена, а затем перезагрузите страницу. Любые ошибки будут четко выделены. Внизу этого блога приведен пример того, что Вы можете увидеть, если Ваша политика блокирует unsafe-inline и Вы используете Google Analytics; сообщения об ошибках очень полезны.

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

Как всегда, огромное преимущество использования балансировщика нагрузки заключается в том, что для защиты всех наших серверов (и сайтов) нам нужно сделать это только в одном центральном месте. Нам не нужно полагаться на разработчиков или перенастраивать веб-серверы. На балансировщик нагрузки edgeNEXUS мы просто импортируем шаблон автоматической конфигурации jetPACK и назначаем правило трафика flightPATH той виртуальной службе (службам), которую мы хотим защитить (после соответствующих изменений).

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

flightPATH — это динамический, основанный на событиях механизм правил, разработанный компанией edgeNEXUS для интеллектуального управления и маршрутизации сбалансированного по нагрузке IP-, HTTP- и HTTPS-трафика. Он очень настраиваемый и мощный, но при этом очень простой в использовании.

Если Вы хотите узнать больше, стоит ознакомиться с этими ссылками;

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

https://developer.mozilla.org/en/docs/Web/Security/CSP/CSP_policy_directives

http://content-security-policy.com/

https://www.clickintelligence.co.uk/header-response-checker/

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

About Donna Toomey