CodeQL 文档

原型污染合并调用

ID: js/prototype-pollution
Kind: path-problem
Security severity: 6.1
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-078
   - external/cwe/cwe-079
   - external/cwe/cwe-094
   - external/cwe/cwe-400
   - external/cwe/cwe-471
   - external/cwe/cwe-915
Query suites:
   - javascript-code-scanning.qls
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

点击查看 CodeQL 仓库中的查询

大多数 JavaScript 对象继承了内置 Object.prototype 对象的属性。原型污染是一种漏洞,攻击者可以通过它修改 Object.prototype。由于大多数对象都继承自受损的 Object.prototype,攻击者可以使用它来篡改应用程序逻辑,并经常升级到远程代码执行或跨站点脚本。

造成原型污染的一种方式是使用不安全的合并扩展函数来递归地从不受信任的源对象复制属性。这样的调用可以修改目标对象可访问的任何对象,而内置的 Object.prototype 通常可以通过特殊属性 __proto__constructor.prototype 访问。攻击者可以利用这一点,通过发送包含这些属性名称的对象来修改 Object.prototype

建议

更新您的库依赖项,以便使用合并扩展函数的安全版本。如果您的库没有固定版本,请切换到另一个库。

示例

在下面的示例中,不受信任的值 req.query.prefs 被解析为 JSON,然后复制到一个新对象中

app.get('/news', (req, res) => {
  let prefs = lodash.merge({}, JSON.parse(req.query.prefs));
})

在 lodash 4.17.11 之前,这会容易受到原型污染的攻击。攻击者可以发送以下 GET 请求

GET /news?prefs={"constructor":{"prototype":{"xxx":true}}}

这会导致 xxx 属性被注入到 Object.prototype 上。通过更新 lodash 版本来修复此问题

{
  "dependencies": {
    "lodash": "^4.17.12"
  }
}

请注意,一些 Web 框架(如 Express)默认使用扩展的 URL 编码来解析查询参数。在这种情况下,即使不使用 JSON.parse,应用程序也可能容易受到攻击。以下示例也容易受到原型污染

app.get('/news', (req, res) => {
  let config = lodash.merge({}, {
    prefs: req.query.prefs
  });
})

在上面的示例中,攻击者可以通过发送以下 GET 请求来造成原型污染

GET /news?prefs[constructor][prototype][xxx]=true

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私