服务器端 URL 重定向¶
ID: js/server-side-unvalidated-url-redirection
Kind: path-problem
Security severity: 6.1
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-601
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
在没有验证输入的情况下直接将用户输入合并到 URL 重定向请求中会助长网络钓鱼攻击。在这些攻击中,毫无戒心的用户可能会被重定向到一个恶意网站,该网站看起来与他们打算访问的真实网站非常相似,但实际上由攻击者控制。
建议¶
为了防止不可信的 URL 重定向,建议避免将用户输入直接放入重定向 URL 中。相反,在服务器上维护一个授权重定向列表;然后根据提供的用户输入从该列表中进行选择。
如果这不可行,那么应该通过其他方式验证用户输入,例如验证目标 URL 是否与当前页面的主机相同。
示例¶
以下示例显示了一个 HTTP 请求参数在没有验证输入的情况下直接用于 URL 重定向,这会助长网络钓鱼攻击
const app = require("express")();
app.get("/redirect", function (req, res) {
// BAD: a request parameter is incorporated without validation into a URL redirect
res.redirect(req.query["target"]);
});
解决此问题的一种方法是在执行重定向之前,根据已知的固定字符串验证用户输入
const app = require("express")();
const VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html";
app.get("/redirect", function (req, res) {
// GOOD: the request parameter is validated against a known fixed string
let target = req.query["target"];
if (VALID_REDIRECT === target) {
res.redirect(target);
} else {
res.redirect("/");
}
});
或者,我们可以通过解析它相对于具有已知主机的基本 URL 并验证主机是否保持不变来检查目标 URL 是否没有重定向到其他主机
const app = require("express")();
function isLocalUrl(path) {
try {
return (
// TODO: consider substituting your own domain for example.com
new URL(path, "https://example.com").origin === "https://example.com"
);
} catch (e) {
return false;
}
}
app.get("/redirect", function (req, res) {
// GOOD: check that we don't redirect to a different host
let target = req.query["target"];
if (isLocalUrl(target)) {
res.redirect(target);
} else {
res.redirect("/");
}
});
请注意,如上所述,上面的代码将允许重定向到 example.com
上的 URL,这虽然无害,但可能并非预期。您可以用自己的域(如果已知)替换 example.com
以防止这种情况。
参考资料¶
通用弱点枚举:CWE-601.