Synchronizer Token Pattern - Node.js
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.
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,
https://github.com/hinami95/synchronizer-token-pattern-nodejs
For more information on Cross-site Request Forgery, visit,
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
For more information on Cross-site Request Forgery, visit,
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
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
Post a Comment