Preventing Cross-Site Request Forgery (CSRF) with Synchronizer Token Pattern
First, Let's see what is CSRF and it's impact on the vulnerability of a system. According to CWE , it's stated that when the application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request is known as CSRF. Describing it furthermore, when a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
In 2010 this vulnerability was ranked at number 5 at OWASP Top 10 Most Critical Web Application Security Risks index, but by the extreme awareness provided by the industry has made this vulnerability to drop out of Top 10 published for 2017. This doesn't imply in anyway that the risk is gone. Still many applications are been built with vulnerability to this CSRF attack. CSRF attacks are also known by a number of other names, including XSRF, "Sea Surf", Session Riding, Cross-Site Reference Forgery, and Hostile Linking. This post will show how you can develop your online application resistant to CSRF attacks.
- Executing a CSRF attack scenario
Before prevention let's see how CSRF attack can be carried out with respect to an example. In a Cross-Site Request Forgery attack, the attacker is exploiting how the target web application manages authentication. For CSRF to be exploited, the victim must be authenticated against (logged into) the target site. For instance, let’s say bank.com has online banking that is vulnerable to CSRF. If I visit a page containing a CSRF attack on bank.com but am not currently logged in, nothing happens. If I am logged in, however, the requests in the attack will be executed as if they were actions that I had intended to take.
Let’s look at how the attack described above would work in a bit more detail. First, let’s assume that I’m logged into my account on bank.com, which allows for standard online banking features, including transferring funds to another account.
Now let’s say I happen to visit malicioussite.com. It just so happens that this site is trying to attack people who bank with bank.com and has set up a CSRF attack on its site. The attack will transfer Rs. 100,000.00 to account number 123456789. Somewhere on malicioussite.com, attackers have added this line of code:
Upon loading that image, my browser will send that request to bank.com, which my browser has already logged in as me. The request will be processed and send Rs.100,000.00 to account 123456789.
- Common Misconceptions in Prevention of CSRF
- Secret Cookie
All cookies even the secret ones get sent with a request. Therefore, making the cookie a secret doesn't prevent prof CSRF attacks. - By using POST instead of GET
Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed. Unfortunately, this logic is incorrect. There are numerous methods in which an attacker can trick a victim into submitting a forged POST request, such as a simple form hosted in an attacker's website with hidden values. This form can be triggered automatically by JavaScript or can be triggered by the victim who thinks the form will do something else.<body onload="document.forms[0].submit()"> - By using multi step transactions
Here, you can assume that if there was another step when transferring money or an alert to be interacted before completing the bank transfer can prevent CSRF. But, an attacker can easily predict or deduce each step of the transaction and make changes to the code according to bypass, then CSRF is possible. - Using HTTPSHTTPS by itself does nothing to defend against CSRF but it encrypts the data sent via network which makes the request MITM attack-proof. It doesn't helps to validate the request in request generation phase.
- Preventing Cross-Site Request Forgery (CSRF) Vulnerabilities
The most common method to prevent Cross-Site Request Forgery (CSRF) attacks is to append CSRF tokens to each request and associate them with the user’s session. Such tokens should at a minimum be unique per user session, but can also be unique per request. By including a challenge token with each request, the developer can ensure that the request is valid and not coming from a source other than the user. There are 2 types of patterns that systems can adapt in order to prevent CSRF.
- Synchronizer Token Pattern
- Double Submit Cookies Pattern
In this blog post, we will look at how the Synchronizer Token Pattern prevents CSRF and how it can be implemented in a JSP application. The following blog post will discuss Double Submit Cookies Pattern.
- Synchronizer Token Pattern
In Synchronizer Token pattern, the application would generate a CSRF token which is one-time use only and store it server side against the sessionID. This token would be sent embedded to the HTML. When the user requests an action such as transfer funds, this token will be sent along with other parameters. The server will validate sessionID and this token value. If they match, the request will be completed.The token is generated uniquely per form. Therefore, the attacker has no way of accessing this. Even if the attacker submits the other parameters, since the CSRF token is unavailable, the server will not complete the action. Thereby, CSRF is prevented.
When a Web application formulates a request (by generating a link or form that causes a request when submitted or clicked by the user), the application should include a hidden input parameter with a common name such as "CSRFToken". The value of this token must be randomly generated such that it cannot be guessed by an attacker. Consider leveraging the java.security.SecureRandom class for Java applications to generate a sufficiently long random token. Alternative generation algorithms include the use of 256-bit BASE64 encoded hashes. Developers that choose this generation algorithm must make sure that there is randomness and uniqueness utilized in the data that is hashed to generate the random token.
<form action="/transfer.do" method="post">
<input type="hidden" name="CSRFToken"
value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWE...
wYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZ...
MGYwMGEwOA==">
…
</form>
Here, normally we can use AJAX call to get a CSRF token generated using calling the relevant endpoint and that response data to fill the hidden value of "CSRFToken" field. The developers need only generate this token once for the current session. After initial generation of this token, the value is stored in the session and is utilized for each subsequent request until the session expires. When a request is issued by the end-user, the server-side component must verify the existence and validity of the token in the request as compared to the token found in the session. If the token was not found within the request or the value provided does not match the value within the session, then the request should be aborted, token should be reset and the event logged as a potential CSRF attack in progress.
- Sample Application
In the application which i have developed use HashMap to store the user session ID with relevant generated CSRF token.
Login Page is as follows and user has to provide "admin" for both username and password.
The Home page with hidden field visible, it's the field adjacent to the Submit Button. In this page user submit some kind of form and with that form details CSRF token also get sent. Just for the demonstration purposes i have change the field type from hidden to text.
Validation Page, Here the CSRF token received with the request is matched with stored CSRF token.
These are the cookies and tokens stored in browser with requests.
Now, let's move on to the code base of the project. This is the index.jsp page and handles the login aspects of the project.

We have written a AJAX query to retrieve CSRF token from the token endpoint to fill the hidden text field in the form.
So, in this scenario, even if an attacker can provoke you to complete some action and send an unintended request to the server, although the cookies are sent, the CSRF token is not present. Therefore, the transaction will not be completed, hence preventing CSRF.
The full implementation of this example can be found at Github,
In the next blog we will focus on How Double Submit Cookie Pattern can be used to prevent CSRF.
Login Page is as follows and user has to provide "admin" for both username and password.
The Home page with hidden field visible, it's the field adjacent to the Submit Button. In this page user submit some kind of form and with that form details CSRF token also get sent. Just for the demonstration purposes i have change the field type from hidden to text.
Validation Page, Here the CSRF token received with the request is matched with stored CSRF token.
These are the cookies and tokens stored in browser with requests.
Now, let's move on to the code base of the project. This is the index.jsp page and handles the login aspects of the project.
- index.jsp
- Home.jsp
We have written a AJAX query to retrieve CSRF token from the token endpoint to fill the hidden text field in the form.
- confirm.jsp
- Login.java
- SimpleStorage.java
- Validator.java
So, in this scenario, even if an attacker can provoke you to complete some action and send an unintended request to the server, although the cookies are sent, the CSRF token is not present. Therefore, the transaction will not be completed, hence preventing CSRF.
The full implementation of this example can be found at Github,
In the next blog we will focus on How Double Submit Cookie Pattern can be used to prevent CSRF.
Comments
Post a Comment