Статья Фильтрация мусора и Content Security Policy (CSP) отчеты

Данная статья является переводом. Оригинал вот


Принято считать, что если вы принимаете отчеты о Content Security Policy (CSP) (на рус. "Нарушения Политики Безопасности Контента"), вам придется фильтровать множество непонятных и недействительных отчетов.

Но дела обстоят получше, чем шесть лет назад, когда я впервые начал идти по пути CSP с Caspr. Браузеры и другие пользовательские агенты гораздо более продуманны в отношении того, что и когда они сообщают. А новые дополнения к CSP, такие как "script-sample", сделали фильтрацию легкой.

Эта статья даст краткий обзор, а затем расскажет о некоторых методах, которые можно использовать для фильтрации Content Security Policy отчетов. Это методы, которые хорошо сработали в от Csper.


Введение в Content Security Policy
Данный раздел - перевод отдельной

Content Security Policy - это не тривиальная тема, но к сожалению, многие люди в ней ошибаются ( ).


Что такое Content Security Policy?

Веб-сайты состоят из различного контента. Есть HTML, который создает основу для веб-страницы и дает ей текст. Есть CSS, который применяет стили и делает страницу красивой. Есть javascript, который делает веб-страницы динамическими. Также есть изображения, видео, шрифты и многое другое.

Content Security Policy - это механизм, который обеспечиваает какое содержимое (скрипты, стили, шрифты, изображения и т.д.) может быть загружено и использовано веб-сайтом.

Но на самом деле, это слегка глупо. Как владелец сайта, разве вы уже не решаете, какой контент разрешено использовать веб-странице? Как владелец сайта, вы уже говорите своим пользователям, какой контент загружать, когда вы передаете им HTML документ.

1591963015919.png

Рисунок 1: Браузер, запрашивающий веб-страницу

Полученный HTML-документ из catbook загрузит правильные изображения, таблицы стилей, javascript, шрифты и т.д. Так зачем нам понадобилась эта Content Security Policy (CSP), чтобы ограничить еще больше?

CSP вам нужна чтобы предотвратить случаи, когда веб-страница работает не так, как вы задумывали. Есть пара способов, в которых это может произойти, но тот, для решения которого была разработано Content Security Policy, - это распространенная веб-уязвимость под названием Cross Site Scripting (XSS).


Cross Site Scripting

Межсайтовый скриптинг - это нежелательное/вредноносное выполнение Javascript на веб-странице.

Давайте представим, что мы создали сайт под названием Catbook: Фейсбук для Кошек. Это социальная сеть, где кошки могут взаимодействовать с другими кошками через Интернет.

Давайте представим, что у нее есть такой URL:


1591963729808.png

Рисунок 2: HTML содержит URL и вид отображенного браузера

Мы видим, что имя пользователя "madCatChessy" берется из URL, а затем помещается веб-сервером в HTML, а затем выводится браузером.

Итак, теперь самое интересное. Что, если вместо этого мы перейдем на веб-страницу типа: <script>alert(1)</script>.

1591963829791.png

Рисунок 3: Инъекция Javascript в веб-страницу (межсайтовый скриптинг)

И так, веб-сервер подумал, что <script>alert(1)</script> - это имя кошки. Поэтому он взял это имя и ввел его в HTML. HTML затем был отображен браузером и <script>alert(1)</script> интерпретировалось как Javascript, а не как имя пользователя.

Таким образом, если бы вы хотели этим как-то навредить, вы могли бы отправить этот URL всем своим друзьям-кошкам и напугали бы их: <script>alert('Ваша учетная запись в catbook была удалена')</script>.

В то время как у нас это забавный розыгрыш, на самом деле есть много действительно плохих примеров, которые можно воплотить с XSS. Например:
  • Вы можете использовать его, чтобы "украсть чей-то сеанс" и эффективно войти в систему. Это значит, что Вы можете украсть чей-то аккаунт (в некоторой степени).
  • Вы можете послать вредоносную ссылку, чтобы напугать других людей и заставить их делать то, что вы хотите ("Ваш компьютер взломан!!!. Скачайте этот (поддельный) антивирус").
  • Вы также можете использовать его, чтобы узнать личную информацию и в дальнейшем использовать шантаж. Вы можете использовать это, для чтения всех HTML элементов на странице и подождать, пока пользователи введут информацию о своей кредитной карте или еще что-нибудь конфиденциальное.

Это очень серьезная проблема, поэтому все основные браузеры тратят время на внедрение Content Security Policy (наряду с другими мерами защиты) для предотвращения таких проблем.


Как политика безопасности контента предотвращает XSS?

Во-первых, Content Security Policy (CSP) отключает любой встроенный javascript от запуска. Во-вторых, она требует, чтобы вы явно указывали, с какого внешнего источника вы разрешаете вашему сайту загружать javascript.

Позволяя только определенному сайту быть источником javascript (и явно не позволяя встроенный javascript), мы можем уменьшить количество разрешенных исполняемых скриптов. Цель состоит в том, чтобы уменьшить количество исполняемых скриптов до такой степени, что бы выполнялся только изначально запланированый JavaScript скрипты.

Код:
script-src 'self' https://www.google-analytics.com https://cdn.catbook.com/vendor.js;
style-src 'self' https://cdn.bootstrap.com;
report-uri https://csper.io/;

Выше приведен пример Content Security Policy. Наиболее распространенное происхождение является "self", что означает, что на catbook.com я могу загрузить и выполнить javascript из <script src=" "/>. Вы также можете использовать cdn.catbook.com и затем загрузить javascript из <script src=" "/>. Что действительно важно, так это доверенны источник скриптов.

Те же ограничения могут быть сделаны для всех типов содержимого, но javascript является наиболее важным.


С чего начать?

Самый простой способ - это автоматические инструменты, генерирующие для вас CSP. - это расширение для chrome/firefox, которое автоматически генерирует политику безопасности контента для любого сайта.




Что такое отчет о Content Security Policy?

Если вы новичок в этой области, я бы порекомендовал сначала ознакомиться с разделом «Введение в Content Security Policy».

Content Security Policy имеет отличную функцию под названием report-uri . Когда report-uri включен, браузер будет отправлять JSON blolb всякий раз, когда браузер обнаруживает нарушение в CSP. (Для получения дополнительной информации: ). Этот JSON blolb является отчетом.

Вот случайное сообщение о нарушении с моего личного сайта :

JSON:
{
  "csp-report": {
    "document-uri": "https://c0nrad.io/",
    "referrer": "",
    "violated-directive": "style-src-elem",
    "effective-directive": "style-src-elem",
    "original-policy": "default-src 'self'; font-src 'self' data: https://maxcdn.bootstrapcdn.com; img-src 'self' http://c0nrad.io; object-src 'none'; script-src 'report-sample' 'self'; style-src 'report-sample' 'self' https://maxcdn.bootstrapcdn.com; base-uri 'none'; report-uri https://5e52f4c893efcda6a7d40460.endpoint.csper.io;",
    "disposition": "report",
    "blocked-uri": "inline",
    "line-number": 8,
    "source-file": "https://c0nrad.io/",
    "status-code": 0,
    "script-sample": ".something { width: 100%}"
  }
}

Отчет: Рапорт о нарушении от c0nrad.io в стиле inline.


В отчете есть ряд интересных деталей:
  • blocked-uri: inline. blocked-uri был «встроенным» ресурсом
  • violated-directive: style-src-elem. violated-directive былj элементом CSS (блок <style> в отличие от "style =" attr (attribute) для HTML элемента)
  • source-file / line-number: / 8. source-file появился из файла с 8 строки. Если вы просмотрите исходный код , то сможете его найти.
  • script-sample: .something { width: 100%}«Первые 40 символов .something { width :100%}.
Эти отчеты – настоящий подарок, когда начинаешь работать с CSP. Вы можете использовать их, чтобы быстро определить, где отсутствует ваша политика. Вы даже можете использовать их для создания новых политик с нуля. Фактически, такие инструменты, как автоматически создают CSP. Просто анализируя эти отчеты.


Зачем фильтровать отчеты о политике безопасности контента?

Если отчеты о нарушении настолько информативны, почему мы хотим их отфильтровать? Сначала это может позаказаться немного нелогичным, но не все отчеты создаются одинаково.

Вот некоторые из встроенных отчетов, которые Csper получил по своей собственной политике. Только три из них от реального встроенного скрипта в Csper (который я специально ввел).

Для большего удовольствия я настоятельно рекомендую ознакомиться с этим удивительным списком забавных отчетов CSP: csp-wtf

Расстраивает то, что большой процент отчетов, полученных от CSP, неактивен. Они на самом деле не связаны с сайтом. Эти «неактивные» отчеты могут приходить из различных мест. Наиболее распространенными являются расширения и дополнения. Есть также реклама, контент, введенный интернет-провайдерами, вредоносные программы, корпоративные прокси-серверы, пользовательские скрипты, особенности браузера и множество серьезных отчетов "wtf".


Техника фильтрации

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

Они в некоторой степени перечислены в порядке: важность + легкость + надежность.


Черные списки

Самый простой способ отфильтровать огромное количество отчетов, применить несколько простых правил внесения в черный список.

Я думаю, что каждый прямо или косвенно брали пример с книги Нила Мататалла/Твиттера в 2014 году:

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

Но только эта техника исключает ~50% странных сообщений.


Неверно сформированные отчеты


Еще один простой способ фильтрации отчетов - убедиться, что в них есть все необходимые поля (к примеру: effective-directive, является реальной директивой). Если не хватает некоторых полей, то, вероятнее всего, не стоит тратить время на их исследование. Скорее всего, это очень старый или неполный пользовательский агент. Все поля можно найти в .

JSON:
{
  "csp-report": {
    ...
    "violated-directive": "%22%3e%3cimg%20src%3dx%20id%3ddr%3deval(atob(this%2eid))%3e..."
    ...,
  }
}

Вы можете подумать, что, возможно, пользователи, которые используют XSS, работают на очень старом браузере, который неправильно отображает отчеты по всем полям, и поэтому, если вы отфильтруете их, вы пропустите XSS, который должен быть исправлен. Это, безусловно, справедливо. Но с автоматическим обновлениями браузеров я думаю/надеюсь, что большинство людей используют свежие браузеры. А также (это не должно быть оправданием, чтобы не решать такую проблему) у людей с очень устаревшими браузерами, вероятно, другие проблемы с браузером, о которых нужно беспокоиться. И если несколько пользователей используют XSS, большинство из них, вероятно, используют компетентный пользовательский агент, который сообщит обо всех полях, поэтому он будет выбран.

Все зависит от того, сколько времени/ресурсов организация должна посвятить CSP. Что-то лучше чем ничего. И в этом случае, это что-то может сэкономить вам несколько часов, для довольно маленького шанса, из которого может получиться трещина. Я рекомендую добавлять ярлык к отчетам, в которых отсутствуют важные поля (или используются неправильные значения), которые следует классифицировать как «неправильно сформированные» и просто держать в стороне, чтобы их можно было просматривать каждый раз в течение некоторого времени.


Боты

Еще один простой способ отфильтровать "неактивные" отчеты - это проверить, принадлежат ли пользовательские агенты боту. Несколько веб-scraper внедряют JavaScript в страницы, которые они анализируют. (У ботов также включена CSP). Что поначалу выглядит глупо, но, скорее всего, они просто используют хром без загловков или что-то в этом роде.

Несколько примеров пользовательских агентов:

Код:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; compatible; BuiltWith/1.0; +http://builtwith.com/biup) Chrome/60.0.3112.50 Safari/537.36
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/61.0.3163.59 Safari/537.36 Prerender (+https://github.com/prerender/prerender)
Mozilla/5.0 (compatible; woorankreview/2.0; +https://www.woorank.com/)
Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)

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


Script-Sample

Если report-sample включен ( настоятельно рекомендую его включить), вы можете начать отфильтровывать отчеты по первым 40 символам в поле образца сценария.

Хорошей отправной точкой является список csp-wtf .

Небольшое предостережение относительно веб-сайтов, работающих в режиме «Content-Security-Policy-Report-Only». Если вы автоматически отфильтруете все, что соответствует этим примерам сценариев, злоумышленник может попытаться использовать XSS, который начинается с одной из этих строк, чтобы избежать обнаружения. Если это XSS на основе DOM, будет очень трудно определить, что это инъекция, а не XSS на основе DOM (подробнее об этом позже).


Возраст браузера

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

Поэтому, когда отчет получен, вы берете User Agent + Version, ищите дату выпуска этого User Agent и, если он старше некоторого периода времени (2 года), помечаете его как более старый пользовательский агент. Это исключает около 15% отчетов.

Тот же аргумент все еще остается в силе, "Если XSS-жертва использует старый браузер". Опять же, я думаю, что это зависит от уровня безопасности сайта и доступных ресурсов, чтобы определить, какой уровень усилий необходим. Но для обычного веб-сайта стоит уделять меньше внимания браузерам старше двух лет, но уделять больше внимания остальным отчетам, вместо того, чтобы захломляться отчетами и ничего не делать. Отчеты все еще остануться для тех, кто хочет их просмотреть.


Анализ по
line-number / column-number


Современные браузеры попытаються добавить номер Line-Number/Column-Number в отчеты о нарушениях. ( ).

Таким образом, если есть ресурс, который не имеет нумерацию строк/столбцов, то стоит на это обратить внимание. Многие отчеты также используют «1» или «0» в качестве номера строки, что также может быть отличным сигналом чего-то странного.

Я обнаружил, что обычно номер строки 0/1 означает, что ресурсы были "введены" после этого факта. (Поскольку в нем не было части оригинального HTML). Это можеть быть, как SPAS (angular/react ) инъекционные ресурсы, браузеры, внедряющие скрипты контента, или XSS на основе DOM.

К сожалению (по крайней мере, для современного Chrome), я не смог определить разницу между XSS на основе DOM и чем-то, что вводится скриптом браузера.

Например, вот отчет о XSS на основе DOM, который я внедрил через внутренний HTML. Это выглядит почти так же, как множество инъекций расширения с номером строки 1:

JSON:
{
  "csp-report": {
    "document-uri": "http://localhost:4200/blog/csp-report-filtering",
    "referrer": "",
    "violated-directive": "script-src-attr",
    "effective-directive": "script-src-attr",
    "original-policy": "default-src 'report-sample' 'none'; report-uri http://localhost:8080/endpoint/5e84a130bd4c866cb237ce18;",
    "disposition": "report",
    "blocked-uri": "inline",
    "line-number": 1,
    "source-file": "http://localhost:4200/blog/csp-report-filtering",
    "status-code": 200,
    "script-sample": "alert(1)"
  }
}

Но по-прежнему интересно, когда в отчете номер строки равен 1. Таким образом, встроенные отчеты можно разделить на категории «встроенные» или «внедренные». Внедренный отчет будет содержать большую часть содержимого браузера, но может также содержать XSS на основе DOM, так что все еще нужно просмотреть.

Я надеюсь, что в будущем исходный файл будет точно отражать происхождение javascript, и мы сможем легко отфильтровать все расширения.


SourceFile / DocumentURI

В некотором роде, stored или reflected XSS должны иметь соответствующий sourcefile/documenturi (очевидно, не относится к DOM или более экзотическим XSS). В некоторых странных отчетах исходный файл будет из стороних ресурсов(например, скрипта из Google Translate).

Если вы специально хотите обнаружить stored/reflected XSS, несоответствие может быть хорошим признаком того, что, возможно, отчет не так полезен.

Firefox, в некоторой степени, также не включает исходный файл из расширений eval, что может помочь уменьшить eval noise. (Их можно поместить в бакт расширений).


Другие идеи

Подобные отчеты из более новых версий браузера


Браузеры становятся лучше, когда полностью определяют, какой контент поступил от расширения. Например, ниже довольно очевидно, что этот отчет имеет расширение (благодаря исходному файлу, начинающемуся с moz-extension). Это сообщение было получено от пользователя Useragent с Firefox/Windows/Desktop, выпущенного 22 дня назад.

JSON:
{
  "csp-report": {
    "blocked-uri": "inline",
    "column-number": 33,
    "document-uri": "https://csper.io/docs/generating-content-security-policy",
    "line-number": 214,
    "original-policy": "default-src 'self'; connect-src 'self' https://*.hotjar.com https://*.hotjar.io https://api.hubspot.com https://forms.hubspot.com https://rs.fullstory.com https://stats.g.doubleclick.net https://www.google-analytics.com wss://*.hotjar.com; font-src 'self' data: https://script.hotjar.com; frame-src 'self' https://charts.mongodb.com https://app.hubspot.com https://js.stripe.com https://vars.hotjar.com https://www.youtube.com; img-src 'self' data: https:; object-src 'none'; script-src 'report-sample' 'self' http://js.hs-analytics.net/analytics/ https://edge.fullstory.com/s/fs.js https://js.hs-analytics.net/analytics/ https://js.hs-scripts.com/ https://js.hscollectedforms.net/collectedforms.js https://js.stripe.com/v3/ https://js.usemessages.com/conversations-embed.js https://script.hotjar.com https://static.hotjar.com https://www.google-analytics.com/analytics.js https://www.googletagmanager.com/gtag/js; style-src 'report-sample' 'self' 'unsafe-inline'; base-uri 'self'; report-uri https://csper-prod.endpoint.csper.io/",
    "referrer": "",
    "script-sample": "(() => {\n        try {\n            // co…",
    "source-file": "moz-extension://1f302211-a995-4090-a7ee-be593ef4168a/content/core.js",
    "violated-directive": "script-src"
  }
}

Следующий отчет, скорее всего, был составлен из того же расширения, но из отчета не видно, откуда он взялся. Это UserAgent - Firefox/Windows/Desktop, но он был выпущен 9 месяцев назад.

JSON:
{
  "csp-report": {
    "blocked-uri": "inline",
    "column-number": 1,
    "document-uri": "https://csper.io/blog/other-csp-security",
    "line-number": 1,
    "original-policy": "default-src 'self'; connect-src 'self' https://*.hotjar.com https://*.hotjar.io https://api.hubspot.com https://forms.hubspot.com https://rs.fullstory.com https://stats.g.doubleclick.net https://www.google-analytics.com wss://*.hotjar.com; font-src 'self' data: https://script.hotjar.com; frame-src 'self' https://app.hubspot.com https://js.stripe.com https://vars.hotjar.com https://www.youtube.com; img-src 'self' data: https:; object-src 'none'; script-src 'report-sample' 'self' http://js.hs-analytics.net/analytics/ https://edge.fullstory.com/s/fs.js https://js.hs-analytics.net/analytics/ https://js.hs-scripts.com/ https://js.hscollectedforms.net/collectedforms.js https://js.stripe.com/v3/ https://js.usemessages.com/conversations-embed.js https://script.hotjar.com https://static.hotjar.com https://www.google-analytics.com/analytics.js https://www.googletagmanager.com/gtag/js; style-src 'report-sample' 'self' 'unsafe-inline'; base-uri 'self'; report-uri https://csper-prod.endpoint.csper.io/",
    "referrer": "",
    "script-sample": "(() => {\n        try {\n            // co…",
    "source-file": "https://csper.io/blog/other-csp-security",
    "violated-directive": "script-src"
  }
}

Это не идеально, но можно сгруппировать похожие отчёты вместе и выполнить анализ на последнем пользовательском агенте. Но нужно быть осторожным, чтобы не сгруппировать отчеты до такой степени, чтобы злоумышленник мог попытаться перехватить XXS, которые начинаются с (() => {\n // co, чтобы избежать обнаружения при развертывании только для отчетов.

Надеюсь, что все переходят на самые последние версии браузеров, и мы сможем просто отфильтровать исходный файл. Была также небольшая болтовня о добавлении sha256-hash к отчету , что также сделало бы это бесконечно более осуществимым (но для того, чтобы отправить новый sha256, люди должны были бы использовать более свежие версии своих браузеров, и к этому моменту у вас уже будет индикатор moz-extension в исходном файле).


Маркировка "Crowd Sourced"

Еще одна идея, над которой я думаю - это маркировка «Crowd Sourced». Что если бы все могли пометить отчеты как «неактивные» (что-то вроде списка csp-wtf)? Или «этот отчет не относится к моему проекту». Эти отчеты агрегируются и затем отображаются другим пользователям endpoint report-uri как «другие пользователи отметили этот отчет как неактивный». Для людей, только начинающих работать с CSP, это может быть хорошей информацией для игнорирования отчета.

Или, в частности, если есть XSS с известным пейлоадом, люди могут пометить как «это настоящий XSS», и другие пользователи получают это указание, когда в их проекте есть аналогичный отчет.

Из-за моей обеспокоенности по поводу конфиденциальности/злоупотребления эта идея была бестолковой. На данный момент (для csper) нет способа для клиента собрать информацию о другом клиенте, и очевидно, что так и должно быть, и это нормально. Но, возможно, в будущем для этого можно будет устанваить анонимный флаг функции. Но не в течение многих месяцев, по крайней мере. Если вам это интересно, я буду рад услышать ваши мысли! Stuart@csper.io.


Вывод

Я недеюсь, что в один прекрасный день, каждый сможет использовать Content-Security-Policy-Report-Only и получать прибыль, практически не работая. Если отдельные лица используют последние пользовательские агенты, и если классификация конечной точки достаточно хороша, веб-сайты могут развернуть CSP в режиме report-only на несколько недель, чтобы установить базовую линию известных встроенных отчетов и их позиции, и тогда endpoint узнает где существуют ожидаемые встроенные ресурсы, и затем только предупреждают владельцев веб-сайтов о новых отчетах, которые он посчитает за XSS. Обнаружение XSS для любого сайта практически без усилий.

Пока этого не произошло, но браузеры совершенствуются в том, что они отправляют, и классификация отчетов становится проще.

Я надеюсь, что это было полезно! Если у вас есть идеи или комментарии, я хотел бы их услышать! stuart at csper.io.

И, конечно, если вы заинтересованы в report-uri, который делает все это, посмотрите !
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!