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

Protect an old web application against CSRF without adding hidden input in all forms

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

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

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

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

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

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 and/or 如果您的站点容易受到 XSS/Open 重定向的攻击,这种方法可以轻松绕过此检查,则此方法将不起作用。

感谢您的反馈和回答。我遵循了以下解决方案。 我创建了两个过滤器。 设置 CsrfTokenFilter。 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 中的几乎所有网址添加了这两个过滤器。 最后在我的 jsp 页面中,通过 jquery 以所有形式在代码下方注入。

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

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