保护旧的 Web 应用程序免受 CSRF 攻击,而无需在所有表单中添加隐藏输入

Posted

技术标签:

【中文标题】保护旧的 Web 应用程序免受 CSRF 攻击,而无需在所有表单中添加隐藏输入【英文标题】:Protect an old web application against CSRF without adding hidden input in all forms 【发布时间】:2015-09-11 15:33:45 【问题描述】:

在最近对 Java Web 应用程序的安全扫描中,我们发现了 CSRF 漏洞。 我知道对于使用像 Spring Security 这样的安全框架的较新应用程序,我们可以轻松地在每个表单中添加隐藏输入并进行其他必需的配置,这将解决问题。

<input type="hidden"
name="$_csrf.parameterName"
value="$_csrf.token"/>

但我们的应用程序是一个非常古老的应用程序,仍在使用 acegi-security (1.0.2),并且有 100 多个用 JSP 编写的表单。 在所有这些表单上添加输入类型隐藏的 csrf 令牌似乎非常乏味。有没有更聪明的方法来保护我的应用程序而无需所有这些艰苦的工作。

【问题讨论】:

通过 javascript?或者只是对所有 JSP 进行正则表达式替换。 如果 Javascript 能胜任,我愿意接受。考虑过所有 JSP 的正则表达式替换,如果没有其他解决方案,这是我的最终解决方案。 看看 OWASP CSRFGuard 项目。我没有亲自使用它,但我读过以下有趣的行:OWASP CSRFGuard 3 支持在当前加载到用户浏览器中的 DOM 中动态注入 CSRF 预防令牌的能力 【参考方案1】:

Synchronizer Token Pattern 是防止 CSRF 的最佳方法。

防止 CSRF 的另一种方法是检查 referer 标头。一个示例代码,

String request_origin = request.getHeader("referer");

//check if origin of the request 
//is coming from known source
if(!knownURIs(request_origin)) 
    //reject the request 

else
    //process request

但是,如果您使用的是 HTTPS 和/或如果您的网站容易受到 XSS / Open 重定向的攻击,则此方法将无法正常工作,从而可以轻松绕过此检查。

【讨论】:

【参考方案2】:

感谢您的反馈和回答。我遵循以下解决方案。 我创建了两个过滤器。 SetCsrfTokenFilter。 doFilter 方法执行以下操作。

HttpServletRequest httpReq = (HttpServletRequest) request;
    HttpServletResponse httpRes = (HttpServletResponse) response;
    String randomLong = ""+random.nextLong();
    Cookie cookie = new Cookie("csrfToken", randomLong);        
    httpRes.addCookie(cookie);
    next.doFilter(request, response);   

验证CsrfTokenFilter。 doFilter 方法执行以下操作

String csrfToken = httpReq.getParameter("csrfToken");
        String tokenFromCookie = getCsrfTokenFromCookie(httpReq);
        if (WmUtil.isEmpty(csrfToken) || !csrfToken.equals(tokenFromCookie)) 
            httpRes.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                   
        else 
            next.doFilter(request, response);
        

为我的 web.xml 中的几乎所有 url 添加了这两个过滤器。 最后在我的jsp页面中通过jquery以所有形式注入下面的代码。

<input type="hidden" name="csrfToken" value="readFromCookieThroughJavascript"/>

这解决了我的问题,下次扫描找不到任何 csrf 问题。 对于那些想要服务器端过滤器的完整源代码和客户端 JavaScript 代码的人,我创建了一个 git 项目。 https://github.com/anilpank/oldWebAppCsrfProtection

【讨论】:

以上是关于保护旧的 Web 应用程序免受 CSRF 攻击,而无需在所有表单中添加隐藏输入的主要内容,如果未能解决你的问题,请参考以下文章

保护ASP.NET 应用免受 CSRF 攻击

保护 oauth 不记名令牌免受 javascript 应用程序中的 XSS、CSRF 等攻击

是否有必要保护 JAX-RS 请求免受 CSRF 影响?

在 Safari 中保护 Web 服务器免受 MITM 攻击

如何保护 Web 应用程序免受 cookie 窃取攻击?

CSRF 保护