原型污染 0day 漏洞影响所有流行的 Lodash 库版本(附详情和 PoC)
编译:奇安信代码卫士团队
光在GitHub 上就有400多万个项目在使用的 Lodash npm 库被曝存在一个高危的原型污染漏洞。它影响包括最新版本 4.17.11 在内的所有 Lodash 版本。
Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库,内部封装了很多字符串、数字、数组、函数和对象等常见数据类型的处理函数,目的是简化编程过程,帮助程序员更有效地编写并维护 JavaScript 代码。
该漏洞 CVE-2019-10744 是由 Snyk 公司的 Liran Tal 发现的。鉴于 Lodash 每个月的下载量超过8000万次,因此它影响大量前端项目。三个月前,该公司在非常流行的 jQuery JavaScript 前端库中发现了一个类似的原型污染漏洞。
和其它原型污染漏洞一样,执行不安全的递归 JSON 合并函数实现可能导致能够篡改通过原型链影响其它数据的 JavaScript 对象。根据受影响的用例以及是否可利用的情况,这类漏洞的影响范围包括属性注入、代码执行、拒绝服务等。
PoC
函数defaultsDeep可被诱骗使用constructor有效负载添加或修改Object.prototype的属性。
const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"a0": true}}}'
function check() {
mergeFn({}, JSON.parse(payload));
if (({})[`a0`] === true) {
console.log(`Vulnerable to Prototype Pollution via ${payload}`);
}
}
check();
详细分析
原型污染漏洞是影响 JavaScript 的漏洞,它指的是将属性注入现有 JavaScript 语言构建原型的能力,如对象。JavaScript 允许修改所有的Object属性,包括其魔力属性如_proto_、constructor和prototype。操纵这些属性的攻击者能够通过注入其它值的方式覆写或污染 JavaScript 应用程序对象原型。Object.prototype上的属性随后被所有 JavaScript 对象通过原型链继承。之后,可通过触发 JavaScript 异常而导致拒绝服务,或者篡改应用程序源代码,强制攻击者注入的代码路径从而触发远程代码执行。
如下是原型污染发生的两种主要方式:
不安全的 Object 递归合并
按路径定义的属性
不安全的 Object 递归合并
易受攻击的递归合并函数逻辑遵循如下高级别模式:
当源object中包含通过 Object.definProperty() 定义的名为 _proto_属性时,查看该属性是否存在且是目标及源的对象的条件通过,目标合并递归,作为由攻击者定义的 Object 原型和Object源。随后属性被复制到Object属性上。
克隆操作是一种特殊的不安全的递归合并的子类,当递归合并在空对象merge({}.source)上进行时会发生。
Lodash 和 Hoek 就是遭递归合并攻击的两种库。
按路径定义的属性
有一些 JavaScript 库使用 API 来定义基于既定路径上的对象属性值。受影响的函数通常包含签名:theFunction(object, path,value)。
如果攻击者能够控制 “path” 的值,那么就能将该值赋给 _proto_.myValue。myValue随后被复制给该对象类的原型。
攻击类型
原型污染遭操纵的方法如下:
类型 | 来源 | 简要说明 |
拒绝服务 | 客户端 | 这是最可能发生的攻击。 当Object包含被各种操作隐式调用的泛型函数(如toString和valueOf)时就会发生拒绝服务。 攻击者污染Object.prototype.someattr 并将其状态更改为异常值如Int或Object。在本例中,代码失败并可能引发拒绝服务。 例如:如果攻击者通过将其定义为整数的方式污染Object.prototype.toString,如果代码库依赖于someobject.toString(),则会失败。 |
远程代码执行 | 客户端 | 远程代码执行的情况仅在代码库评估了某个特定的对象属性然后执行该评估时才会发生。 例如:eval(someobject.someattr)。在本案例中,如果攻击者污染了Object.prototype.someattr,可能能够借此执行代码。 |
属性注入 | 客户端 | 攻击者污染了代码库赖以获悉信息值的属性,包括 cookie 或令牌等安全属性。 例如:如果代码库检查someuser.isAdmin 的权限,之后当攻击者污染Object.prototype.isAdmin并将其设为true 时,即可获得管理员权限。 |
受影响环境
Application 服务器
Web 服务器
防御措施
1. 冻结原型——使用Object.freeze(Object.prototyp)。
2. 要求对 JSON 输入进行架构验证。
3. 避免使用不安全的递归合并函数。
4. 考虑使用没有原型的对象(如Object.creat(null)),打破原型链并防止污染。
5. 作为最佳实践,使用Map而非Object。
该研究员已将问题告知 Lodash 库的维护人员 John Dalton,并提供了修复方案(https://github.com/lodash/lodash/pull/4336/files)。补丁将在 Lodash 下个版本中发布。
原文链接
https://thehackernews.com/2019/07/lodash-prototype-pollution.html
https://snyk.io/blog/snyk-research-team-discovers-severe-prototype-pollution-security-vulnerabilities-affecting-all-versions-of-lodash/
https://snyk.io/vuln/SNYK-JS-LODASH-450202
题图:Pixabay License
本文由奇安信代码卫士编译,不代表奇安信观点,转载请注明“转自奇安信代码卫士 www.codesafe.cn”。
奇安信代码卫士 (codesafe)
国内首个专注于软件开发安全的产品线。