Статьи

Content Security Policy

8.03.2013

/

Ядром модели веб-безопасности является same origin policy. Политика разрешает коду, находящемуся на страницах одного сайта, доступ к данным этого сайта, но запрещает доступ к большинству методов и свойств для страниц на других сайтах. Таким образом, ресурсы оказываются изолированными друг от друга. В теории все замечательно, однако давно были найдены пути обмана системы.

Cross-site scripting (XSS) – пример атаки, которая обходит same origin policy, заставляя сайт отправлять вредоносный код вместе с легитимным. Одой из главных проблем, потворствующих атаке, является то, что браузер слепо доверяет всем данным, появляющимся на странице. И если атакующий преуспеет в данной атаке последствия могут быть очень серьезными: данные сессий пользователей скомпрометированы, информация, хранящаяся в секрете, оказывается в руках плохих парней. Мы, очевидно, хотели бы это предотвратить.

Эта статья об относительно новом защитном механизме, который способен значительно уменьшить риск XSS атаки в современных браузерах – Content Security Policy (CSP).

Главной проблемой, эксплуатируемой XSS – неспособность браузера отличить скрипт, который является частью вашего приложения, от скрипта, злонамеренно внедренного третьим лицом.

Вместо того чтобы доверять всему, что присылает сервер, CSP определяет HTTP-заголовок Content-Security-Policy, который позволяет формировать «белый список» источников контента и заставляет браузер обрабатывать данные только из этих источников. Даже если атакующему удастся найти брешь в нашей защите и внедрить скрипт, он не будет выполнен, если не соответствует заданному «белому списку».

Например, мы доверяем apis.google.com как поставщику кода, и также мы верим себе. Давайте определим политику, разрешающую выполнение скриптов только из этих двух источников:

Content-Security-Policy: script-src ‘self’ https://apis.google.com

Как вы, наверное, уже догадались, script-src – директива, определяющая доверенные источники javascript кода. Таким образом, браузеру будет разрешено загрузить и выполнить скрипт с https://apis.google.com, также как и с нашего домена.

При попытке получения скрипта из любого другого источника браузер выдаст ошибку, показанную на рисунке 1.

CSP

Рисунок 1 – Ошибка загрузки скрипта


Скрипты представляют собой наиболее очевидную угрозу безопасности, однако CSP включает в себя довольно богатое множество директив, управляющих ресурсами, которые может загружать страничка. Просмотрим оставшиеся директивы:

  • сonnect-src – указывает легитимные ресурсы для XMLHttpRequest, WebSocket and EventSource соединений;
  • font-src – задает разрешенные источники для загрузки шрифтов;
  • frame-src – определяет ресурсы, которые могут быть встроены в страницу как фреймы;
  • img-src – определяет ресурсы, с которых могут быть загружены изображения;
  • media-src – определяет ресурсы, с которых санкционированно получение аудио- и видео-файлов;
  • object-src – позволяет контролировать Flash и другие плагины;
  • style-src – аналог script-src для CSS.

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

Поведение по умолчанию можно изменить с помощью директивы default-src. Она задает поведение для всех директив, которые остались неопределенными. Например, если default-src установлен на https://mydomain.com, и style-src не определена, то загружать таблицы стилей мы сможем только с https://mydomain.com.

Мы можем использовать так много рассмотренных директив, сколько имеет смысл в конкретном приложении, просто перечисляя их в HTTP-заголовке и разделяя точкой с запятой. Например, у нас есть приложение, которое загружает все ресурсы c системы доставки контента https://cdn.example.com, также нам абсолютно не нужен контент во фреймах и медиаэлементы (аудио, видео), тогда наша политика может выглядеть так:

Content-Security-Policy: default-src https://cdn.example.net; frame-src 'none'; media-src 'none'

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

Разрешенные источники в каждой директиве также задаются довольно гибко и определяются по схеме (data:, https:). Можно указать только имя хоста (example.com, что соответствует любой схеме и любому порту) или полностью URI (https://example.com:443, что соответствует только 443 порту и HTTPS). Также возможно использование wildcard, но только в качестве схемы, порта, или пути до файла, например, *://*.example.com:* будет соответствовать всем поддоменам example.com (но не example.com самому) с любой схемой и портом.

Помимо этого доступно еще четыре ключевых слова для использования в качестве источника:

  • ‘none’ – означает пустое множество, не один URL не соответствует;
  • ‘self’ – соответствует хосту, с которого был загружен документ, включая URL схему и номер порта;
  • ‘unsafe-inline’ – разрешает встроенный в документ javascript и css;
  • ‘unsafe-eval’ – разрешает использование eval() и подобных ему методов.

Конец первой части. To be continued...


Использованные источники:

  1. http://www.w3.org/TR/CSP/
  2. http://www.html5rocks.com/en/tutorials/security/content-security-policy/
  3. https://developer.mozilla.org/en-US/docs/Security/CSP/Introducing_Content_Security_Policy