Protection against cross-site request forgery attacks
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.
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.