CodeQL 文档

通过参数篡改导致类型混淆

ID: js/type-confusion-through-parameter-tampering
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-843
Query suites:
   - javascript-code-scanning.qls
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

点击查看 CodeQL 仓库中的查询

清理不受信任的 HTTP 请求参数是防止 SQL 注入或路径遍历等注入攻击的常用技术。这有时通过检查请求参数是否包含黑名单子字符串来完成。

但是,清理请求参数时假设其类型为String并使用内置字符串方法(如String.prototype.indexOf)容易受到类型混淆攻击。在类型混淆攻击中,攻击者会篡改 HTTP 请求参数,使其具有Array类型的值,而不是预期的String类型。此外,该数组的内容经过精心设计,利用字符串和数组的一些同名方法的行为差异,从而绕过清理程序。

建议

如果输入类型由用户控制,请检查清理程序输入的运行时类型。

更安全的替代方案是设计应用程序,使其不需要清理,例如对 SQL 查询使用预处理语句。

示例

例如,Node.js 服务器框架通常将请求参数表示为字符串。但是,如果攻击者发送多个具有相同名称的请求参数,那么请求参数将被表示为数组。

在以下示例中,清理程序检查路径是否包含".."字符串,这将允许攻击者访问用户可访问目录之外的内容。

var app = require("express")(),
  path = require("path");

app.get("/user-files", function(req, res) {
  var file = req.param("file");
  if (file.indexOf("..") !== -1) {
    // BAD
    // we forbid relative paths that contain ..
    // as these could leave the public directory
    res.status(400).send("Bad request");
  } else {
    var absolute = path.resolve("/public/" + file);
    console.log("Sending file: %s", absolute);
    res.sendFile(absolute);
  }
});

按此编写,该清理程序无效:类似["../", "/../secret.txt"]的数组将绕过清理程序。该数组不包含".."作为元素,因此对indexOf的调用返回-1。这是有问题的,因为absolute变量的值最终变为"/secret.txt"。这是因为"/public/"与数组的连接导致"/public/../,/../secret.txt"resolve调用将其转换为"/secret.txt"

要修复清理程序,请检查请求参数是否为字符串,而不是数组。

var app = require("express")(),
  path = require("path");

app.get("/user-files", function(req, res) {
  var file = req.param("file");
  if (typeof file !== 'string' || file.indexOf("..") !== -1) {
    // GOOD
    // we forbid relative paths that contain ..
    // as these could leave the public directory
    res.status(400).send("Bad request");
  } else {
    var absolute = path.resolve("/public/" + file);
    console.log("Sending file: %s", absolute);
    res.sendFile(absolute);
  }
});

参考文献

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