通过参数篡改导致类型混淆¶
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
清理不受信任的 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);
}
});
参考文献¶
Node.js API:querystring。
常见弱点枚举:CWE-843。