The current state of CSRF and should I still worry about it?

What is CSRF?

CSRF stands for “Cross Site Request Forgery” and is a term that is used to describe a situation in which an attacker tricks a computer user into submitting a web request that they are unaware of performing, that is performed under their identity, and which is typically against their interests. An example might be an instruction to their online bank to transfer money out of their account and into the attacker’s account. Since the action is performed from the victim’s computer, it is indistinguishable from a legitimate and intentional request made by the victim. This obviously sounds fairly alarming! Let’s dig deeper into the mechanisms that make this possible.

 

 

What is a (legitimate) Cross-Site Request?

When you are browsing a website most of the requests you make will be within the same website context, in that they will request resources and send requested actions to the same “origin” (essentially the same website domain).

 

Diagram showing Same Origin Request

 

However, it is very common for websites to store static content such as images and video on (and therefore fetched from) different sources (different domains) such as a Content Delivery Networks (CDNs). Many websites store scripts, images, and other static resources on CDNs in order to cache them closer to the “network edge” (nearer to the user than the server) and speed up delivery times.

 

Content Delivery Network Diagram

 

When a website instructs a user’s browser to fetch a resource from a different domain or origin, the browser is making a cross-site request, loading content from one origin or domain (the CDN) within the context of another (the main site).

 

 

How can Cross-Site Requests be dangerous?

Cross-Site Requests are very widely used but can represent a security issue if a website instructs a victim’s web browser to perform an HTTP request to another website without the user’s intent, and in such a way that an action is performed that is against their interest. This is possible because in addition to simple “resource fetch” requests (such as loading an image), cross-site requests can also be made which elicit a changed state.

 

How is CSRF used by attackers?

Forcing the victim to retrieve data doesn’t typically benefit an attacker because the attacker doesn’t receive the response, the victim’s browser does. CSRF attacks will therefore typically make HTTP requests that cause a state change on the target server – that is, that will perform a change of some record on the server, rather than simply fetching a resource. Examples will depend on the functionality of the targeted website but could include changing the victim’s registered details (in order to takeover their account), purchasing something using a victim’s details, or transferring money out of their online bank account (and into the attacker’s).

 

 

How do CSRF attacks work?

CSRF attacks rely on the fact that targeted web applications are unaware whether the requested action is a valid request made by the user or a malicious action made without them being aware. The latter case may occur when a victim for example clicks on a link in an email.

Cross-site requests are possible because they are sent to the target server from the victim’s computer, hence they inherit the identity and privileges of the victim and are indistinguishable from a legitimate request to the receiving server. This is made possible because a web browser will automatically include any credentials associated with a site, such as the user’s session cookie, in all requests to that site. Therefore, if the user is currently authenticated to a site , the receiving site trusts that the action has been legitimately requested and authorised, and will execute it.

 

How is this possible?

Web applications often use session cookies as a mechanism to identify a user across multiple pages and clicks through a website. Once a user has authenticated with their password, the server wants them to have to avoid reauthenticating by entering their username and password for every single page load – that would get burdensome pretty quickly. Instead, once a user has proven their identity with a single login, the server assignes them a session cookie that is associated with their ID server-side. When a cookie is set for a specific website, the web browser sends this trusted token as part of the metadata of every future HTTP request to that domain, until the user logs out or the cookie expires.

 

Diagram showing Session Cookies

 

However, this does mean that (because the password doesn’t have to be entered manually on every page load), the receiving site is actually extablishing a trust relationship with the user’s browser rather than with the user themselves. Normally, this is not a problem, however, since the user’s session cookie is sent with every request, attackers can abuse this established trust relationship and launch a cross-site request forgery attack that send requests within this trusted context but without your consent and without you noticing.

 

 

What web applications are vulnerable?

Any application that accepts HTTP requests from an authenticated user without having some check in place to verify that the HTTP request is unique and was initiated by the user is vulnerable to CSRF.

 

How are users tricked into making malicious Cross-Site Requests?

Attack Example – GET scenario

HTTP GET requests are used to request data from a web server. For example, when you enter a website URL in your web browser, your browser will send an HTTP GET request to the web server that hosts the website and fetch a resource. However if the server receiving the GET request is using a dynamic language server-side, it can also cause a state-change server-side before returning the requested resource, even though this isn’t perhaps strictly expected under the original specification (RFCs).

In an example CSRF attack using GET method, lets assume that a bank uses GET requests to perform bank transfers. An attacker can take a look at a valid GET request and modify it to one that performs an action instructing the transfer of money to themselves, for example:

http://bank.example/transfer?acct=ATTACKER&amount=10000

All the attacker then needs to do is to use some form of social engineering to get the victim to click on or load this URL. If the targeted user is logged into her online banking when she clicks the link, then the request will execute and the transfer will be performed.

 

Diagram showing Reflected Cross Site Scripting

 

It may seem unlikely that anyone is going to click on such a link. However the URL that the attack has crafted can be disguised as an ordinary link, masking the actual action performed:

<a href=”http://bank.example/transfer?acct=ATTACKER&amount=10000″>Click here to see your e-Birthday Card</a>

Only the link text, and not the URL would be displayed, masking its true nature.

 

Hiding the CSRF Attack from the Victim

It is not always necessary for the victim even to click on the link directly. Sometimes, GET requests are triggered automatically by certain HTML tags or by JavaScript, without requiring user interaction. For example, the <img> tag will automatically generate a GET request to retrieve the image resource, meaning it is only necessary to include an image tag in an HTML format email to the victim – the attack would be launched without the victim even clicking on a link, as soon as they opened the email and the image loaded.

 

Attack Example – POST scenario

HTTP POST requests are used to send data to be posted on the web application. For example, when you submit a web form, such as a login or contact form, your browser generates an HTTP POST request. The request contains data submitted through the web form. A web application that uses POST requests for state change actions is just as vulnerable as one that uses GET requests. This is because although the malicious link cannot be embedded in elements such as IMG tags, it can instead be embedded using a FORM tag that is then executed automatically using JavaScript.

 

How to Prevent Cross-Site Request Forgery Attacks

Method 1 – Anti-CSRF ‘Tokens’

As we saw above, our hypothetical attacker was able to launch a CSRF attack against our bank because they were able to form requests consisting of known parameters and value. For example, in our URL from above the parameter “acct” is used for the recipient account ID and the value “ATTACKER” is inserted as the value:

acct=ATTACKER

However, this means that requests can be validated by the receiving application (the online bank in our scenario) to verify that the parameter and values provided in a URL are valid and form a legitimate request. By adding an additional parameter with a value that is unknown to the attacker and which can be validated by the server, potential CSRF attacks can be thwarted.

 

Diagram showing Anti Cross Site Request Forgery

 

In order to do this, legitimate requests should contain an identifier that is unique to each request and is not valid if re-used in subsequent requests. This is often done by generating a hidden field on legitimate pages within the application that contain a one-time use token known as a nonce (number-used-once) that protects against replay attacks and parameter value prediction that CSRF relies on. When a form is submitted from a legitimate page within the application, the nonce (token) is appended to the HTTP request on submission. However, an attacker has no way to “read” a legitimate page within the application from the victim’s perspective, meaning that any malicious forms or URLs crafted by an attacker and send to a victim would be rendered harmless since the server would reject it as invalid in not containing a valid nonce.

It is important that nonces are not predictable therefore, which means that they must be both strongly (i.e. cryptographically) random as well as being immune to replay or re-use by being rendered dynamically for every unique link or form on every page for every user. Web frameworks usually either have built in, or recommended extensions which provide, CSRF protection; these should be used in preference to inhouse developed solutions since they are more likely to be robust and secure.

 

Method 2 – SameSite flag in Cookies

A newer method which can be partnered with tokenised forms strategy outlined above is the use of the SameSite cookie attribute. This attribute helps the browser decide whether to send cookies along with cross-site requests (as it previously would have done always by default). This method takes a different approach to the token approach in that it instead breaks the CSRF pre-condition or reliance on cross-site requests executing within an authorised context (the user being logged in to the target application and hence all actions from them being trusted).

When set to Strict the browser will not send the session cookie to the target site. Any CSRF link clicked on by the user will therefore be executed outside of a user context and hence be ineffective. In our example URL from earlier:

http://bank.example/transfer?acct=ATTACKER&amount=10000

we can see that nowhere is the source of the account transfer detailed (since this is looked up by the target application from the context of the authorised user session) – without this information the malicious request cannot be executed/lacks context, and so the request would be rejected, and the attack fail.

It should be noted that setting the SameSite cookie attribute to Strict can negatively impact the user experience since resources from a third party sites which require authentication cannot be loaded, and even following a link to the third party site would not include the cookie and therefore the user would appear to be logged out.

Another option for the SameSite attribute is to set it to Lax, this is now the default in most browsers. Set to Lax, the browser will send the cookie in requests that originate from another site if it is a GET request and the request was from a top-level user initated navigation. Other requests such as POST, or those initated by scripts will not include the cookie.

The Lax configuration is more user friendly, however still allows the possibility for CSRF attacks, since applications may implement sensitive actions using GET requests or may honour requests that use an unexpected request method (i.e. they were expecting POST but will still process a GET request). Therefore an attacker could include a malicious link to a vulnerable application on their website and entice a user to click it. This is not as subtle as the attack used to be since the user is redirected to the vulnerable application, however by that point it may be too late since the attack has taken place. Therefore SameSite=Lax is only considered a partial mitigation against CSRF attacks.

Note the SameSite attribute can also be set to None which instructs the browser to send the cookie in all contexts (i.e. the behaviour before the SameSite attribute was introduced), this is not recommended.

The SameSite attribute, it is not currently universally supported and exact implementation may differ between browsers ( https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#browser_compatibility).

While SameSite cookies are a valuable tool to be used when defending against CSRF, Anti-CSRF Tokens described above are still the recommended defence.

 

Additional techniques

In addition to the two primary techniques outlines above, several additional techniques outlined below can also be used as part of a defense in depth strategy to help prevent CSRF attacks, even if they should not be relied on exclusively on their own.

An additional defence pattern available to web application developers is having their web applications check the Referrer request header in HTTP requests. Ensuring that the HTTP request has been generated within the context of the original site means that requests that are maliciously formed will not be valid when evaluated by the target server.

A relatively weak defence but which may also help as part of a defense in depth strategy as a backstop if other measures fail is to implement a short or aggressive session inactivity timeout for authorised user sessions, whereby users active sessions are invalidated after say 5 minutes since the last detected action within an authorised session. This has the advantage that it reduces the attack window or length of time that a target application may be targeted by an attacker – if the user becomes logged out due to inactivity, then CSRF attacks against that web application will fail to execute within their context and the attack will fail.

 

Pop-up box notifying of session expiry

 

A final pattern that can be used by web application developers is to perform sensitive action reauthentication – that is, upon performing any high-risk or critical transaction (such as a bank transfer), display an additional decision or confirmation to the user. This could be a confirmation dialogue at its most simple, however since that it is subject to bypass via cross site scripting for example, then a stronger requirement would be for the user to enter their password (even though already logged in) in order to verify that they authorise the transaction. A CSRF attacker would not know the password of the user and therefore the transaction could not be performed via a CSRF attack.

 

Pop-up box asking for password verification

 

Although CSRF is fundamentally a server-side problem that lies in the failure by targeted web applications to adequately validate the source of web requests that perform state change on the server, end users can help to protect themselves by getting into the habit of explicitly logging out of websites when they are finished – particularly where the application is critical, such as online banking.

Lastly – but by no means least! – AppCheck makes it easy to test if your own websites and web applications are vulnerable to CSRF – as well as other vulnerabilities such as the OWASP Top 10.  Our AppCheck vulnerability scanner includes a custom CSRF scanner plugin and scans can be launched in seconds using pre-defined scan profiles built by our security experts.

 

Get started with Appcheck

No software to download or install.
Contact us or call us 0113 887 8380

Start your free trial