Deciphering CSRF

Deciphering CSRF

CSRF refers to cross-site request forgery. It is an exploit on websites where an attacker is forging the identity of a trusted user to perform an action that the user didn’t intend to.

Who is a trusted user?

A trusted user for a website can be an authenticated user with valid session data. The attack gets worse if the trusted user has administrative privileges to the website.

How it works?

The attacker poses as the trusted user (who is unaware of the ill intention of the attacker) to perform an action and it mostly tries to alter the state of website’s backend data. The attacker executes this action via social engineering e.g. a hidden link in email which when clicked executes the script or hidden link in img tag which does not even require user to click any link but will be executed as soon as the page is loaded. It may look like this

<img src='<>' height=0, width=0>
<a href='<>'> View Cute Pictures! </a>

or some POST request like this

<form action="<>" method="POST">

<input type="hidden" name="acct" value="EVIL"/>
<input type="hidden" name="amount" value="10000"/>
<input type="submit" value="View my pictures"/>


or PUT

function put() {
    var x = new XMLHttpRequest();"PUT","<>",true);
    x.setRequestHeader("Content-Type", "application/json");
    x.send(JSON.stringify({"acct": "EVIL", "amount":10000})); 

<body onload="put()">

Web browsers by default send all the cookies and session data of the domain website when the request is made to that website. So when the request is executed by the trusted user (unknowingly) the vulnerable receiver website will validate the session data and allow the request to go through.

How to prevent CSRF?

  1. Disabling CORS - Most modern browsers disable CORS by default which means cross origin requests won’t go through. However, attack can still happen if the target website has enabled CORS by putting * in 'Access-Control-Allow-Origin' header.

  2. 'X-CSRF-TOKEN’ - Setting this token explicitly in headers. Backend server can generate a token (random and time based) and send it to the client in response cookies for preflight request. Client can parse the cookie and set the header while making a new request to backend server. This token should be a random and unique value with expiry for each request. However, this approach is based on the fact that the attacker script is unable to read the response cookies and set the header parameter.

  3. Checking the referrer header (Origin/Referer header)- Backend server should always check if the referrer is a domain other than the one they intended to allow and block such requests from going to the application servers. Reliability on these headers comes from the fact that they cannot be altered programmatically as they fall under forbidden headers list, meaning that only the browser can set them.

  4. SameSite cookie attribute - Setting this cookie value to Lax, Strict, or None . This attribute helps the browser decide whether to send cookies along with cross-site requests.

  5. Do not use GET requests for state changing operations.