NodeJS - __proto__ & prototype Pollution
JavaScript 中的对象
JavaScript 中的对象本质上是键值对的集合,称为属性。可以使用 Object.create
并将 null
作为参数来创建一个空对象。此方法允许创建没有任何继承属性的对象。
一个空对象类似于一个空字典,表示为{}
。
JavaScript中的函数和类
在JavaScript中,类和函数密切相关,函数通常作为类的构造函数。尽管JavaScript缺乏原生类支持,但构造函数可以模拟类的行为。
Prototypes in JavaScript
JavaScript 允许在运行时修改、添加或删除原型属性。这种灵活性使得类功能的动态扩展成为可能。
像 toString
和 valueOf
这样的函数可以被改变以改变它们的行为,展示了 JavaScript 原型系统的适应性。
Inheritance
在基于原型的编程中,属性/方法由对象从类中继承。这些类是通过将属性/方法添加到另一个类的实例或一个空对象来创建的。
需要注意的是,当一个属性被添加到作为其他对象原型的对象(例如 myPersonObj
)时,继承的对象可以访问这个新属性。然而,除非明确调用,否则这个属性不会自动显示。
__proto__ pollution
Exploring Prototype Pollution in JavaScript
JavaScript 对象由键值对定义,并从 JavaScript 对象原型继承。这意味着改变对象原型可以影响环境中的所有对象。
让我们用一个不同的例子来说明:
通过以下方式可以访问 Object 原型:
通过向 Object 原型添加属性,每个 JavaScript 对象将继承这些新属性:
prototype pollution
对于限制使用 __proto__
的场景,修改函数的原型是一个替代方案:
这仅影响从 Vehicle
构造函数创建的对象,使它们具有 beep
、hasWheels
、honk
和 isElectric
属性。
通过原型污染全局影响 JavaScript 对象的两种方法包括:
直接污染
Object.prototype
:
污染常用结构的构造函数原型:
在这些操作之后,每个 JavaScript 对象都可以执行 goodbye
和 greet
方法。
污染其他对象
从类到 Object.prototype
在一个可以 污染特定对象 的场景中,如果你需要 到达 Object.prototype
,你可以使用以下代码进行搜索:
数组元素污染
注意,由于您可以污染 JS 中对象的属性,如果您有权污染数组,您也可以通过索引污染数组的值(请注意,您不能覆盖值,因此您需要污染以某种方式使用但未被写入的索引)。
Html elements pollution
通过 JS 生成 HTML 元素时,可以 覆盖 innerHTML
属性,使其写入 任意 HTML 代码。 这个写作的想法和示例.
示例
基本示例
原型污染是由于应用程序中的缺陷导致的,该缺陷允许覆盖 Object.prototype
上的属性。这意味着大多数对象从 Object.prototype
派生其属性。
最简单的示例是向一个未定义属性的对象添加一个值,该对象将被检查,例如:
如果属性 admin
未定义,则可以利用 PP 并将其设置为 True,例如:
该机制涉及操纵属性,以便如果攻击者控制某些输入,他们可以修改应用程序中所有对象的原型。这种操纵通常涉及设置 __proto__
属性,在 JavaScript 中,这与直接修改对象的原型同义。
成功执行此攻击的条件,如特定 研究 中所述,包括:
执行递归合并。
根据路径定义属性。
克隆对象。
Override function
Proto Pollution to RCE
Prototype Pollution to RCE其他有效载荷:
Client-side prototype pollution to XSS
Client Side Prototype PollutionCVE-2019–11358: 通过 jQuery $ .extend 的原型污染攻击
有关更多详细信息,请查看这篇文章 在 jQuery 中,$ .extend
函数如果深拷贝功能使用不当,可能导致原型污染。此函数通常用于克隆对象或合并默认对象的属性。然而,当配置错误时,原本用于新对象的属性可能会被分配给原型。例如:
此漏洞被识别为 CVE-2019–11358,说明深拷贝如何无意中修改原型,从而导致潜在的安全风险,例如如果像 isAdmin
这样的属性在没有适当存在验证的情况下被检查,可能会导致未经授权的管理员访问。
CVE-2018–3721, CVE-2019–10744: 通过 lodash 的原型污染攻击
Lodash 遇到了类似的原型污染漏洞 (CVE-2018–3721, CVE-2019–10744)。这些问题在版本 4.17.11 中得到了修复。
另一个包含 CVE 的教程
检测原型污染的工具
Server-Side-Prototype-Pollution-Gadgets-Scanner: Burp Suite 扩展,旨在检测和分析 Web 应用程序中的服务器端原型污染漏洞。该工具自动化扫描请求的过程,以识别潜在的原型污染问题。它利用已知的工具 - 利用原型污染执行有害操作的方法 - 特别关注 Node.js 库。
server-side-prototype-pollution: 此扩展识别服务器端原型污染漏洞。它使用在 server side prototype pollution 中描述的技术。
NodeJS 中的 AST 原型污染
NodeJS 在 JavaScript 中广泛使用抽象语法树 (AST) 进行模板引擎和 TypeScript 等功能。本节探讨与模板引擎(特别是 Handlebars 和 Pug)中的原型污染相关的漏洞。
Handlebars 漏洞分析
Handlebars 模板引擎易受原型污染攻击。此漏洞源于 javascript-compiler.js
文件中的特定函数。例如,appendContent
函数在存在时会连接 pendingContent
,而 pushSource
函数在添加源后会将 pendingContent
重置为 undefined
。
利用过程
利用过程利用 Handlebars 生成的 AST(抽象语法树),遵循以下步骤:
解析器的操控:最初,解析器通过
NumberLiteral
节点强制值为数字。原型污染可以规避此限制,从而允许插入非数字字符串。编译器的处理:编译器可以处理 AST 对象或字符串模板。如果
input.type
等于Program
,则输入被视为预解析,这可以被利用。代码注入:通过操控
Object.prototype
,可以将任意代码注入模板函数,这可能导致远程代码执行。
一个演示 Handlebars 漏洞利用的示例:
这段代码展示了攻击者如何将任意代码注入到 Handlebars 模板中。
外部参考:在 'flat' 库中发现了与原型污染相关的问题,详细信息见此处:GitHub 问题。
Python 中原型污染利用的示例:
Pug 漏洞
Pug,另一个模板引擎,面临着类似的原型污染风险。详细信息可在关于 Pug 中的 AST 注入 的讨论中找到。
Pug 中原型污染的示例:
预防措施
为了降低原型污染的风险,可以采用以下策略:
对象不可变性:可以通过应用
Object.freeze
使Object.prototype
变为不可变。输入验证:JSON 输入应严格根据应用程序的架构进行验证。
安全合并函数:应避免不安全的递归合并函数使用。
无原型对象:可以使用
Object.create(null)
创建没有原型属性的对象。使用 Map:应使用
Map
来存储键值对,而不是Object
。库更新:通过定期更新库来纳入安全补丁。
Linter 和静态分析工具:使用像 ESLint 这样的工具及适当的插件来检测和防止原型污染漏洞。
代码审查:实施彻底的代码审查,以识别和修复与原型污染相关的潜在风险。
安全培训:教育开发人员有关原型污染的风险和编写安全代码的最佳实践。
谨慎使用库:在使用第三方库时要谨慎。评估其安全态势并审查其代码,特别是那些操作对象的库。
运行时保护:采用运行时保护机制,例如使用安全导向的 npm 包,这些包可以检测和防止原型污染攻击。
参考文献
Last updated