Content Security Policy (CSP) Bypass
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!
Hacking Insights Engage with content that delves into the thrill and challenges of hacking
Real-Time Hack News Keep up-to-date with fast-paced hacking world through real-time news and insights
Latest Announcements Stay informed with the newest bug bounties launching and crucial platform updates
Join us on Discord and start collaborating with top hackers today!
What is CSP
Content Security Policy (CSP) вважається технологією браузера, яка в основному спрямована на захист від атак, таких як міжсайтовий скриптинг (XSS). Вона функціонує, визначаючи та деталізуючи шляхи та джерела, з яких ресурси можуть бути безпечно завантажені браузером. Ці ресурси охоплюють ряд елементів, таких як зображення, фрейми та JavaScript. Наприклад, політика може дозволити завантаження та виконання ресурсів з того ж домену (self), включаючи вбудовані ресурси та виконання рядкового коду через функції, такі як eval
, setTimeout
або setInterval
.
Впровадження CSP здійснюється через заголовки відповіді або шляхом включення мета-елементів у HTML-сторінку. Дотримуючись цієї політики, браузери активно забезпечують виконання цих вимог і негайно блокують будь-які виявлені порушення.
Implemented via response header:
Реалізовано через мета-тег:
Headers
CSP може бути застосований або моніторений за допомогою цих заголовків:
Content-Security-Policy
: Застосовує CSP; браузер блокує будь-які порушення.Content-Security-Policy-Report-Only
: Використовується для моніторингу; повідомляє про порушення без їх блокування. Ідеально підходить для тестування в середовищах перед випуском.
Defining Resources
CSP обмежує джерела для завантаження як активного, так і пасивного контенту, контролюючи аспекти, такі як виконання вбудованого JavaScript та використання eval()
. Приклад політики:
Директиви
script-src: Дозволяє конкретні джерела для JavaScript, включаючи URL-адреси, вбудовані скрипти та скрипти, що викликаються обробниками подій або XSLT-стилями.
default-src: Встановлює стандартну політику для отримання ресурсів, коли конкретні директиви отримання відсутні.
child-src: Вказує дозволені ресурси для веб-робітників та вбудованого вмісту фреймів.
connect-src: Обмежує URL-адреси, які можуть бути завантажені за допомогою інтерфейсів, таких як fetch, WebSocket, XMLHttpRequest.
frame-src: Обмежує URL-адреси для фреймів.
frame-ancestors: Вказує, які джерела можуть вбудовувати поточну сторінку, застосовується до елементів, таких як
<frame>
,<iframe>
,<object>
,<embed>
, і<applet>
.img-src: Визначає дозволені джерела для зображень.
font-src: Вказує дійсні джерела для шрифтів, завантажених за допомогою
@font-face
.manifest-src: Визначає дозволені джерела файлів маніфесту додатка.
media-src: Визначає дозволені джерела для завантаження медіа-об'єктів.
object-src: Визначає дозволені джерела для елементів
<object>
,<embed>
, і<applet>
.base-uri: Вказує дозволені URL-адреси для завантаження за допомогою елементів
<base>
.form-action: Перераховує дійсні кінцеві точки для відправки форм.
plugin-types: Обмежує mime-типи, які може викликати сторінка.
upgrade-insecure-requests: Інструктує браузери переписувати HTTP URL-адреси на HTTPS.
sandbox: Застосовує обмеження, подібні до атрибута sandbox елемента
<iframe>
.report-to: Вказує групу, до якої буде надіслано звіт, якщо політика буде порушена.
worker-src: Вказує дійсні джерела для скриптів Worker, SharedWorker або ServiceWorker.
prefetch-src: Вказує дійсні джерела для ресурсів, які будуть отримані або попередньо отримані.
navigate-to: Обмежує URL-адреси, до яких документ може переходити будь-яким способом (a, форма, window.location, window.open тощо).
Джерела
*
: Дозволяє всі URL-адреси, крім тих, що мають схемиdata:
,blob:
,filesystem:
.'self'
: Дозволяє завантаження з того ж домену.'data'
: Дозволяє завантаження ресурсів через схему даних (наприклад, зображення, закодовані в Base64).'none'
: Блокує завантаження з будь-якого джерела.'unsafe-eval'
: Дозволяє використанняeval()
та подібних методів, не рекомендується з міркувань безпеки.'unsafe-hashes'
: Дозволяє конкретні вбудовані обробники подій.'unsafe-inline'
: Дозволяє використання вбудованих ресурсів, таких як вбудовані<script>
або<style>
, не рекомендується з міркувань безпеки.'nonce'
: Список дозволених для конкретних вбудованих скриптів, що використовують криптографічний nonce (число, що використовується один раз).Якщо у вас обмежене виконання JS, можливо отримати використаний nonce всередині сторінки за допомогою
doc.defaultView.top.document.querySelector("[nonce]")
і потім повторно використовувати його для завантаження шкідливого скрипта (якщо використовується strict-dynamic, будь-яке дозволене джерело може завантажити нові джерела, тому це не потрібно), як у:
'sha256-<hash>'
: Дозволяє скрипти з конкретним sha256 хешем.'strict-dynamic'
: Дозволяє завантаження скриптів з будь-якого джерела, якщо воно було внесено до білого списку за допомогою nonce або хешу.'host'
: Вказує конкретний хост, наприклад,example.com
.https:
: Обмежує URL-адреси тими, що використовують HTTPS.blob:
: Дозволяє завантаження ресурсів з Blob URL (наприклад, Blob URL, створених за допомогою JavaScript).filesystem:
: Дозволяє завантаження ресурсів з файлової системи.'report-sample'
: Включає зразок порушуючого коду у звіт про порушення (корисно для налагодження).'strict-origin'
: Схоже на 'self', але забезпечує, щоб рівень безпеки протоколу джерел відповідав документу (тільки безпечні джерела можуть завантажувати ресурси з безпечних джерел).'strict-origin-when-cross-origin'
: Надсилає повні URL-адреси при виконанні запитів з одного джерела, але лише надсилає джерело, коли запит є крос-доменним.'unsafe-allow-redirects'
: Дозволяє завантаження ресурсів, які негайно перенаправлять на інший ресурс. Не рекомендується, оскільки це послаблює безпеку.
Небезпечні правила CSP
'unsafe-inline'
Working payload: "/><script>alert(1);</script>
self + 'unsafe-inline' через Iframes
CSP bypass: self + 'unsafe-inline' with Iframes'unsafe-eval'
Це не працює, для отримання додаткової інформації перевірте це.
Працююча корисна навантаження:
strict-dynamic
Якщо ви зможете якимось чином змусити дозволений JS код створити новий тег скрипта в DOM з вашим JS кодом, оскільки його створює дозволений скрипт, новий тег скрипта буде дозволено виконати.
Wildcard (*)
Працююча корисна навантаження:
Відсутність object-src та default-src
Схоже, що це більше не працює
Працюючі корисні навантаження:
Завантаження файлів + 'self'
Якщо ви можете завантажити файл JS, ви можете обійти цей CSP:
Робочий вантаж:
Однак, ймовірно, що сервер перевіряє завантажений файл і дозволить вам завантажити лише певні типи файлів.
Більше того, навіть якщо ви зможете завантажити JS код всередині файлу з розширенням, прийнятим сервером (наприклад: script.png), цього буде недостатньо, оскільки деякі сервери, такі як apache server, вибирають MIME тип файлу на основі розширення, а браузери, такі як Chrome, відмовляться виконувати Javascript код всередині чогось, що повинно бути зображенням. "Сподіваємось", є помилки. Наприклад, з CTF я дізнався, що Apache не знає про розширення .wave, тому не подає його з MIME типом, як audio/*.
Звідси, якщо ви знайдете XSS і завантаження файлів, і вам вдасться знайти неправильно інтерпретоване розширення, ви можете спробувати завантажити файл з цим розширенням і вмістом скрипта. Або, якщо сервер перевіряє правильний формат завантаженого файлу, створіть поліглот (деякі приклади поліглотів тут).
Form-action
Якщо неможливо впровадити JS, ви все ще можете спробувати ексфільтрувати, наприклад, облікові дані, впроваджуючи дію форми (і, можливо, очікуючи, що менеджери паролів автоматично заповнять паролі). Ви можете знайти приклад у цьому звіті. Також зверніть увагу, що default-src
не охоплює дії форм.
Third Party Endpoints + ('unsafe-eval')
Для деяких з наступних payload unsafe-eval
навіть не потрібен.
Завантажте вразливу версію angular та виконайте довільний JS:
Payloads using Angular + a library with functions that return the window
object (check out this post):
window
object (check out this post):У пості показано, що ви можете завантажити всі бібліотеки з cdn.cloudflare.com
(або будь-якого іншого дозволеного репозиторію JS бібліотек), виконати всі додані функції з кожної бібліотеки та перевірити які функції з яких бібліотек повертають об'єкт window
.
Angular XSS з імені класу:
Зловживання JS-кодом google recaptcha
Згідно з цією CTF-статтею, ви можете зловживати https://www.google.com/recaptcha/ всередині CSP для виконання довільного JS-коду, обходячи CSP:
Більше пейлоадів з цього опису:
Зловживання www.google.com для відкритого перенаправлення
Наступне URL перенаправляє на example.com (з тут):
Зловживання *.google.com/script.google.com
Можливо зловживати Google Apps Script, щоб отримувати інформацію на сторінці всередині script.google.com. Як це зроблено в цьому звіті.
Треті сторони + JSONP
Сценарії, подібні до цього, де script-src
встановлено на self
та певний домен, який є у білому списку, можуть бути обійдені за допомогою JSONP. JSONP кінцеві точки дозволяють небезпечні методи зворотного виклику, які дозволяють зловмиснику виконати XSS, робочий вантаж:
JSONBee містить готові до використання JSONP кінцеві точки для обходу CSP різних веб-сайтів.
Та сама вразливість виникне, якщо достовірна кінцева точка містить відкритий редирект, оскільки якщо початкова кінцева точка є надійною, редиректи також вважаються надійними.
Зловживання з боку третіх осіб
Як описано в наступному пості, існує багато доменів третіх осіб, які можуть бути дозволені десь у CSP, і їх можна зловживати для ексфільтрації даних або виконання JavaScript коду. Деякі з цих третіх осіб:
Суб'єкт | Дозволений домен | Можливості |
---|---|---|
www.facebook.com, *.facebook.com | Exfil | |
Hotjar | *.hotjar.com, ask.hotjar.io | Exfil |
Jsdelivr | *.jsdelivr.com, cdn.jsdelivr.net | Exec |
Amazon CloudFront | *.cloudfront.net | Exfil, Exec |
Amazon AWS | *.amazonaws.com | Exfil, Exec |
Azure Websites | *.azurewebsites.net, *.azurestaticapps.net | Exfil, Exec |
Salesforce Heroku | *.herokuapp.com | Exfil, Exec |
Google Firebase | *.firebaseapp.com | Exfil, Exec |
Якщо ви знайдете будь-який з дозволених доменів у CSP вашої цілі, є ймовірність, що ви зможете обійти CSP, зареєструвавшись на сторонньому сервісі та або ексфільтрувати дані на цей сервіс, або виконати код.
Наприклад, якщо ви знайдете наступний CSP:
або
Ви повинні мати можливість ексфільтрувати дані, так само як це завжди робилося з Google Analytics/Google Tag Manager. У цьому випадку ви дотримуєтеся цих загальних кроків:
Створіть обліковий запис розробника Facebook тут.
Створіть новий додаток "Facebook Login" і виберіть "Веб-сайт".
Перейдіть до "Налаштування -> Основні" і отримайте свій "ID додатка".
На цільовому сайті, з якого ви хочете ексфільтрувати дані, ви можете ексфільтрувати дані, безпосередньо використовуючи гаджет Facebook SDK "fbq" через "customEvent" і навантаження даних.
Перейдіть до "Менеджера подій" вашого додатка і виберіть створений вами додаток (зауважте, що менеджер подій можна знайти за URL, подібним до цього: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).
Виберіть вкладку "Тестові події", щоб побачити події, які надсилаються з "вашого" веб-сайту.
Потім, на стороні жертви, ви виконуєте наступний код, щоб ініціалізувати піксель відстеження Facebook, вказуючи на ID додатка розробника Facebook атакуючого та видаючи подію користувача, як ця:
Щодо інших семи доменів третьої сторони, зазначених у попередній таблиці, існує багато інших способів їх зловживання. Зверніться до попереднього блог посту для додаткових пояснень про інші зловживання третьою стороною.
Bypass via RPO (Relative Path Overwrite)
На додаток до згадуваного перенаправлення для обходу обмежень шляху, існує ще одна техніка, званою Relative Path Overwrite (RPO), яка може бути використана на деяких серверах.
Наприклад, якщо CSP дозволяє шлях https://example.com/scripts/react/
, його можна обійти наступним чином:
Браузер в кінцевому підсумку завантажить https://example.com/scripts/angular/angular.js
.
Це працює, тому що для браузера ви завантажуєте файл з назвою ..%2fangular%2fangular.js
, розташований за адресою https://example.com/scripts/react/
, що відповідає CSP.
∑, вони декодують його, фактично запитуючи https://example.com/scripts/react/../angular/angular.js
, що еквівалентно https://example.com/scripts/angular/angular.js
.
Шляхом експлуатації цієї невідповідності в інтерпретації URL між браузером і сервером, правила шляху можна обійти.
Рішення полягає в тому, щоб не розглядати %2f
як /
на стороні сервера, забезпечуючи послідовну інтерпретацію між браузером і сервером, щоб уникнути цієї проблеми.
Онлайн приклад: https://jsbin.com/werevijewa/edit?html,output
Виконання JS в Iframes
Iframes in XSS, CSP and SOPвідсутній base-uri
Якщо директива base-uri відсутня, ви можете зловживати цим, щоб виконати dangling markup injection.
Більше того, якщо сторінка завантажує скрипт за допомогою відносного шляху (як <script src="/js/app.js">
) з використанням Nonce, ви можете зловживати base tag, щоб змусити його завантажити скрипт з вашого власного сервера, досягаючи XSS.
Якщо вразлива сторінка завантажується з httpS, використовуйте httpS URL в base.
AngularJS події
Специфічна політика, відома як Content Security Policy (CSP), може обмежувати JavaScript події. Проте, AngularJS вводить користувацькі події як альтернативу. У межах події AngularJS надає унікальний об'єкт $event
, що посилається на об'єкт події браузера. Цей об'єкт $event
може бути використаний для обходу CSP. Зокрема, у Chrome об'єкт $event/event
має атрибут path
, що містить масив об'єктів, залучених до ланцюга виконання події, причому об'єкт window
завжди розташований в кінці. Ця структура є вирішальною для тактик втечі з пісочниці.
Спрямовуючи цей масив до фільтра orderBy
, можна ітерувати його, використовуючи термінальний елемент (об'єкт window
), щоб викликати глобальну функцію, таку як alert()
. Наведений нижче фрагмент коду ілюструє цей процес:
Цей фрагмент підкреслює використання директиви ng-focus
для виклику події, використовуючи $event.path|orderBy
для маніпуляції масивом path
, і використовуючи об'єкт window
для виконання функції alert()
, тим самим розкриваючи document.cookie
.
Знайдіть інші обходи Angular на https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS та домен у білому списку
Політика CSP, яка дозволяє завантаження скриптів з певних доменів в Angular JS додатку, може бути обійдена через виклик функцій зворотного виклику та певних вразливих класів. Додаткову інформацію про цю техніку можна знайти в детальному посібнику, доступному в цьому git репозиторії.
Працюючі пейлоади:
Інші кінцеві точки для довільного виконання JSONP можна знайти тут (деякі з них були видалені або виправлені)
Обхід через редирект
Що відбувається, коли CSP стикається з редиректом на стороні сервера? Якщо редирект веде до іншого походження, яке не дозволено, він все ще зазнає невдачі.
Однак, відповідно до опису в CSP spec 4.2.2.3. Paths and Redirects, якщо редирект веде до іншого шляху, він може обійти початкові обмеження.
Ось приклад:
Якщо CSP встановлено на https://www.google.com/a/b/c/d
, оскільки враховується шлях, скрипти /test
та /a/test
будуть заблоковані CSP.
Однак, фінальний http://localhost:5555/301
буде перенаправлений на стороні сервера на https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
. Оскільки це перенаправлення, шлях не враховується, і скрипт може бути завантажений, таким чином обходячи обмеження шляху.
З цим перенаправленням, навіть якщо шлях вказано повністю, він все ще буде обійдено.
Отже, найкраще рішення - це забезпечити, щоб веб-сайт не мав жодних вразливостей до відкритого перенаправлення і щоб не було доменів, які можна експлуатувати в правилах CSP.
Обхід CSP з висячою розміткою
Читати як тут.
'unsafe-inline'; img-src *; через XSS
'unsafe-inline'
означає, що ви можете виконувати будь-який скрипт всередині коду (XSS може виконувати код), а img-src *
означає, що ви можете використовувати на веб-сторінці будь-яке зображення з будь-якого ресурсу.
Ви можете обійти цей CSP, ексфільтруючи дані через зображення (в даному випадку XSS зловживає CSRF, де сторінка, доступна ботом, містить SQLi, і витягує прапор через зображення):
From: https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle
Ви також можете зловживати цією конфігурацією, щоб завантажити javascript код, вставлений всередині зображення. Якщо, наприклад, сторінка дозволяє завантаження зображень з Twitter. Ви можете створити спеціальне зображення, завантажити його в Twitter і зловживати "unsafe-inline", щоб виконати JS код (як звичайний XSS), який завантажить зображення, витягне JS з нього і виконає його: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
З сервісними працівниками
Функція importScripts
сервісних працівників не обмежена CSP:
Впровадження політики
Дослідження: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Якщо параметр, надісланий вами, вставляється всередині оголошення політики, то ви можете змінити політику таким чином, що вона стане недійсною. Ви можете дозволити скрипт 'unsafe-inline' з будь-яким з цих обходів:
Тому що ця директива перезапише існуючі директиви script-src. Ви можете знайти приклад тут: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E
Edge
В Edge це набагато простіше. Якщо ви можете додати в CSP лише це: ;_
Edge відкине всю політику.
Приклад: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; через XSS (iframe) - Атака за часом
Зверніть увагу на відсутність директиви 'unsafe-inline'
Цього разу ви можете змусити жертву завантажити сторінку під вашим контролем через XSS з <iframe
. Цього разу ви змусите жертву отримати доступ до сторінки, з якої ви хочете витягти інформацію (CSRF). Ви не можете отримати доступ до вмісту сторінки, але якщо якимось чином ви зможете контролювати час, необхідний для завантаження сторінки, ви зможете витягти потрібну інформацію.
Цього разу буде витягнуто прапор, коли символ буде правильно вгадано через SQLi, відповідь займає більше часу через функцію сну. Тоді ви зможете витягти прапор:
Via Bookmarklets
Ця атака передбачає певну соціальну інженерію, де атакуючий переконує користувача перетягнути та скинути посилання на закладку браузера. Ця закладка міститиме шкідливий javascript код, який, коли його перетягнуть або натиснуть, буде виконано в контексті поточного веб-вікна, обходячи CSP і дозволяючи вкрасти чутливу інформацію таку як куки або токени.
Для отримання додаткової інформації перевірте оригінальний звіт тут.
CSP bypass by restricting CSP
У цьому CTF звіті CSP обходиться шляхом інжекції всередину дозволеного iframe більш обмежувального CSP, який забороняє завантаження конкретного JS файлу, який, потім, через прототипне забруднення або dom clobbering дозволяє зловживати іншим скриптом для завантаження довільного скрипту.
Ви можете обмежити CSP iframe за допомогою атрибута csp
:
У цьому CTF звіті було можливим через впровадження HTML обмежити більше CSP, тому скрипт, що запобігає CSTI, був вимкнений, і, отже, вразливість стала експлуатованою. CSP можна зробити більш обмежувальним, використовуючи HTML мета-теги, а вбудовані скрипти можна вимкнути видаленням входу, що дозволяє їх nonce та включити конкретний вбудований скрипт через sha:
JS exfiltration with Content-Security-Policy-Report-Only
Якщо вам вдасться змусити сервер відповісти заголовком Content-Security-Policy-Report-Only
з значенням, контрольованим вами (можливо, через CRLF), ви зможете вказати на свій сервер, і якщо ви обернете JS контент, який хочете ексфільтрувати, в <script>
, і оскільки, ймовірно, unsafe-inline
не дозволено CSP, це викличе помилку CSP, і частина скрипту (що містить чутливу інформацію) буде надіслана на сервер з Content-Security-Policy-Report-Only
.
Для прикладу перевірте цей CTF звіт.
Витік інформації з CSP та Iframe
Створюється
iframe
, який вказує на URL (назвемо йогоhttps://example.redirect.com
), що дозволений CSP.Цей URL потім перенаправляє на секретний URL (наприклад,
https://usersecret.example2.com
), який не дозволений CSP.Слухаючи подію
securitypolicyviolation
, можна захопити властивістьblockedURI
. Ця властивість розкриває домен заблокованого URI, витікаючи секретний домен, на який перенаправив початковий URL.
Цікаво відзначити, що браузери, такі як Chrome та Firefox, мають різну поведінку в обробці iframe стосовно CSP, що може призвести до потенційного витоку чутливої інформації через невизначену поведінку.
Інша техніка полягає в експлуатації самого CSP для виведення секретного піддомену. Цей метод спирається на алгоритм бінарного пошуку та коригування CSP, щоб включити конкретні домени, які навмисно заблоковані. Наприклад, якщо секретний піддомен складається з невідомих символів, ви можете ітеративно тестувати різні піддомени, змінюючи директиву CSP, щоб блокувати або дозволяти ці піддомени. Ось фрагмент, що показує, як CSP може бути налаштований для полегшення цього методу:
Моніторинг запитів, які блокуються або дозволяються CSP, дозволяє звузити можливі символи в секретному піддомені, врешті-решт виявивши повний URL.
Обидва методи експлуатують нюанси реалізації та поведінки CSP у браузерах, демонструючи, як, здавалося б, безпечні політики можуть ненавмисно витікати чутливу інформацію.
Трюк з тут.