In this reading we'll look at preventing cross-site request forgery.

What is CSRF (cross-site request forgery.)?

Cross-site request forgery (CSRF) is a common security attack. It involves subjecting a user to code on a maliciously designed web page that automatically (and usually secretly) submits a form to another application on behalf of a user who is often the victim of the attack.

For example, a user may be presented with a form on an attacker's website that automatically posts to a URL on the user's banking website (which is presumably poorly designed and vulnerable to such an attack) to transfer money. The user may not even know that the attack happened until they notice money missing from their account

In order to prevent the CSRF attacks we need to take below actions:

  1. Applications can generate a CSRF token upon displaying a form, place that token in a hidden field, and then stow it for later use on the server.
  2. When the form is submitted, the token is sent back to the server along with the rest of the form data.
  3. The request is then intercepted by the server and compared with the token that was originally generated.
  4. If the token matches, the request is allowed to proceed. Otherwise, the form must have been rendered by an evil website without knowledge of the token generated by the server.

The good news is that Spring Security has built-in CSRF protection. Even more fortunate is that it's enabled by default and we don't need to explicitly configure it.

We only need to make sure that any forms our application submits include a field named _csrf that contains the CSRF token.

<input type="hidden" name="_csrf" th:value="${_csrf.token}"/>

In case we are using Spring MVC's JSP tag library or Thymeleaf with the Spring Security dialect, we needn't even bother explicitly including a hidden field. The hidden field will be rendered automatically for us.

CSRF example

Before executing an assault, an attacker typically figures out the application in order to make a forged request appear as legitimate as possible.

For example, a typical GET request for a $500 bank transfer might look like:

GET http://netbanking.com/transfer.do?acct=PersonB&amount=$500 HTTP/1.1

An attacker can maliciously modify the above script and change the name of the Person as himself and get the money transferred to himself,

GET http://netbanking.com/transfer.do?acct=AttackerA&amount=$500 HTTP/1.1

While the user is logged in attacker can embed the link and simulate to the user as if that is the legitimate link to access.

<a href="http://netbanking.com/transfer.do?acct=AttackerA&amount=$500">Read more!</a>

User does not find something wrong with the link and can initiate the transfer to the attacker's account.

Note that if the bank's website is only using POST requests, it's impossible to frame malicious requests using a <a> href tag. In such cases the attack could be delivered in a <form> tag with automatic execution of the embedded JavaScript.

 <body onload="document.forms[0].submit()">
   <form action="http://netbanking.com/transfer.do" method="POST">
     <input type="hidden" name="acct" value="AttackerA"/>
     <input type="hidden" name="amount" value="$500"/>
     <input type="submit" value="Unlock the Drawer!"/>
   </form>
 </body>

Best practices to mitigate CSRF:

  • Logging off web applications when not in use
  • Securing usernames and passwords and use strong encryption.
  • Using safe vaults for storing passwords.
  • Not allowing browsers to remember passwords
  • Avoiding simultaneously browsing while logged into an application

Thanks for reading and sharing. I really appreciate your time and contribution.