Cross-site request forgery - Java

Cross-site request forgery - Java

Need

Protection against cross-site request forgery attacks

Context

  • Usage of Java for building robust and scalable applications
  • Usage of javax.servlet for building Java web applications with Servlet technology
  • Usage of javax.servlet.http for handling HTTP requests and responses in Java web applications

Description

Non compliant code

        import javax.servlet.*;
import javax.servlet.http.*;

public class VulnerableServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String userAction = request.getParameter("action");
        if (userAction.equals("delete")) {
            String itemId = request.getParameter("itemId");
            // Code to delete the item with the given itemId
        }
    }
}
        
        

In the above code, an HTTP POST request is being processed by the doPost method in the VulnerableServlet class. The doPost method retrieves the "action" parameter from the request, and if it equals "delete", it retrieves the "itemId" parameter and proceeds to delete the item with the given itemId.

The vulnerability here is that there is no CSRF token being checked in this request. CSRF tokens are used to ensure that the user intended to perform the action that the request is asking to perform. Without checking for a CSRF token, an attacker could trick a user into sending a request that performs an action without the user's consent.

For example, an attacker could construct a malicious website that sends a POST request to this servlet when visited by the user. If the user is authenticated with the application, the request would be processed, and the action would be performed without the user's knowledge or consent. This is why it's essential to always check for a CSRF token in requests that perform actions.

Steps

  • Implement a CSRF token mechanism
  • Include the CSRF token in all requests that modify data
  • Verify the CSRF token on the server-side before executing any action
  • Ensure that the CSRF token is unique for each user session
  • Use secure and random CSRF token generation
  • Consider implementing SameSite cookies to mitigate CSRF attacks

Compliant code

        import javax.servlet.*;
import javax.servlet.http.*;
import java.security.SecureRandom;
import java.math.BigInteger;

public class SecureServlet extends HttpServlet {
    private SecureRandom random = new SecureRandom();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String csrfToken = new BigInteger(130, random).toString(32);  // Generate a secure and random CSRF token
        HttpSession session = request.getSession();
        session.setAttribute("csrfToken", csrfToken);  // Store the CSRF token in the user's session
        // Include the CSRF token in the form that will be submitted
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String sessionToken = (String) session.getAttribute("csrfToken");  // Retrieve the CSRF token from the user's session
        String requestToken = request.getParameter("csrfToken");  // Retrieve the CSRF token from the request

        if (sessionToken.equals(requestToken)) {  // Verify that the CSRF token in the request matches the one in the session
            String userAction = request.getParameter("action");
            if (userAction.equals("delete")) {
                String itemId = request.getParameter("itemId");
                // Code to delete the item with the given itemId
            }
        } else {
            // Handle the case where the CSRF tokens do not match
        }
    }
}
        
        

The code above fixes the Cross-Site Request Forgery (CSRF) vulnerability by implementing a CSRF token mechanism.

In the doGet method, a secure and random CSRF token is generated using the SecureRandom class. This token is then stored in the user's session and included in the form that will be submitted.

In the doPost method, the CSRF token from the user's session and the CSRF token from the request are retrieved. If these tokens match, the action is executed. If they do not match, the request is rejected.

This ensures that an attacker cannot trick an authenticated user into executing actions without their consent, as they would not have access to the CSRF token.

In addition, consider implementing SameSite cookies to further mitigate CSRF attacks. SameSite cookies are a security measure that browsers can use to restrict how cookies are sent with cross-site requests. This can prevent CSRF attacks by ensuring that cookies are only sent with requests from the same site that set the cookie.

References