lodash原型链污染漏洞大全
看到一篇肥肠好的博客
https://www.anquanke.com/post/id/248170
package.json
lodash.defaultsDeep
2019 年 7 月 2 日,Snyk 发布了一个高严重性原型污染安全漏洞(CVE-2019-10744),影响了小于 4.17.12 的所有版本的 lodash。
环境搭建
这里借用了Xnuca的源码
官方的验证poc
很迷,跑上面的poc不行
我的demo
使用vscode运行调试server.js
调试lodash.defaultsDeep,
单步执行来到了这里
这时候随便关注一个全局变量
还没被污染
来到最后一个函数时发现被污染,于是进入后发现调用了func.call
变量里面有亲爱的键值了
再单步执行时果然污染了原型链
原理:
defaultsDeep->baseRest->overRest->apply->func.call
简单的说就是overRest里面有个合并的逻辑,然后construct被当作键名传入apply,apply会把它拿来调用
所以这里就简单复现一下,
可以看到,随便点开一个变量,它的原型都被污染了:"whoami": "Vulnerable"
成功在
__proto__
属性中添加了一个whoami
属性,值为Vulnerable
,污染成功。
官方使用的修复方式是直接上waf
在这部分漏洞函数直接加waf
该修复包括以下两项安全检查:
- 过滤了
constructor
以确保我们不会污染全局对象constructor
- 还添加了一个测试用例以确保将来不会发生回归
最终payload
payload1
payload2
payload3
lodash.merge
lodash版本:4.17.4
4.17.11亲测不行
poc
Lodash.merge 作为 lodash 中的对象合并插件,他可以递归合并
sources
来源对象自身和继承的可枚举属性到object
目标对象,以创建父映射对象:当两个键相同时,生成的对象将具有最右边的键的值。如果多个对象相同,则新生成的对象将只有一个与这些对象相对应的键和值。
但是这里的 lodash.merge 操作实际上存在原型链污染漏洞,下面对其进行简单的分析,这里使用 4.17.4 版本的 Lodash。
- node_modules/lodash/merge.js
merge.js 调用了 baseMerge 方法,则定位到 baseMerge:
- node_modules/lodash/_baseMerge.js
如果 srcValue 是一个对象则进入 baseMergeDeep 方法,跟进 baseMergeDeep 方法:
- node_modules/lodash/_baseMergeDeep.js
跟进 assignMergeValue 方法:
- node_modules/lodash/_assignMergeValue.js:
跟进 baseAssignValue 方法:
- node_modules/lodash/_baseAssignValue.js
这里的 if 判断可以绕过,最终进入 object[key] = value
的赋值操作。
最终payload
在 lodash.merge 方法造成的原型链污染中,为了实现代码执行,我们常常会污染
sourceURL
属性,即给所有 Object 对象中都插入一个sourceURL
属性,然后通过 lodash.template 方法中的拼接实现任意代码执行漏洞。后文中我们会通过 [Code-Breaking 2018] Thejs 这道题来仔细讲解。
lodash.mergeWith
这个方法类似于 merge
方法。但是它还会接受一个 customizer
,以决定如何进行合并。 如果 customizer
返回 undefined
将会由合并处理方法代替。
该方法与 merge
方法一样存在原型链污染漏洞,下面给出一个验证漏洞的 POC:
成功在类型为 Object 的 a 对象的 __proto__
属性中添加了一个 whoami
属性,值为 Vulnerable
,污染成功。
最终payload
同merge
lodash.set
lodash.set的使用:
Lodash.set 方法可以用来设置值到对象对应的属性路径上,如果没有则创建这部分路径。 缺少的索引属性会创建为数组,而缺少的属性会创建为对象。
- 示例:
既然是设置属性,那么在使用 Lodash.set 方法时,如果没有对传入的参数进行过滤,则可能会造成原型链污染。下面给出一个验证漏洞的 POC:
这个没什么原理,因为函数的功能本身就提供了设置属性的操作。
验证poc
最终payload
lodash.setWith
Lodash.setWith 方法类似 set
方法。但是它还会接受一个 customizer
,用来调用并决定如何设置对象路径的值。 如果 customizer
返回 undefined
将会有它的处理方法代替。
该方法与 set
方法一样可以进行原型链污染,下面给出一个验证漏洞的 POC:
验证poc
至此,我们已经对 lodash 模块中的几个原型链污染做了验证,可以成功污染原型中的属性。但如果要进行代码执行,则还需要配合 eval()
方法的执行或模板引擎的渲染。