5
votes

During a recent security scan of our Java web application, we found out CSRF vulnerabilities. I know for a newer app which is using a security framework like Spring Security, we could easily add a hidden input with every form and do other required configurations and that would solve the problem.

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

But ours is a very old app still using acegi-security (1.0.2) and has 100s of forms written in JSPs. Adding an input type hidden csrf token on all these forms seems very tedious. Is there a smarter way of securing my application without all of this hard work.

2
Via JavaScript? Or simply a regex replace over all JSPs.Joop Eggen
I am open to Javascript if it does the job. Thought about regex replace over all JSPs, that is my final solution if nothing else works out.Anil
Take a look at OWASP CSRFGuard project. I haven't used it personally but I've read the following interesting line: OWASP CSRFGuard 3 supports the ability to dynamically inject CSRF prevention tokens throughout the DOM currently loaded in the user's browserm3nation

2 Answers

1
votes

The Synchronizer Token Pattern is the best way to prevent CSRF.

The other way you can prevent CSRF is by checking referer header. An example code,

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

But, this method won't work if you are using HTTPS and/or if your site is vulnerable to XSS / Open redirect which can easily bypass this check.

0
votes

Thank you for your feedback and answers. I followed the following solution. I created two filters. SetCsrfTokenFilter. The doFilter method does the following.

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);   

VerifyCsrfTokenFilter. The doFilter method does the following

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);
        }

Added both these filters for almost all urls in my web.xml. And finally in my jsp pages injected below code through jquery in all forms.

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

This solved my problem and next scan could not find any csrf issues. For those of you who want complete source code of filters on server side and javascript code on client side, I have created a git project. https://github.com/anilpank/oldWebAppCsrfProtection