Synchronizer Token Pattern - Node.js

Hello! I hope you had a good day and an awesome week. 😊

With the advancement of technology in information and communication sectors, millennials are electronics-filled, increasingly online and socially networked, which is exactly why everything can be done once you are connected to the internet. Doing online transactions have become so much easy making it is just a button click but, can we guarantee the safety of these transactions? Cross-site Request Forgery (CSRF) is a type of attack which targets such online transactions.

You’ll need to have the knowledge of cookies as a prerequisite to fully understand CSRF.

What is Cross-site Request Forgery?

Cross-site Request Forgery (CSRF) is a malicious exploit of a website where unauthorized commands are sent from a user the website trusts, without this particular user’s knowledge. This is a vulnerability found in websites. Let’s see the below example to understand CSRF.


Cross-site Request Frogery


When Harry signs in to the bank’s website using his username and password, the bank’s server would create a session for him. The session id of this session would be sent to the browser in form of a cookie. Then Harry visits a malicious website unknowingly that it is malicious and is tempted to click on an image on the website. Once he clicks on the image, without his knowledge, a request for money transfer will be sent to the bank’s server. As the destination domain is ‘unionsavingsbank’ for this unauthorized request, the browser would send all the cookies created by that domain with the request. Session cookie also would include in those cookies. By validating the session id, the bank’s server would know this is a legitimate user and assumes that the request is authorized and performs the request. So, without Harry’s knowledge money would be transferred from his account.

This is how CSRF happens and when Harry realize what actually happened it would be too late. Further, we can say that it is a defect in the bank’s system for not being able to distinguish an unauthorized request from an authorized one.

How to prevent Cross-site Request Forgery?

As a temporary solution, users can use a separate browser to visit malicious websites rather than using their default browser where they are logged into their important accounts, so that browser can’t access the cookies of the default browser. Although it can be done, this is not very practical.

CSRF is pretty straightforward in GET requests, due to fact that data is sent as query parameters in the URL. Therefore, it has become a convention not to implement any state-changing operations (operations that modify data or behavior of the system) through GET requests.

If the attacker knows which parameters to send, a POST request is not safe as well. Therefore, to prevent CSRF, a token is created by the server and only in the presence of this token, the server accepts the request as valid. This can be achieved using two methods,
  •        Synchronizer Token Pattern
  •           Double Submit Cookies Pattern


In this blog, we are only going to see how Synchronizer Token Pattern works and how it can be implemented using Node.js.

Synchronizer Token Pattern


Synchronizer Token Pattern


When Harry signs in to the bank’s website using his username and password, the bank’s server would create a session and a unique CSRF token for him. The session id of this session would be sent to the browser in form of a cookie and the CSRF token would be stored in the server alongside the session id. Once Harry requests the ‘Money Transfer’ page, the server returns the related HTML page. JavaScript inside the returned page would make an AJAX POST request to the server to get the CSRF token. With the AJAX request, session cookie would be sent, which is used by the server to identify the user and send his CSRF token. When CSRF token is received, JavaScript of the HTML page updates the page to put a hidden field for the CSRF token as below.

                            <form>
                            <input type=”hidden” name=”X-CSRF-TOKEN” value=”PQR” />
                            </form>

When Harry submits the money transfer form, CSRF token is sent in the body with rest of the data along with the session cookie in the header which is used to identify the user by the server. The server then validates the request by comparing the received CSRF token value against the value stored in the server. If valid, the request is processed.

How this prevent CSRF is due to the fact that by default cross-domain AJAX calls are not possible. So, when the server gets an AJAX call with a different source domain it is not processed. AJAX call should never be a GET request as the data is passed as query parameters.

If the bank’s server has enabled cross origin AJAX calls, this method won’t work. Moreover, as the server has to store all the CSRF tokens, it would require a huge amount of storage and would be cumbersome when multiple users are logged into the system.

Node.js Implementation

The template I used for this application can be found at,


Login Page



Shown above is the login page, which simply accepts username and password. Once the ‘LOGIN’ button is clicked, the application sends a POST request to the '/home' endpoint of the server where the user is validated and redirected to the home page where transferring money can happen.

/home Endpoint
  
Above shows the '/home' endpoint where it can be seen that during the login, two cookies, session-id and date will be created. In the generation of session-id uuid (universally unique identifier), timestamp is used. Cookies are seen in the browser as follows.


Created Cookies


When successfully logged in, the user is directed to the following home page.

Home Page

Home Page HTML

Above shows the HTML code of the home page which contains a form for money transfer. There it can be seen during the form load, an AJAX POST request is sent to the '/token' endpoint of the server to retrieve the CSRF token.


/token Endpoint

Upon receiving the token, it is embedded in the form in a hidden field as seen below.


Once ‘TRANSFER’ button is clicked, a POST request is sent to '/transfer' endpoint where the CSRF token is validated as below.

/transfer Endpoint

In this scenario, transferring of money happens only if the two values are equal.

This way Cross-site Request Forgery can be prevented through Synchronized Token Pattern.

The full implementation of this example can be found at,

I hope now you have some idea how Synchronizer Token Pattern works. In the next post, let’s talk about Double Submit Cookies Pattern.

I wish you all an amazing week ahead! Adios 😊



Comments

Popular posts from this blog

Double Submit Cookies Pattern - Node.js

Implementing an OAuth 2.0 Client - Node.js