NodeJS - __proto__ & prototype Pollution
JavaScript中的对象
JavaScript中的对象本质上是键值对的集合,称为属性。可以使用Object.create
方法并将null
作为参数来创建一个空对象。这种方法允许创建一个没有任何继承属性的对象。
JavaScript中的函数和类
在JavaScript中,类和函数密切相关,函数经常充当类的构造函数。尽管JavaScript缺乏原生类支持,但构造函数可以模拟类的行为。
JavaScript中的原型
JavaScript允许在运行时修改、添加或删除原型属性。这种灵活性使得可以动态扩展类的功能。
toString
和valueOf
等函数可以被修改以改变它们的行为,展示了JavaScript原型系统的适应性。
继承
在基于原型的编程中,属性/方法是从类中的对象继承的。这些类是通过将属性/方法添加到另一个类的实例或空对象中创建的。
值得注意的是,当将属性添加到充当其他对象原型的对象(如myPersonObj
)时,继承对象就可以访问这个新属性。然而,除非显式调用,否则这个属性不会自动显示。
__proto__污染
探索JavaScript中的原型污染
JavaScript对象由键值对定义,并从JavaScript对象原型继承。这意味着修改Object原型可能会影响环境中的所有对象。
让我们使用一个不同的示例来说明:
可以通过以下方式访问对象原型:
通过向Object原型添加属性,每个JavaScript对象都将继承这些新属性:
原型污染
对于限制了 __proto__
使用的情况,修改函数的原型是一种替代方法:
这仅影响从Vehicle
构造函数创建的对象,为它们提供beep
、hasWheels
、honk
和isElectric
属性。
全局影响JavaScript对象的两种方法包括:
直接污染
Object.prototype
:
污染常用结构的构造函数原型:
污染其他对象
从类到Object.prototype
在一个场景中,您可以污染特定对象并且需要访问Object.prototype
,您可以使用类似以下代码进行搜索:
数组元素污染
请注意,正如您可以污染JS对象的属性一样,如果您可以污染一个数组,您也可以污染可以通过索引访问的数组的值(请注意,您无法覆盖值,因此您需要污染某种方式使用但未写入的索引)。
Html元素污染
在通过JS生成HTML元素时,可以覆盖 innerHTML
属性,使其编写任意HTML代码。 灵感和示例来自此文章。
例子
基本示例
原型污染是由于应用程序中存在漏洞,允许在 Object.prototype
上覆盖属性。这意味着由于大多数对象从 Object.prototype
派生其属性
最简单的示例是向将要被检查的对象的未定义属性添加一个值,如:
如果属性 admin
未定义,就有可能滥用原型污染并将其设置为 True,类似于以下操作:
这背后的机制涉及操纵属性,以便如果攻击者控制某些输入,他们可以修改应用程序中所有对象的原型。这种操纵通常涉及设置 __proto__
属性,在JavaScript中,这与直接修改对象的原型是同义的。
可以成功执行此攻击的条件,如特定研究中所述,包括:
执行递归合并。
基于路径定义属性。
克隆对象。
覆盖函数
Proto污染到RCE
Prototype Pollution to RCE其他有效载荷:
客户端原型污染到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应用程序中的服务器端原型污染漏洞。该工具自动化扫描请求的过程,以识别潜在的原型污染问题。它利用已知的小工具(gadgets)- 利用原型污染执行有害操作的方法 - 特别关注Node.js库。
server-side-prototype-pollution:此扩展程序识别服务器端原型污染漏洞。它使用服务器端原型污染中描述的技术。
NodeJS中的AST原型污染
NodeJS在JavaScript中广泛使用抽象语法树(AST)来实现功能,如模板引擎和TypeScript。本节探讨了与模板引擎中原型污染相关的漏洞,特别是Handlebars和Pug。
Handlebars漏洞分析
Handlebars模板引擎容易受到原型污染攻击。此漏洞源自javascript-compiler.js
文件中的特定函数。例如,appendContent
函数会在存在pendingContent
时连接它,而pushSource
函数在添加源代码后将pendingContent
重置为undefined
。
利用过程
利用AST(抽象语法树)由Handlebars生成,遵循以下步骤:
解析器的操纵:首先,解析器通过
NumberLiteral
节点强制值为数字。原型污染可以绕过这一点,使非数字字符串插入。编译器的处理:编译器可以处理AST对象或字符串模板。如果
input.type
等于Program
,则将输入视为预解析,可以被利用。代码注入:通过操纵
Object.prototype
,可以将任意代码注入模板函数,可能导致远程代码执行。
演示利用Handlebars漏洞的示例:
这段代码展示了攻击者如何将任意代码注入Handlebars模板中。
外部参考: 在'flat'库中发现了与原型污染相关的问题,详细信息请参阅: GitHub上的问题。
外部参考: 与'flat'库中原型污染相关的问题
Python中原型污染利用的示例:
Pug漏洞
Pug,另一个模板引擎,面临着原型污染的类似风险。有关更详细的信息,请参阅Pug中的AST注入讨论。
预防措施
为了减少原型污染的风险,可以采用以下列出的策略:
对象不可变性:可以通过应用
Object.freeze
来使Object.prototype
不可变。输入验证:JSON 输入应该严格根据应用程序的模式进行验证。
安全合并函数:应避免不安全使用递归合并函数。
无原型对象:可以使用
Object.create(null)
来创建没有原型属性的对象。使用 Map:应该使用
Map
而不是Object
来存储键值对。库更新:可以通过定期更新库来整合安全补丁。
代码检查工具:使用诸如 ESLint 等适当插件的工具来检测和防止原型污染漏洞。
代码审查:实施彻底的代码审查,以识别和修复与原型污染相关的潜在风险。
安全培训:教育开发人员有关原型污染的风险以及编写安全代码的最佳实践。
谨慎使用库:在使用第三方库时要谨慎。评估它们的安全状况并审查它们的代码,特别是那些操作对象的代码。
运行时保护:采用运行时保护机制,例如使用专注于安全的 npm 包,可以检测和防止原型污染攻击。
参考资料
最后更新于