mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/nodejs-proto-prototype-p
This commit is contained in:
parent
ab914c2490
commit
8d161fe8f4
@ -1,10 +1,10 @@
|
||||
# NodeJS - \_\_proto\_\_ 和原型污染
|
||||
# NodeJS - \_\_proto\_\_ & prototype Pollution
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## JavaScript中的对象 <a href="#id-053a" id="id-053a"></a>
|
||||
|
||||
JavaScript中的对象本质上是键值对的集合,称为属性。可以使用 `Object.create` 并将 `null` 作为参数来创建一个空对象。此方法允许创建一个没有任何继承属性的对象。
|
||||
JavaScript中的对象本质上是键值对的集合,称为属性。可以使用`Object.create`并将`null`作为参数来创建一个空对象。此方法允许创建没有任何继承属性的对象。
|
||||
```javascript
|
||||
// Run this in the developers tools console
|
||||
console.log(Object.create(null)) // This will output an empty object.
|
||||
@ -13,7 +13,7 @@ console.log(Object.create(null)) // This will output an empty object.
|
||||
|
||||
### JavaScript中的函数和类
|
||||
|
||||
在JavaScript中,类和函数密切相关,函数通常作为类的构造函数。尽管JavaScript缺乏原生类支持,但构造函数可以模拟类的行为。
|
||||
在JavaScript中,类和函数紧密相连,函数通常作为类的构造函数。尽管JavaScript缺乏原生的类支持,但构造函数可以模拟类的行为。
|
||||
```javascript
|
||||
// Run this in the developers tools console
|
||||
|
||||
@ -31,23 +31,23 @@ var employee1 = new Employee("Generic Employee", "Developer")
|
||||
|
||||
employee1.__proto__
|
||||
```
|
||||
### JavaScript中的原型
|
||||
### Prototypes in JavaScript
|
||||
|
||||
JavaScript允许在运行时修改、添加或删除原型属性。这种灵活性使得类功能的动态扩展成为可能。
|
||||
JavaScript 允许在运行时修改、添加或删除原型属性。这种灵活性使得类功能的动态扩展成为可能。
|
||||
|
||||
像`toString`和`valueOf`这样的函数可以被改变以改变它们的行为,展示了JavaScript原型系统的适应性。
|
||||
像 `toString` 和 `valueOf` 这样的函数可以被改变以改变它们的行为,展示了 JavaScript 原型系统的适应性。
|
||||
|
||||
## 继承
|
||||
## Inheritance
|
||||
|
||||
在基于原型的编程中,属性/方法由对象从类中继承。这些类是通过将属性/方法添加到另一个类的实例或一个空对象来创建的。
|
||||
在基于原型的编程中,属性/方法是由对象从类中继承的。这些类是通过将属性/方法添加到另一个类的实例或一个空对象来创建的。
|
||||
|
||||
需要注意的是,当一个属性被添加到作为其他对象原型的对象(例如`myPersonObj`)时,继承的对象可以访问这个新属性。然而,除非明确调用,否则这个属性不会自动显示。
|
||||
需要注意的是,当一个属性被添加到作为其他对象原型的对象(例如 `myPersonObj`)时,继承的对象可以访问这个新属性。然而,除非明确调用,否则这个属性不会自动显示。
|
||||
|
||||
## \_\_proto\_\_ 污染 <a href="#id-0d0a" id="id-0d0a"></a>
|
||||
## \_\_proto\_\_ pollution <a href="#id-0d0a" id="id-0d0a"></a>
|
||||
|
||||
## 探索JavaScript中的原型污染
|
||||
## Exploring Prototype Pollution in JavaScript
|
||||
|
||||
JavaScript对象由键值对定义,并从JavaScript对象原型继承。这意味着改变对象原型可以影响环境中的所有对象。
|
||||
JavaScript 对象是由键值对定义的,并且继承自 JavaScript 对象原型。这意味着改变对象原型可以影响环境中的所有对象。
|
||||
|
||||
让我们用一个不同的例子来说明:
|
||||
```javascript
|
||||
@ -76,9 +76,9 @@ car1.announce() // Outputs "Beep beep!"
|
||||
car1.__proto__.__proto__.isVehicle = true
|
||||
console.log(car1.isVehicle) // Outputs true
|
||||
```
|
||||
## 原型污染
|
||||
## prototype pollution
|
||||
|
||||
对于限制使用 `__proto__` 的场景,修改函数的原型是一个替代方案:
|
||||
在`__proto__`使用受到限制的情况下,修改函数的原型是一个替代方案:
|
||||
```javascript
|
||||
function Vehicle(model) {
|
||||
this.model = model
|
||||
@ -121,7 +121,7 @@ console.log("Hello!")
|
||||
|
||||
### 从类到 Object.prototype
|
||||
|
||||
在一个可以 **污染特定对象** 的场景中,如果你需要 **到达 `Object.prototype`**,你可以使用以下代码进行搜索:
|
||||
在一个可以 **污染特定对象** 的场景中,如果你需要 **到达 `Object.prototype`**,你可以使用类似以下代码进行搜索:
|
||||
```javascript
|
||||
// From https://blog.huli.tw/2022/05/02/en/intigriti-revenge-challenge-author-writeup/
|
||||
|
||||
@ -144,7 +144,7 @@ console.log(key1 + "." + key2)
|
||||
```
|
||||
### 数组元素污染
|
||||
|
||||
请注意,由于您可以污染 JS 中对象的属性,如果您有权污染数组,您也可以通过 **索引** 污染 **数组的值**(请注意,您无法覆盖值,因此您需要污染以某种方式使用但未写入的索引)。
|
||||
注意,既然你可以污染 JS 中对象的属性,如果你有权限污染一个数组,你也可以通过 **索引** 污染 **数组的值**(注意你不能覆盖值,因此你需要污染以某种方式被使用但未被写入的索引)。
|
||||
```javascript
|
||||
c = [1, 2]
|
||||
a = []
|
||||
@ -154,7 +154,7 @@ b[0] //undefined
|
||||
b[1] //"yolo"
|
||||
c[1] // 2 -- not
|
||||
```
|
||||
### Html 元素污染
|
||||
### Html elements pollution
|
||||
|
||||
当通过 JS 生成 HTML 元素时,可以 **覆盖** **`innerHTML`** 属性,使其写入 **任意 HTML 代码。** [Idea and example from this writeup](https://blog.huli.tw/2022/04/25/en/intigriti-0422-xss-challenge-author-writeup/).
|
||||
```javascript
|
||||
@ -173,7 +173,7 @@ settings[root][ownerDocument][body][innerHTML]="<svg onload=alert(document.domai
|
||||
|
||||
原型污染是由于应用程序中的缺陷导致的,该缺陷允许覆盖 `Object.prototype` 上的属性。这意味着大多数对象从 `Object.prototype` 派生其属性。
|
||||
|
||||
最简单的示例是向一个 **未定义的对象属性** 添加一个值,该属性将被检查,例如:
|
||||
最简单的示例是向将要被检查的对象的 **未定义属性** 添加一个值,例如:
|
||||
```javascript
|
||||
if (user.admin) {
|
||||
```
|
||||
@ -183,7 +183,7 @@ Object.prototype.isAdmin = true
|
||||
let user = {}
|
||||
user.isAdmin // true
|
||||
```
|
||||
这个机制涉及操纵属性,以便如果攻击者控制某些输入,他们可以修改应用程序中所有对象的原型。这种操纵通常涉及设置 `__proto__` 属性,在 JavaScript 中,这与直接修改对象的原型同义。
|
||||
该机制涉及操纵属性,以便如果攻击者控制某些输入,他们可以修改应用程序中所有对象的原型。这种操纵通常涉及设置 `__proto__` 属性,在 JavaScript 中,这与直接修改对象的原型同义。
|
||||
|
||||
成功执行此攻击的条件,如特定 [研究](https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf) 中所述,包括:
|
||||
|
||||
@ -213,12 +213,12 @@ client-side-prototype-pollution.md
|
||||
|
||||
### CVE-2019–11358:通过 jQuery $ .extend 的原型污染攻击
|
||||
|
||||
[有关更多详细信息,请查看本文](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) 在 jQuery 中,`$ .extend` 函数如果深拷贝功能使用不当,可能导致原型污染。此函数通常用于克隆对象或合并来自默认对象的属性。然而,当配置错误时,原本用于新对象的属性可能会被分配给原型。例如:
|
||||
[有关更多详细信息,请查看这篇文章](https://itnext.io/prototype-pollution-attack-on-nodejs-applications-94a8582373e7) 在 jQuery 中,`$ .extend` 函数如果深拷贝功能使用不当,可能导致原型污染。此函数通常用于克隆对象或合并来自默认对象的属性。然而,当配置错误时,原本用于新对象的属性可能会被分配给原型。例如:
|
||||
```javascript
|
||||
$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))
|
||||
console.log({}.devMode) // Outputs: true
|
||||
```
|
||||
此漏洞被识别为 CVE-2019–11358,说明深拷贝如何无意中修改原型,从而导致潜在的安全风险,例如如果像 `isAdmin` 这样的属性在没有适当存在验证的情况下被检查,则可能导致未经授权的管理员访问。
|
||||
此漏洞被识别为 CVE-2019–11358,说明深拷贝如何意外修改原型,从而导致潜在的安全风险,例如如果像 `isAdmin` 这样的属性在没有适当存在验证的情况下被检查,则可能导致未授权的管理员访问。
|
||||
|
||||
### CVE-2018–3721, CVE-2019–10744: 通过 lodash 的原型污染攻击
|
||||
|
||||
@ -228,9 +228,9 @@ console.log({}.devMode) // Outputs: true
|
||||
|
||||
### 另一个包含 CVE 的教程
|
||||
|
||||
{{#ref}}
|
||||
https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2
|
||||
{{#endref}}
|
||||
|
||||
- [https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2](https://infosecwriteups.com/javascript-prototype-pollution-practice-of-finding-and-exploitation-f97284333b2)
|
||||
|
||||
|
||||
### 检测原型污染的工具
|
||||
|
||||
@ -250,7 +250,7 @@ Handlebars 模板引擎易受原型污染攻击。此漏洞源于 `javascript-co
|
||||
利用过程利用 Handlebars 生成的 AST(抽象语法树),遵循以下步骤:
|
||||
|
||||
1. **解析器的操控**: 最初,解析器通过 `NumberLiteral` 节点强制值为数字。原型污染可以规避此限制,从而允许插入非数字字符串。
|
||||
2. **编译器的处理**: 编译器可以处理 AST 对象或字符串模板。如果 `input.type` 等于 `Program`,则输入被视为预解析,这可以被利用。
|
||||
2. **编译器的处理**: 编译器可以处理 AST 对象或字符串模板。如果 `input.type` 等于 `Program`,则输入被视为预解析的,可以被利用。
|
||||
3. **代码注入**: 通过操控 `Object.prototype`,可以将任意代码注入模板函数,这可能导致远程代码执行。
|
||||
|
||||
一个演示 Handlebars 漏洞利用的示例:
|
||||
@ -281,9 +281,9 @@ const template = Handlebars.precompile(source)
|
||||
|
||||
console.log(eval("(" + template + ")")["main"].toString())
|
||||
```
|
||||
此代码展示了攻击者如何将任意代码注入到 Handlebars 模板中。
|
||||
这段代码展示了攻击者如何将任意代码注入到 Handlebars 模板中。
|
||||
|
||||
**外部参考**:在 'flat' 库中发现了与原型污染相关的问题,详细信息请参见此处:[GitHub 上的问题](https://github.com/hughsk/flat/issues/105)。
|
||||
**外部参考**:在 'flat' 库中发现了与原型污染相关的问题,详细信息如下:[GitHub 上的问题](https://github.com/hughsk/flat/issues/105)。
|
||||
|
||||
**外部参考**:[与 'flat' 库中的原型污染相关的问题](https://github.com/hughsk/flat/issues/105)
|
||||
|
||||
@ -344,7 +344,7 @@ requests.get(TARGET_URL)
|
||||
4. **无原型对象**:可以使用 `Object.create(null)` 创建没有原型属性的对象。
|
||||
5. **使用 Map**:应使用 `Map` 来存储键值对,而不是 `Object`。
|
||||
6. **库更新**:通过定期更新库来纳入安全补丁。
|
||||
7. **Linter 和静态分析工具**:使用如 ESLint 之类的工具,配合适当的插件,检测和防止原型污染漏洞。
|
||||
7. **代码检查和静态分析工具**:使用如 ESLint 之类的工具,配合适当的插件,检测和防止原型污染漏洞。
|
||||
8. **代码审查**:实施全面的代码审查,以识别和修复与原型污染相关的潜在风险。
|
||||
9. **安全培训**:教育开发人员了解原型污染的风险及编写安全代码的最佳实践。
|
||||
10. **谨慎使用库**:在使用第三方库时要谨慎。评估其安全态势并审查其代码,特别是那些操作对象的库。
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user