In this blogpost we will look at how we can implement Cross-Site Request Forgery protection via Synchronizer Token Patterns(STP).
First things first – As you would have noticed already, this blog is primarily focused on security. Hence, to get started, I will integrate the OWASP dependency check plugin to my project. With Maven, we blindly add many dependencies/ 3rd party libraries without checking how secure those dependencies are. This in turn can make the whole application that we are developing a vulnerable application. So it is important that we have OWASP dependency check plugin in place to check for vulnerable dependencies.
Here I have added it with a configuration – apart from generating a report I have instructed OWASP dependency check to fail the Build if a certain vulnerability is greater than or equal to 8. This is because I may not pay attention to the report and just ignore it during the build and in that case if there are any critical vulnerabilities then the build must fail as I must take note of it and remove that version of the vulnerable plugin.
<plugin> <groupId>org.owasp</groupId> <artifactId>dependency-check-maven</artifactId> <version>3.1.2</version> <configuration> <failBuildOnCVSS>8</failBuildOnCVSS> </configuration> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>
Apart from that, I am going to use PGP based code signing so that anyone can verify that this code was written by me(Ihsan) and not by anyone else. Pictured below is a signed tag that I have added.
You can verify this by typing git tag -v <tag name>
Further reference on code signing can be found at: https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work
One last thing before we get started, throughout this project I have adhered to the Java code conventions as a best practice. Further reference on that is available at: http://www.oracle.com/technetwork/java/codeconvtoc-136057.html
UPDATE: my tag doesnt work atm 🙁 I will try to fix it.
Now that all the good practices are out of the way, lets get in to the actual application.
What is CSRF and how Synchronizer Token Patterns saves the day
Cross Site Request Forgery(CSRF) attacks was one of the top ten attacks put forward by OWASP in the year 2013. In simple terms, Assume you are logged in to a bank. The attacker uses a session that you have with a bank site to transfer money or such do nefarious things without your knowledge. For this he may use a specially crafted link that does this transaction. For example, he can create a webpage, hosted in his own account which has an image tag that has this specially crafted url as the source(src) of the image. Now I hope you have a clear understanding about CSRF. What is the solution to this problem?
One solution is Synchronizer Token Patterns(STP). In STP we generate a CSRF token for a session and append it to that form that makes a transaction using the session.(We append it to the form as a hidden input tag). Now the attacker can’t do a CSRF attack as the session is not the only thing we check in the server. We check for the CSRF token as well. An example tag we use in STP:
<input type="hidden" name="csrf_token" id="csrf_token" value="334976764192434-52342-562-625225">
CSRF STP application
The STP demo application that I developed is available at : https://github.com/ihsanizwer/CSRF-Protection-Via-STP.git
You need to clone it to your machnine to follow along. You must copy the war file in the target directory titled “CSRFProtectionSTP.war” to the webapps directory of tomcat. Now start tomcat and go to the URL: localhost:8080/CSRFProtectionSTP
1. LogIn
Please LogIn with the following credentials: username: Adam password: helloCSRF
2. View the cookie created in the client side (optional)
If you have cookie manager add-on installed, then you can view the cookie like so:
(Type in, STPSesID in the name field)
Fun fact: I put a lot of thought into creating these session values and CSRF tokens. Because we can’t merely create a deterministic session id or csrf token. If we create deterministic ones then attackers can use methods to figure out session keys. I used SecureRandom class in Java to create cryptographically secure random numbers. Numbers used here are positive and negative integers that are concatanated to a String that makes the session key. These are much more secure than the psuedo random numbers generated by other classes. For my reference, I made use of this article. After visiting this site, hit ctrl + f and search for “cryptographically” and you will see my point.
3. Move to the Cash Transfer page.
Click on the link on the top right corner of the homepage and move to the Cash Transfer page.
As this page was loaded, an AJAX request was sent to the sever. This AJAX request is calling the endpoint, /get_csrf_token
to get the CSRF token. Once it gets the CSRF token, it will append it to the page.
4. View the CSRF token
While on this page, right click and select inspect element. Or simply press ctrl + shift + i
. Now select the network tab. Finally select the request made to our desired endpoint and view the response.
5. Transfer funds!
Now that we are sure we have fulfilled all the requirements, enter a value and click on submit. You will land on this page if you entered a correct amount.
Here you don’t need to type in the account number. We ignore that as it is out of scope 🙂
6. Play around
Congratulations! Now you know how csrf works. You can now verify if this actually works by using a software like BurpSuite. You need to intercept the traffic and see the responses. Here you can try removing the CSRF token from the request after submitting the transfer cash form. Enjoy! 🙂