通过 'Referer' header 防止跨站请求伪造

Cross Site Request Forgery prevention via 'Referer' header

我们最近收到了来自 IBM AppScan DAST 的结果,其中一些结果没有多大意义。

2.Medium -- Cross-Site Request Forgery

Risk(s): It may be possible to steal or manipulate customer session and cookies, which might be used to impersonate a legitimate user, allowing the hacker to view or alter user records, and to perform transactions as that user Fix: Validate the value of the "Referer" header, and use a one-time-nonce for each submitted form

The following changes were applied to the original request:

Set header to 'http://bogus.referer.ibm.com'

推理:

测试结果似乎表明存在漏洞,因为测试响应与 原始响应,表明 Cross-Site 请求伪造尝试成功,甚至 尽管它包括一个虚构的 'Referer' header.

Request/Response:

POST /**/main.xhtml HTTP/1.1 -- **This xhtml only opens a default menu on page load**
User-Agent: Mozilla/4.0 (compatible; MS

推荐修复

Validate the value of the "Referer" header, and use a one-time-nonce for each submitted form.

javax.faces.ViewState 具有隐式 CSRF 保护。

https://www.beyondjava.net/jsf-viewstate-and-csrf-hacker-attacks

我还可以使用 protected-views 进行明确的 CSRF 保护。这种明确的 CSRF 保护为所有情况添加了一个令牌,并另外添加了对“referer”和“origin”HTTP headers 的检查。 (参考 Bauke & Arjan Book 权威指南)

该报告还标记了 /javax.faces.resource/ 等 CSS , JS ,我认为报告中的字体是误报。

寻求反馈和一些见解。

这在JSF中确实是不需要的。这种攻击只有在 已经 一个开放的远程代码执行漏洞(例如 XSS)时才有可能在 JSF 中进行(因此黑客可以访问会话 cookie,因此可以通过以下方式复制它们钓鱼站点),或者当视图通过 <f:view transient="true"> 无状态时(因为在没有远程代码执行漏洞的情况下,您丢失了 javax.faces.ViewState 隐藏输入字段作为 "normal" 情况下的隐式 CSRF 保护) ,或者当您使用 HTTP 而不是 HTTPS 时(因为中间人攻击者可以清楚地看到所有传输的位并从中提取会话 cookie)。

您只需确保最终用户的会话 cookie 永远不会以某种方式暴露给世界。建议的修复在这方面一点帮助都没有。当您迟早会不小心引入远程代码执行漏洞时,这只会使攻击者更难执行成功的 CSRF 攻击。但是你 确实比 CSRF 问题大得多 。此工具建议的所有这些努力只会让黑客少一点时间来执行成功的攻击,并给你自己多一点时间来修复远程代码执行漏洞。

如果您只想 "suppress" 此警告,则创建一个 Filter 来完成所需的工作。这是一个启动示例,将其映射到 /*.

if (!"GET".equals(request.getMethod())) {
    String referrer = request.getHeader("referer"); // Yes, with the legendary typo.

    if (referrer != null) {
        String referrerHost = new URL(referrer).getHost();
        String expectedHost = new URL(request.getRequestURL().toString()).getHost();

        if (!referrerHost.equals(expectedHost)) {
            response.sendError(403);
            return;
        }
    }
    else {
        // You could also send 403 here. But this is more likely to affect real users.
    }
}

chain.doFilter(request, response);

另见:

  • CSRF, XSS and SQL Injection attack prevention in JSF