Обход Content Security Policy

In English: https://blog.deteact.com/csp-bypass/

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’а необходимо вставить блок:

Сократить код можно следующим образом:

Изменяется здесь только id, который вы можете посмотреть в вашем личном кабинете Tag Manager’а.

Смысл в том, чтобы подключить скрипт gtm.js и добавить в очередь событие ‘gtm.js’, при обработке которого будет выполнен скрипт.

Есть unsafe-eval

Пример политики:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval' ajax.googleapis.com;

CDN и CSTI

С включенной политикой unsafe-eval мы можем выполнить атаку Client-Side Template Injection.

Если библиотека-шаблонизатор (такая как Vue.JS, Angular, JQuery и т. д.) не подключена на странице, нам нужно её подключить. Для этого хорошо подходит хост ajax.googleapis.com, который очень часто разрешён в CSP для подгрузки каких-то библиотек, нужных для работы сайта.

Для примера подключим AngularJS старой версии (1.4.6) и выполним произвольный код через внедрение шаблона. 

Итоговый вектор атаки:

В векторе мы создаём элемент div с атрибутом ng-app, который активизирует AngularJS, а в содержимом вставляем шаблон, эксплуатирующий CSTI в AngularJS 1.4.6, в результате выполняется код alert(1):

DOM-based XSS

Помимо CSTI, выполнить произвольный код при наличии unsafe-eval могут помочь и любые другие виды DOM-based XSS, в которых содержимое какого-то HTML-элемента попадает в вызов eval().

Нет unsafe-inline и unsafe-eval

Пример политики:

Content-Security-Policy: default-src 'self'; script-src 'self'  *.googleusercontent.com *.google.com *.yandex.net;

Файлообменники

В случае, если в script-src есть домен yandex.net, то скрипт можно подключить с Яндекс Диска. Необходимо скопировать итоговую ссылку на скачивание и заменить в ссылке значение параметра content_type на application/javascript, в таком случае сервер отдаст соответствующий заголовок, и браузер подключит скрипт:

Учитывайте, что ссылка на файл временная, и спустя некоторое время (приблизительно 4 часа) она перестает работать.

Если же в script-src есть записи *.googleusercontent.com и *.google.com, то скрипт аналогично можно подгрузить с Google Drive:

Необходимы обе записи из-за временного Cookie-идентификатора, который создаётся до перенаправления на *.googleusercontent.com.

Загрузка файлов или JS/JSON/JSONP-инъекции

Стоит проверить функциональности загрузки у приложения, возможно оно позволяет загружать JS-файлы, тогда скрипт можно будет запрашивать с собственного домена.

Также могут помочь неэксплуатабельные инъекции содержимого в JavaScript или JSON, а также JSONP hijacking. Например, в случае отсутствия валидации имени функции в JSONP, можно заменить вызываемую функцию, на свою, в которой вы сможете написать произвольный JS код:

Отправка данных

Предположим, что мы научились выполнять произвольный код на странице. Теперь стоит задача извлечь данные и передать их на контролируемый нами хост.

Есть разрешённые хосты

Пример политики:

Content-Security-Policy: default-src 'self'; connect-src: 'self' www.google-analytics.com *.google.com *.yandex.ru;

Системы аналитики

Если в политике разрешён хост Google Analytics, то можем отправлять данные туда. Учитывайте, что максимальный размер принимаемых данных за один запрос — 8КБ.

Ссылка для отправки данных выглядит следующим образом:

https://www.google-analytics.com/collect?v=1&tid=***&cid=123&t=event&ec=email&el=321&cs=newsletter&cm=email&cn=&cm1=1&ea=data

После этого в событиях вы увидите данные, которые вы отправили в параметре ea:

Системы опросов, чаты и т. д.

Если на сайте используются системы с онлайн консультантами, можно воспользоваться ими для отправки данных. 

При наличии в connect-src *.google или *.yandex.ru , можно воспользоваться сервисами, котороые расположены на этих поддоменах, а именно гугл формами и яндекс взглядом .

Пример отправки данных в гугл форму — https://docs.google.com/forms.

Тут все довольно просто, обычный POST запрос:

Пример отправки данных в яндекс взгляд — https://surveys.yandex.ru/.

Для яндекс взгляда будет необходимо генерировать уникальный ivid, функция отправки  будет выглядеть примерно так:

Нет разрешённых хостов

Пример политики:

Content-Security-Policy: default-src 'self'

Редирект

Если не разрешено соединение с какими-либо хостами, можно передать данные прямо в URL (в query string), перенаправив пользователя на свой веб-сервер:

Отправка внутри приложения

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

Что делать?

Всё это конечно хорошо, и мы научились ломать, но более важный вопрос — как защититься?

Не разрешать лишнее

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

Для проверки CSP можно воспользоваться https://csp-evaluator.withgoogle.com/. Данный сайт проанализирует выставленные политики и покажет какие угрозы несет каждая из них. 

Использовать директиву report-uri

Или пришедшую на замену report-to, что заставит браузер сообщать о попытках злоумышленников обойти CSP на вашем сайте. Это поможет вам вовремя среагировать на атаку и минимизировать риски от нее.

Запретить unsafe-inline

Или используйте nonce, а также не разрешайте unsafe-eval.

Не допускать XSS!

Механизм CSP — это лишь компенсирующая мера, которая усложняет эксплуатацию XSS, но зачастую не делает её невозможной.

Проводить пентест

Чтобы проверить корректность настройки CSP и устойчивость вашего приложения к XSS и другим атакам, обратитесь к нам для проведения пентеста веб-приложения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *