There are many solutions out there today that allow an administrator or developer to easily protect their entire application from Cross-Site Request Forgery (CSRF) attacks. If you are unfamiliar with CSRF, you can quickly get up to speed by reading the articles here and here. A short list of protection solutions include the OWASP CSRFGuard Project, implementing one-time use form tokens (custom), or implementing some type of CAPTCHA system such as reCAPTCHA. This list is obviously not all inclusive, and may not work for your specific setup, but it should give you a general idea of what is required to harden your site against CRSF.
But what of you only want to protect certain areas of your application? CSRFGuard is highly configurable and could accomplish this, but I believe there is an even simpler solution that does not require the use and configuration of a framework. What is it? Re-Authentication. In my opinion re-authentication offers the same amount of protection as other CSRF solutions without all the overhead of generating random tokens, placing them in hidden form fields or attaching them to every URL, and then validating them on the server before processing. Having said as much, here is a simple implementation that you could follow for sensitive areas of your application. (Note: An area should be considered sensitive if it should only be accessible by administrators, allows a user to modify his/her credentials, allows a user to modify any attribute used to determine authorization for a given action, or any other part of an application where the application owner wants to validate the identity of the requestor beyond what is stored in the requestor’s authenticated session.)
Scenario:
Due to the nature of CSRF Attacks, relying on values stored within the user’s session to validate the requestor is not sufficient. Therefore, the easiest way to validate the user is to request the user’s password prior to allowing them access to the Admin portion of the application. The flow looks something like this:
1. User requests a resource (JSP, Servlet, Struts Action, etc) the application owner considers
sensitive.
2. The resource implements logic to validate that the request is actually coming from the real user.
Example (Java):
…
HttpSession authenticatedSession = request.getSession();
String userVerified = authenticatedSession .getAttribute("userVerified");
if ("verified" != userVerified) {
authenticatedSession .setAttribute("userVerified", "notVerified");
StringBuffer requestedResource = request.getRequestURL();
if (null != request.getQueryString()) {
requestedResource.append("?");
requestedResource.append(request.getQueryString());
}
authenticatedSession .setAttribute("requestedResourceName",
requestedResource.toString());
RequestDispatcher rd = request.getRequestDispatcher("/verifyUser.jsp");
rd.forward(request, response);
}
…
3. verifyUser.jsp would then gather and submit the current user’s password to the VerifyUserServlet.
4. The VerifyUserServlet implements logic to validate the submitted credential.
Example (Java):
…
HttpSession authenticatedSession = request.getSession();
String currentUserName = authenticatedSession .getAttribute(“currentUserName”);
String password = request.getParameter("password");
if (null != password) {
validateCredentials(currentUserName, password);
authenticatedSession .setAttribute("userVerified", "verified");
// Redirect to requestedResourceName (set in the session by the requested resource)
}
else {
// Redirect to verifyUser.jsp
}
…
5. After the process is complete, the requestedResourceName session attribute could be reset to
notVerified to ensure that each access of a sensitive area is valid. Otherwise, this system
would still be vulnerable to CSRF if the user being attacked had already been verified prior to the
attack happening. One way to modify this (will slightly decrease the effectiveness, but will
increase usability) would be to set a second session attribute called userValidatedUntil that
contains a future timestamp detailing when the current user should be revalidated. Determining
how long the validation is good would completely depend on the application, its usage, and what
exactly is being protected. In any case, allowing for an extended validation period should be left
up to the application and data owners.
Using the above pattern, I believe that a developer could easily protect selective parts of his/her application without the need to implement an external framework. In the end, the control is about access control and validating that the requestor is authorized to perform the action being requested.