免责声明
本号所写文章方法和工具只用于学习和交流,严禁使用文章所述内容中的方法未经许可的情况下对生产系统进行方法验证实施,发生一切问题由相关个人承担法律责任,其与本号无关。
什么是原型污染
原型污染是一种 JavaScript 漏洞,它使攻击者能够向全局对象原型添加任意属性,然后这些属性可能被用户定义的对象继承。原型污染通常无法作为一个独立的漏洞利用,但它允许攻击者控制原本无法访问的对象的属性。如果应用程序随后以不安全的方式处理攻击者控制的属性,则这可能会与其他漏洞相关联。在客户端 JavaScript 中,这通常会导致 DOM XSS,而服务器端原型污染甚至会导致远程代码执行。
在JavaScript函数以递归方式将包含用户可控制属性的对象合并到现有对象中时,如果没有先清理键,就可能出现原型污染漏洞。这是因为攻击者可以利用这个过程,注入具有特殊意义的键(如__proto__
)以及任意嵌套属性。这种漏洞的存在基于JavaScript的一些特性,特别是关于对象的原型和继承机制。
JavaScript中的每个对象都链接到某种类型的另一个对象,即其原型。对象会自动继承其分配的原型的所有属性(除非它们自己已经拥有相同键的属性)。例如,字符串会自动分配内置的String.prototype ,新对象能够继承原型的属性和方法,这是正常的继承机制。然而,当在合并对象的递归操作中缺乏对键的清理时,攻击者就有了可乘之机。
例如,假设存在一个函数,它递归地合并来自用户输入的对象到一个已有的对象中。如果用户输入的对象包含了__proto__
属性,这个属性就可能被误添加到目标对象的原型上,而不是作为目标对象自身的属性处理。这样一来,攻击者就能够通过污染原型来影响后续基于该原型创建的对象的行为。这可能导致一系列安全问题,如修改对象的默认行为,或者通过继承被污染的原型,使原本安全的对象变得可被攻击利用。
在JavaScript中,__proto__
是一个对象的默认原型属性,它指向该对象的原型对象。原型对象是JavaScript中实现继承机制的关键,它允许对象共享一组公共的属性和方法。每个对象都有一个__proto__
属性,通过这个属性,对象可以访问其原型对象上的所有属性和方法。
在进行对象合并(merge)操作时,如果直接将一个对象的属性复制到另一个对象上,而不考虑属性的特殊含义,就有可能引发原型污染问题。具体来说,如果源对象中包含__proto__
属性,并且在合并过程中没有对其进行特殊处理,那么这个属性就会被复制到目标对象的原型上,而不是目标对象本身。这样一来,所有基于该原型创建的对象都会受到这个属性的影响,从而导致不可预见的行为。
攻击者可以利用原型污染漏洞,通过注入恶意的__proto__
属性来改变对象的行为。例如,攻击者可以创建一个对象,其中__proto__
属性指向一个包含有害值的对象。当这个对象被合并到目标对象时,目标对象的原型就会被污染,从而影响到所有基于该原型创建的对象。这些对象可能会以危险的方式使用被污染的属性,导致应用程序出现安全问题。
成功利用原型污染需要有原型污染源(能够使用任意属性对原型对象进行中毒的任何输入。)、接收器(允许执行任意代码的 JavaScript 函数或 DOM 元素)、可利用的小工具(未经适当筛选或清理而传递到 Sink 的任何属性。)
原型污染源是任何用户可控制的输入,可用于向原型对象添加任意属性。
最常见的来源如下:
基于JSON的输入
:如果应用程序在处理JSON输入时没有进行适当的验证和清理,攻击者可以通过构造恶意的JSON数据来污染原型对象。
Web消息
:应用程序在处理接收到的Web消息时没有进行适当的验证和清理,攻击者可以通过发送恶意的消息来污染原型对象。
URL参数
:应用程序在处理URL参数时没有进行适当的验证和清理,攻击者可以通过构造恶意的URL参数来污染原型对象。
URL参数原型污染源
包含攻击者构造的查询字符串URL如下:
https://example.com/?__proto__[evilProperty]=payload
这里的 __proto__
是一个特殊的属性,用于指向对象的原型。evilProperty 是攻击者希望添加或修改的属性名,payload 是攻击者希望设置的属性值。当应用程序接收到这个 URL 并解析参数时,如果没有对 __proto__
属性进行适当的处理,就会导致原型污染。例如,如果应用程序将 URL 参数转换为一个 JavaScript 对象,那么这个对象的原型就会被添加一个名为 evilProperty 的属性,其值为 payload。
JSON 输入原型污染
JSON.parse() 方法用于将JSON字符串转换为JavaScript对象。它将JSON对象中的键视为任意字符串,包括 __proto__
之类的内容。如果在解析JSON时,能够控制包含 " __proto__
" 键值对的JSON字符串输入到JSON.parse() 中,就可能会修改对象的原型,造成原型污染。
原型污染接收器
接收器本质上只是一个JavaScript函数或DOM元素,您可以通过原型污染访问它。这使您能够执行任意JavaScript或系统命令。由于原型污染允许您控制原本无法访问的属性,因此这可能使您能够在目标应用程序中访问许多额外的sink。
原型污染小工具
“小工具”(gadget)通常指的是应用程序中可以被攻击者利用的特定代码路径或功能。由于应用程序对用户输入的处理不当而导致的。在原型污染的情况下,小工具是指那些可以被攻击者通过污染原型来访问和利用的JavaScript函数或DOM元素。
通过客户端原型污染
,攻击者可以利用DOMXSS。例如,如果应用程序使用了eval()函数来处理用户输入,那么攻击者可以通过污染原型来注入恶意代码,从而执行任意JavaScript代码。
服务器端原型污染
:在服务器端,攻击者可以通过污染原型来执行任意代码。例如,如果应用程序使用了for...in...循环来处理用户输入,那么攻击者可以通过污染原型来注入恶意属性,从而执行任意代码。
原创 老付话安全