SV.CSRF.GET

This error indicates a potential leak of a cross-site request forgery token through the request URL.

Vulnerability and risk

Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated.

A standard approach to mitigating CSRF vulnerabilities is to use synchronizer tokens. A cryptographically secure random token is uniquely associated with a user session and added as a hidden field to any form that results in a state changing operation. The server rejects the requested action if the CSRF token fails validation.

Many implementations of synchronizer tokens include the challenge token in GET (URL) requests as well as POST requests. While this control does help mitigate the risk of CSRF attacks, the unique per-session token is being exposed for GET requests. CSRF tokens in GET requests are potentially leaked at several locations.

Code examples

Vulnerable code example 1

Copy
   void doGet(HttpServletRequest req, HttpServletResponse resp) {
   if (!isValidRequest(req)) {
       handleInvalidRequest(req, resp);
   } else {
       update(req, resp);
   }
 }

   private boolean isValidRequest(final HttpServletRequest req) {
        return req.getParameter("_csrf_token").equals(req.getSession().getAttribute("_csrf_token"));
   }

   private void update(HttpServletRequest req, HttpServletResponse resp) {
       //...
   }

   private void handleInvalidRequest(HttpServletRequest req, HttpServletResponse resp) {
       //...
   }

SV.CSRF.GET is reported on line 16: ‘req’ is being checked for a CSRF token (at line 25). GET requests should not be used for state changing actions, therefore a check for a CSRF should not be necessary. A check for a CSRF token implies the token is present in the GET request, potentially leaking through the URL.

Fixed code example 1

Copy
   void doPost(HttpServletRequest req, HttpServletResponse resp) {
   if (!isValidRequest(req)) {
       handleInvalidRequest(req, resp);
   } else {
       update(req, resp);
   }
 }

   private boolean isValidRequest(final HttpServletRequest req) {
        return req.getParameter("_csrf_token").equals(req.getSession().getAttribute("_csrf_token"));
   }

   private void update(HttpServletRequest req, HttpServletResponse resp) {
       //...
   }

   private void handleInvalidRequest(HttpServletRequest req, HttpServletResponse resp) {
       //...
   }

The ideal solution is to only include the CSRF token in POST/PUT/DELETE requests and modify server-side actions that have state changing affect to only respond to POST/PUT/DELETE requests. This is in fact what the RFC 2616 requires for GET requests. If sensitive server-side actions are guaranteed to only ever respond to POST/PUT/DELETE requests, then there is no need to include the token in GET requests.

Security training

Application security training materials provided by Secure Code Warrior.

Extension

This checker can be extended through the Klocwork knowledge base. See Tuning Java analysis for more information.