Обход Content Security Policy
Content Security Policy (CSP) — это дополнительный механизм безопасности, встроенный в браузеры, позволяющий предотвращать Cross Site Scripting (XSS).
CSP позволяет определять белые списки источников для подключения JavaScript, стилей, изображений, фреймов, создания соединений. Также CSP может регулировать возможность исполнения inline-скриптов, возможность подключения текущей страницы во фрейме и т. д.
Рассмотрим различные конфигурации CSP и варианты для обхода ограничений.
В некоторых случаях в CSP разрешено выполнение инлайн-скриптов (директива unsafe-inline), и при этом заголовок Content-Security-Policy выставляется не на всех страницах (его выдаёт не балансировщик, а бекенд, или политика задаётся через тег meta). В таком случае можно открыть страницу, для которой политика не задана, и перезаписать её содержимое (см. https://xakep.ru/2018/10/01/xss-csp-bypass/). При этом, если директива frame-src ограничивает создание фреймов, придётся прибегнуть к созданию окна через window.open.
Рассмотрим различные варианты эксплуатации XSS, когда условия жёстче, и вышеупомянутый способ не работает.
Эксплуатация сводится к двум шагам: сначала нужно научиться выполнять произвольный код, а затем — получать нужные данные со страницы в браузере жертвы.
Исполнение кода
Рассмотрим некоторые распространённые способы обхода CSP для выполнения кода в зависимости от наличия или отсутствия в политике директив unsafe-inline и unsafe-eval.
Есть unsafe-inline
Content-Security-Policy: default-src ‘self’; script-src ‘self’ ‘unsafe-inline’ www.googletagmanager.com;
Inline-выполнение
С включенной политикой unsafe-inline мы без проблем можем исполнять код в тегах script.
Google Tag Manager
Иногда возникает необходимость собрать много информации, выполнив достаточно объёмный скрипт. Весь код может не помещаться в векторе, и в таком случае его нужно динамически подгрузить из какого-то источника.
В нашем случае можно посмотреть на политику и увидеть, что разрешено выполнение скриптов с домена www.googletagmanager.com. В этом сервисе можно сохранять пользовательский html, в который к нашему счастью можно вставлять свой JS-код. Учтите, что по умолчанию не поддерживается спецификация ECMAScript6.
Вставить свой код можно через добавление тегов. Например, попробуем добавить код с alert и встроить на сайте с настроенной политикой CSP.
Чтобы выполнился код из Tag Manager’а необходимо вставить блок:
Content Security Policy как настроить для WordPress да и везде
Что такое Content Security Policy
Иногда такой гадости не происходит, а плагин просто подменяет своим кодом рекламу на сайте. Банально вырезает ваш Adsense и ставит свой. Такого юзер вообще не замечает, владелец сайта может почувствовать некоторое падение дохода.
Также подмена контента на странице может осуществляется из-за вирусов, троянов, стороннего программного обеспечения, виджетов на сайте и т.д.
Ещё полезная ссылка на статью 2013 года в блоге Яндекса на Хабре. Там есть упоминания про утилиты для тестирования политик CSP, я их не пробовал, но возможно они вам пригодятся.
Как определить что вам нужно включить Content Security Policy
Проверьте в любой установленной у вас метрике наличие переходов с вашего сайта на сайты на которые переходов быть по определению не должно. Очень хорошо необходимость настройки Content Security Policy видно в метрике Live Internet. В Яндекс Метрике это не так очевидно ( что странно ).
Открываете статистику LI. Пункт переходы на сайты. Если вы видите здесь значительное количество переходов на совершенно левые сайты, то вам стоит задуматься о настройке CSP
Какие риски при неправильной настройке CSP
CSP запрещает сторонним скриптам менять содержимое страницы. Буквально вставлять код, картинки и прочее. Большинство современных сайтов используют у себя на сайте контекстную рекламу, счетчики, виджеты социальных кнопок, виджеты соцсетей, кнопки метрик, сторонние системы комментирования и многое другое. Если вы не правильно настроите Content Security Policy что-то из этого может перестать работать совсем или станет работать не так как ожидалось. Отловить некоторые баги порой очень сложно и не очевидно.
Также, в теории, может упасть или увеличиться, доход с контекстных сетей. Лично у меня он вообще не изменился. Но отзывы есть и о падении и о росте. По логике вещей он должен бы был расти. Ведь первое что делают плагины — это подменяют нашу рекламу.
В итоге если вы не уверены, что делаете, если левого трафика не много, возможно вообще не стоит всем этим заниматься.
Обратите внимание, то что делал я — хорошо работает в моем случае, как будет работать у вас я не знаю. Тут часто многое индивидуально. Я гарантий никаких не даю и ничего не обещаю. Вы всё делаете на свой страх и риск, ко мне без претензий.
Итак как настроить Content Security Policy
Суть настройки Content Security Policy это отправка браузеру посетителя необходимых http заголовков. Если браузер поддерживает эти заголовки, то он будет действовать в соответствии с политиками которые вы пропишите в этом заголовке. Сделать это можно различными способами.
Можно вообще описать заголовок Content-Security-Policy в meta вашей темы, но у этого способа есть серьезные ограничения. Этот способ настройки CSP я бы очень не рекомендовал.
Настройка CSP (Content Security Policy)
Браузеры пользователей часто заражены приложениями, которые подсовывают им во время сёрфинга по сайтам рекламу сомнительного характера (порно, казино, разводы на деньги и пр.). Несмотря на то, что это проблема со стороны пользователя, Яндекс может дать за это фильтр, понизив позиции или вовсе выкинув из индекса.
Даже если от поисковой системы мы санкции не получим, всё равно можем остаться в проигрыше, т.к. недополучаем деньги: наша реклама подменяется чужой рекламой. Симптомы такой проблемы выражаются внешними переходами по ссылкам, которых нет на ваших сайтах. Например:
Вообще эта проблема старая. Обсуждается давно на серче. Вот как всё начиналось.
Как с этим бороться? Использовать Content Security Policy! Ведь поставив CSP, мы можем еще и доход повысить, а не только предотвратить возможность схватить фильтр.
Алгоритм действий по настройке CSP:
Изучаем внешние источники
Сперва мы должны создать предварительное правило CSP для нашего сайта. Для этого нам нужно знать, какие именно внешние источники используются у нас на сайте.
Ознакомимся с директивами
Правило CSP состоит из директив:
Четыре ключевых слова, которые могут быть использованы в директивах (списке источников):
Далее, просмотрев код нашего сайта, мы начинаем создавать предварительное правило CSP.
Создаем тестовое правило CSP
Тестовое правило Content-Security-Policy для любого сайта будет выглядеть так:
Теперь подключаем наше правило.
Подключаем правило CSP к сайту
Существует несколько способов подключить правила CSP к сайту. Рассмотрим самые распространённые из них:
Вставляем в него следующий код:
Header set Content-Security-Policy «_____»
В коду между строчками и вставляем:
В файле functions.php после кода
Теперь начинается монотонный, немного нудный процесс поиска ошибок и их исправления. Для этого я использовал опять же Оперу (либо можно использовать плагин для ФФ — Firebug). Открываем консоль ошибок браузера (Ctrl+Shift+C) и наблюдаем такую картинку:
Дальше нам нужно перенести все заблокированные домены в соответствующую секцию нашего правила, как понятно из текста ошибки – это script-src. Вносим правки в правило, обновляем код и смотрим, что у нас получилось.
Часть ошибок пропала, но вылезли новые. Это связано с тем, что некоторые скрипты после того, как мы их разблокируем, могут подгружать дополнительные.
Как видно на скриншоте, ошибки связаны с unsafe-eval (использует наш jQuery) для script-src и секцией frame-src. Обновим наше правило.
Последняя ошибка связана с секцией connect-src, добавим данную секцию в наше правило и внесем домен mc.yandex.ru (можно просто *.yandex.ru).
Финальная версия нашего CSP
Ошибок может быть в разы больше, поэтому нужно ещё «походить» по сайту с открытой консолью и понаблюдать за возможными ошибками. Кроме того, проверить на ошибки лучше в нескольких браузерах, например, ещё в Google Chrome.
Результаты
Результат настройки CSP на одном моем сайте:
И вот результат моего коллеги:
Как видите, переходов на «левые» сайты теперь стало гораздо меньше
Content Security Policy (CSP)
CSP разрабатывался с возможностью полной обратной совместимости (за исключением CSP version 2, в которой были намеренно определены некоторые противоречия блокирующие обратную совместимость; с деталями можно ознакомиться здесь, в пункте 1.1). Браузеры, которые не поддерживают CSP, все ещё могут работать с серверами, которые поддерживают CSP, и наоборот: браузеры, в которых поддержка CSP отсутствует, будут её игнорировать, продолжая работу в соответствии со стандартными правилами ограничения домена для загрузки контента. В случае, если сайт не предоставляет CSP-заголовки, браузеры, в свою очередь, будут использовать стандартные правила ограничения домена.
Угрозы
Межсайтовый скриптинг
Основная цель создания CSP заключается в устранении XSS-атак и сборе данных об их попытках. XSS-атаки используют доверие браузера к контенту, полученному с сервера. Зловредные скрипты исполняются в браузере жертвы, поскольку браузер доверяет источнику, даже когда скрипт поставляется не оттуда, откуда кажется.
CSP даёт возможность администраторам серверов снизить или полностью устранить вектора, по которым злоумышленники могут провести XSS, с помощью определения доменов, которые браузер клиента должен считать доверенными источниками исполняемых скриптов. В таком случае, браузер, совместимый с CSP, будет исполнять только те скрипты, которые были получены из списка разрешённых источников, и игнорировать прочие (в т.ч. встраиваемые скрипты и обработчики событий, указанные непосредственно в HTML-атрибутах).
В качестве крайней меры защиты, сайты, которые хотят запретить исполнение скриптов, могут настроить это поведение глобально, с помощью соответствующей опции.
Пакетный сниффинг
В дополнение к ограничению количества доверенных доменов, с которых разрешается получать контент, можно также ограничить список используемых протоколов; например (в идеале и это крайне желательно с точки зрения обеспечения безопасности), сервер может поставить ограничение на получение контента только по HTTPS. Завершённая стратегия защиты передачи данных должна включать в себя не только принуждение к использованию HTTPS, но также и пометку всех кук с помощью специального флага, а также перенаправление запросов с HTTP на HTTPS. Сайты также могут использовать Strict-Transport-Security HTTP-заголовок, чтобы обеспечить подключение к ним браузеров только по защищённому каналу.
Использование CSP
Настройка CSP включает в себя добавление на страницу HTTP-заголовка Content-Security-Policy (en-US) и его настройку в соответствии со списком доверенных источников, из которых пользователь может получать контент. Например, страница, на которой происходит загрузка и отображение изображений может разрешать их получение из любых источников, но ограничить отправку данных формы конкретным адресом. При правильной настройке, Content Security Policy поможет защитить страницу от атак межсайтового скриптинга. Данная статья описывает как правильно настроить необходимые заголовки и примеры, как это сделать.
Определение политики
Вы можете начать настройку Content-Security-Policy (en-US) с определения HTTP-заголовка и указания какую политику использовать:
Создание политики
Примеры: Распространённые случаи применения
В данном разделе приводятся наиболее распространённые сценарии использования CSP.
Пример 1
Вы хотите ограничить источники контента только исходным сервером (исключая поддомены)
Пример 2
Вы хотите разрешить получение контента с доверенного домена и всех его поддоменов (доверенный домен не обязательно должен совпадать с тем, на котором настраиваются CSP.)
Пример 3
Вы хотите разрешить пользователям приложения вставлять в создаваемый ими контент картинки из любого источника, но при этом ограничить источники аудио- и видео-файлов списком доверенных провайдеров. Получение скриптов должно происходить только с конкретного сервера, содержащего доверенный код.
При такой настройке, весь контент доступен для получения только с исходного домена, со следующими исключениями:
Пример 4
Вы хотите удостовериться, что весь получаемый контент для онлайн-банкинга идёт по SSL и атакующий не сможет обрабатывать запросы:
Пример 5
Для просмотра писем в почтовом клиенте вы хотите разрешить использование HTML внутри письма, а также позволить загрузку изображений из любых источников, но запретить использование любого JavaScript-кода и прочий потенциально опасный контент.
Заметьте, что в настройке политики отсутствует директива script-src (en-US); при такой настройке CSP при загрузке скриптов будут использоваться настройки, определяемые директивой default-src (en-US), следовательно все скрипты могут быть загружены только с исходного домена.
Тестирование настройки политики
Для облегчения развёртывания можно настроить развёртывание CSP в режиме report-only. Таким образом, политика не будет ограничивать загрузку, но будет сообщать обо всех нарушениях на указанный в заголовке URI. Кроме того, заголовок report-only может использоваться для тестирования новой политики без полноценного развёртывания.
Для определения вашей политики вы можете использовать заголовок Content-Security-Policy-Report-Only (en-US) следующим образом:
Настройка отправки отчётов
По умолчанию, отправка отчётов не производится. Для того чтобы включить отправку отчётов, необходимо в вашей политике определить директиву report-uri (en-US) и указать как минимум один URI, куда будут направляться отчёты:
Кроме того, необходимо настроить свой сервер на получение этих отчётов; вы можете хранить и обрабатывать эти отчёты как считаете нужным.
Синтаксис отчёта о происшествиях
Объект отчёта в формате JSON содержит следующие поля:
Пример отчёта о происшествии
Совместимость с браузерами
BCD tables only load in the browser
Для некоторых версий Safari существует специфическая несовместимость реализации CSP. Если установить заголовок Content Security Policy без заголовка Same Origin, то браузер начнёт блокировать и создавать ложно-положительные отчёты о нарушении политики для всего контента, как с запрашиваемого источника, так и из внешних источников.
Как настроить Content Security Policy (CSP)
Три года назад организацией Mozilla Foundation был разработан новый стандарт политики безопасности, который предотвращает XSS-атаки и другие, связанные с ним виды атак запрещая подгружать и выполнять скрипты с запрещённых ресурсов. Называется он Content Security Policy (CSP), что в переводе означает «Политика безопасности контента».
На момент написания статьи стандарт CSP находится в статусе Candidate Recommendation, что означает возможное принятие этого стандарта в будущем W3C консорциумом. На данный момент все популярные браузеры поддерживают этот стандарт.
| Браузер | Версия | Примечания |
|---|---|---|
| Chrome | 25+ | Полная поддержка |
| Firefox | 23+ | |
| Opera | 15+ | |
| Яндекс.Браузер | ||
| Firefox | 4-22 | Поддерживают нестандартный заголовок X-Content-Security-Policy и частично поддерживают стандартный |
| IE | 10+ | |
| Chrome | 14-24+ | Поддерживают нестандартный заголовок X-Webkit-CSP и частично поддерживают стандартный |
| Safari | 5-7 | |
Как отсутствие CSP может навредить сайту?
Допустим у вас есть сайт, на котором вы показываете рекламу пользователям и честно зарабатываете деньги. И всё идёт хорошо, пока к вам не начнут ходит пользователи с заражёнными браузерами. Заражённый браузер будет подменять рекламу на вашем сайте на свою и показывать её пользователю. Как следствие — пессимизация со стороны поисковиков и падение дохода. Если же вы введёте политику CSP на своём сайте, то чужая реклама уже не покажется конечному пользователю, потому что сервер с которого реклама будет пытаться загрузиться находится не в белом списке, впрочем обо всё по порядку.
Содержание Content Security Policy
По сути Content Security Policy — это заголовок, который сервер отправляет браузеру. Давайте разберём более детально из чего же он состоит.
| Директива | Назначение |
|---|---|
| default-src | В этой директиве задаются белые списки хостов, которые будут автоматически присвоены не заданным директивам. |
| script-srс | Белый список хостов с которых разрешается загрузка javascript |
| style-src | Белый список хостов с которых разрешается загрузка css |
| object-src | Белый список хостов с которых разрешается загрузка Flash-подобных плагинов |
| img-src | Белый список хостов с которых разрешается загрузка картинок |
| media-src | Белый список хостов с которых разрешается загрузка аудио и видео |
| frame-src | Белый список хостов с которых разрешается загрузка iframe’ов |
| font-src | Белый список хостов с которых разрешается загрузка шрифтов |
| connect-src | Специальные директивы для XMLHttpRequest, WebSocket и EventSource. Обратите внимание, что для каждой из этих директив задаётся список не урлов, а хостов, с которыми разрешено общаться браузеру. |
| report-uri | Url, на который будет отсылаться JSON-отчёт о нарушениях политики. Пример отчёта будет показан ниже в статье. |
Сейчас ещё немного теории, и потом сразу перейдём к практики, потерпите 😉
Устанавливаем Content Security Policy на сайт
Как я уже писал выше, CSP — это обычный http заголовок, который можно наблюдать в консоли Google Chrome, наряду с остальными заголовками:
Чтобы лучше понять как работает Content Security Policy, давайте немного поэкспериментируем. Создайте файл index.php и напишите в него следующий код:
Обратите внимание, что в http заголовке я указал Content-Security-Policy-Report-Only он аналогичен Content-Security-Policy, с той лишь разницей, что не блокирует ресурсы, а только оповещает о нарушении. Крайне полезная штука при тестировании системы перед внедрением!
Т.е. попробуем выполнить инлайн скрипт и загрузить картинку со стороннего хоста. И посмотрим как отреагирует наш бравый защитник: 
CSP отреагировал адекватно. Т.е. подгрузил картинку и выполнил инлайновый javascript, но при этом сказал нам в консоли «ата-та!», а именно: сообщил о том, что произошло два нарушения.
Теперь давайте изменим заголовок с Content-Security-Policy-Report-Only на Content-Security-Policy и посмотрим что будет: 
Пендальф CSP никого не пустил. 
Инлайн скрипт не был выполнен, а картинка не загрузилась. Круто, правда?
Теперь можете поэкспериментировать самостоятельно. Вам пригодятся две таблички выше в статье, в которых мы рассмотрели директивы и ключевые слова для указания хостов. Попробуйте заменить ‘self’ на https://zabolotskikh.com/ и посмотрите что произойдет — картинка сможет загрузиться, так как её сервер был указан в белом списке.
Обработка отчётов
Вся прелесть этой политики в том, что помимо блокирования, мы также можем собирать отчёты о нарушениях! Помните в примере в http заголовке мы указали url report-uri http://localhost/csp/collector.php для сбрасывания отчётов? Как не сложно догадаться на этот url будут отправляться все отчёты о нарушениях.
Вот так выглядит отчёт о нарушении (в формате JSON):
С этим отчётом вы можете делать всё что угодно, например сохранять в базу, отправлять на почту. Я предлагаю записывать все нарушения в csv файл. Давайте сделаем это!
Создайте файл collector.php и напишите в него следующие строки:
Теперь ещё раз обновите страницу и посмотрите в директорию http://localhost/csp/. У вас должен появиться файл report.csv с двумя строчками кода: 
Ура! Мы поймали отчёт о нарушениях и записали его в файл. Можете показать этот файл друзьям 😉 А лучше всего начните внедрять CSP на свой сайт, сначала в режиме тестирования, а потом в «боевом» виде. На этапе тестирования отчёт поможет вам анализировать какие директивы реагируют на нарушения и соответствующим образом настраивать их.
Полезные материалы по Content Security Policy
Здравствуй дорогой читатель! Я рад приветствовать тебя на страницах моего блога. Уже несколько лет я занимаюсь веб-программированием и рад поделиться с тобой своими знаниями и советами. Если тебе понравились мои статьи, ты можешь подписаться на рассылку блога, из неё ты узнаешь много интересного!










