Version 10

    This is the second article out of a series of articles on security of Java web applications. The first article in this series is Java web applications security. XSS.

     

     

    Overview

     

         Cross-Site Request Forgery is an attack which exploits the trust that a website has for the currently authenticated user and executes unwanted actions on a web application. CSRF attacks are also known as XSRF, Cross Site Reference Forgery, "Sea Surf", Session Riding, Hostile Linking, and One-Click attack.

         It is fair to say that CSRF is one of the most powerful attacking techniques. Hacker doesn't need to output any tags to the server. The point is to exploit certain features of the webpage. With the help of social engineering like sending emails, instant messages with a link inside, a hacker can trick the victim into loading a page that contains a malicious request. It is malicious in the sense that it inherits the identity and privileges of the victim and the attacker can make the victim perform actions that he/she doesn't intend to. The entire web application could be compromised if the victim is the administrator.

         Here is an example taken from Chris Shiflett's Blog:

    http://shiflett.org/images/foiling_cross_site_attacks_4.png

         Sometimes it is possible to combine XSS and CSRF attacks in order to store the CSRF attack on the vulnerable site itself, in other words to make so called Stored CSRF flaw. In this case the severity of the attack is amplified because the victim is sure to be authenticated on the site and most likely to view the page containing the attack.

     

     

    CSRF aims

     

    The CSRF attacks could be used for the following purposes:

    1. posting unwanted content to a message board, chat, etc., where a victim is authenticated
    2. subscribing to an unwanted newsletter, sending e-cards
    3. using CSRF attack as a vector to exploit existing XSS flaws in a given application
    4. performing illegal actions such as using victim's shopping cart, executing stock trades
    5. performing a Denial Of Service attack

     

     

    Possible example

     

    There are a lot of web-sites that provide a lost-password feature for registered users. As usual an email address is required to obtain a new password. In this case an CSRF attack scenario could look like this one:

    1. find a page with a lost-password form inside and find out which fields would be updated
    2. trick the administrator to load a hacker page with a malicious request on it that submits a new email
    3. administrator's e-mail is now changed to the email submitted by hacker
    4. a hacker performs a lost-password request and receives a new password

     

     

    Possible protection

     

         The most popular suggestion to prevent CSRF attacks is to use a transient authentication method, in other words to append the unique request identifier (usually 128-bits string random generated) that is rendered as a hidden field on the page for every submit action. A hacker has no knowledge of this identifier. The protection scenario could look like this one:

    1. a user is logged in and the session for this user starts. Now the unique request identifiers should be generated for all links on a given page and initialized just like any other session variable. The value for unique IDs could be generated with a secure random generator such as SecureRandom for J2EE
    2. a unique ID is appended to every link or form
    3. an application checks whether the unique ID is passed with the HTTP request and the unique ID is valid for a given request. The validity of the token can also be limited to a small period of time
    4. if the unique ID is not present, the proper measures will be taken, e.g. the user session is cleared or the request is rejected

     

         Another way to protect your application is a double confirmation. When HTTP request is received by the application, business logic could examine the request. If the request commits a transaction, application could respond to the user with another request for the confirmation, e.g. password re-enter, to be sure the request is valid and comes from the user.

     

         Besides you can use PhaseListener to check ViewState for valid ID:

     

    import java.io.IOException;
    import java.util.regex.Pattern;
    import javax.faces.FacesException;
    import javax.faces.component.UIViewRoot;
    import javax.faces.context.ExternalContext;
    import javax.faces.context.FacesContext;
    import javax.faces.event.PhaseEvent;
    import javax.faces.event.PhaseId;
    import javax.faces.event.PhaseListener;
    import javax.faces.render.ResponseStateManager;
    import javax.servlet.http.HttpServletResponse;
    
    public class ViewStateParameterGuardPhaseListener implements PhaseListener {
    
         private static final long serialVersionUID = 3028312034502825084L;
    
         public void afterPhase(PhaseEvent event) {
         }
    
         private static final Pattern VIEW_STATE_PARAMETER_PATTERN = Pattern.compile(
                   Pattern.quote(UIViewRoot.UNIQUE_ID_PREFIX) + "\\d+");
         
         public void beforePhase(PhaseEvent event) {
              FacesContext facesContext = event.getFacesContext();
              ExternalContext externalContext = facesContext.getExternalContext();
              String viewState = externalContext.getRequestParameterMap().get(ResponseStateManager.VIEW_STATE_PARAM);
              if (viewState != null) {
                   if (!VIEW_STATE_PARAMETER_PATTERN.matcher(viewState).matches()) {
                        facesContext.responseComplete();
    
                        HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
                        try {
                             response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Bad view id pattern!");
                        } catch (IOException e) {
                             throw new FacesException(e.getMessage(), e);
                        }
                   }
              }
         }
    
         public PhaseId getPhaseId() {
              return PhaseId.RESTORE_VIEW;
         }
    }
    

     

     

    References

     

    There is a list of web sites where you can also get helpful information about CSRF attacks:

    1. The Cross-Site Request Forgery (CSRF/XSRF) FAQ
    2. OWASP - Cross-Site Request Forgery
    3. Cross-site request forgery on Wikipedia
    4. CSRF Guard
    5. CSRF Tester

     

     

    Conclusion or how to protect yourself

     

         The fact is as long as you visit websites and don't have control of these applications you can't do anything with attacks. You could only to login out of one site before visiting another especially if you have administrative privileges. In most cases hackers enjoy people's confidence performing XSS/CSRF attacks. You could use some tools that prevent exploitation of security vulnerabilities. If you are a Mozilla Firefox, Flock, or Seamonkey user you could simply install the NoScript extension that provides extra protection for browser and allows JavaScript, Java, Flash and other plug-ins to be executed only by trusted web sites of your choice.