我的应用程序中有以下JavaScipt函数,该函数在一分钟后将用户重定向到登录页面:
(function redirect_expired() {
$j.get('/app/ExpiredSession', function (resp) {
if (resp && resp.redirectTo) {
window.location.href = resp.redirectTo;
}
});
setInterval(redirect_expired, 60 * 1000);
})();
以及相关的 Java servlet 函数:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
PrintWriter pw = resp.getWriter();
resp.setContentType("application/json");
if (req.getSession != null && req.getSession().getAttribute("authorizationBean") == null) {
pw.print("{"redirectTo": "" + req.getContentPath() + ""}");
} else {
pw.print("{"redirectTo": ""}");
}
pw.close();
}
当我使用 Fortify 扫描我的应用程序时,我在 JavaScript 函数中发现了以下漏洞:
- 该方法
lambda()
在线window.location.href = resp.redirectTo;
将未经验证的数据发送到Web浏览器,这可能导致浏览器执行恶意代码。 - JS函数将未经验证的数据传递给在线
window.location.href = resp.redirectTo;
的HTTP重定向函数。使用未经验证的输入来控制 rredirect 中使用的 URL 可以帮助网络钓鱼攻击。
有人可以解释一下这个重定向调用window.location.href = resp.redirectTo;
到底出了什么问题,我该如何解决它?
也许我可以在 Java 端添加一些额外的输入检查?
JS 函数将未经验证的数据传递给行 window.location.href = resp.redirectTo 上的 HTTP 重定向函数;允许未经验证的输入来控制重定向中使用的 URL 可能有助于网络钓鱼攻击。
您的重定向正在使用从您的get
返回的值。您无法确定收到的 url 是否是您期望的 URL。如果您的/app/ExpiredSession
页面遭到入侵,您可能会收到恶意网址。
在警告的情况下,他们建议网络钓鱼攻击,这些攻击可能伪装成另一个站点,试图获取用户凭据(例如(。在您的情况下,当您重定向到其他页面时,您可能会受到"反向制表"的影响,恶意页面可能会伪装成您的网站并欺骗用户相信他们从未离开过您的页面。
您可能希望通过不同的方式验证 URL 是否受信任。一个简单的方法是存储受信任的 url 或域的列表,并在重定向到该 url 之前检查您是否识别该 URL。
更具体的方法是使用 SSL 固定。这将确保您仅与您信任的服务器和SSL(使用https(进行通信。这通过保存SSL证书的指纹并将其与请求的目标进行比较来工作。如果它们不同,那么我们假设该站点已受到威胁,不应继续请求。
两者的组合意味着您仅在发出请求时与受信任的站点通信,并且仅重定向到您"知道"的站点。
JS 函数将未经验证的数据传递给行窗口上的 HTTP 重定向函数.location.href = resp.redirectTo;。允许未经验证的输入来控制重定向中使用的 URL 可能有助于网络钓鱼攻击。
可以将恶意代码注入 url,您可以通过运行来测试
window.location.href = "javascript:alert(1)"
关于如何验证网址,有一些很好的OWASP建议
- 以/开头的输入重定向到本地页面是不安全的。
//example.org
是有效的网址。 - 以所需域名开头的输入不安全。
https://example.org.attacker.com
是有效的。 - 仅允许 HTTP(S( 协议。应阻止所有其他协议,包括 JavaScript URI,如
javascript:alert(1)
- 应阻止数据 URI(如
data:text/html,<script>alert(document.domain)</script>
( - 包含 CRLF 字符的 URI 可能导致标头注入或响应拆分攻击,应予以阻止
下面是一个使用 OWASP 建议的 Javascript 正则表达式的示例
var validateUrl = new RegExp(/^((((https?|ftps?|gopher|telnet|nntp)://)|(mailto:|news:))(%[0-9A-Fa-f]{2}|[-()_.!~*';/?:@&=+$,A-Za-z0-9])+)([).!';/?:,][[:blank:|:blank:]])?$/)
var url = 'http://google.com'
if (url.match(validateUrl)) {
console.log('Redirecting to', url)
} else {
// Do not do anything with the url variable here, executing it could be dangerous
console.log('Not a valid url')
}
此正则表达式将防止上述情况,除非在https://example.org.attacker.com
.但是,通过使用上述具有受信任域列表的建议来解决这种情况。你可以在这里亲眼看到
好吧,在这种情况下,在 Java 端执行此操作可能不起作用。考虑警告的这一部分:"可以帮助网络钓鱼攻击" - 如果攻击者能够提供恶意链接,您可以将用户重定向到网络钓鱼站点(看起来像您的站点,但实际上并非如此(,该站点允许用户输入其凭据,然后将请求发送到您的服务器(甚至可能再次重定向(。即使您的服务器会识别出网络钓鱼站点已经可以访问用户的凭据。
警告的另一部分是"可能导致浏览器执行恶意代码"(我强调( - 这已经暗示了代码在发送到您的服务器之前正在执行,因此您甚至无法识别那里的这种攻击。
你如何解决这个问题?好吧,我不是 JavaScript 专家,但请考虑"JS 函数将未经验证的数据传递给 HTTP 重定向函数"——这表明您应该验证输入或仅使用"预先验证"的 URL。
有关更多信息,请查看此处:https://owasp.org/www-project-cheat-sheets/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html