Cross-Site Request Forgery

Cross-Site Request Forgery (CSRF) Attack: What It Is, How It Works, and How to Prevent It

CSRF vulnerability tricks authenticated users of an application to perform a dangerous activity on that application, simply by clicking a link. This post explains how CSRF works with a practical example, and shows how to protect against it, both as a user and a developer building web applications.

7 min read

You must be tired of your IT security team reminding you again and again and again not to click any suspicious-looking links from suspicious-looking emails received from suspicious-looking sources, right? But have you ever wondered why, or what could happen if you click it?

A good reason is that it could give hackers access to your company portal or even AWS account, using a vulnerability in web applications known as Cross-Site Request Forgery (CSRF). This post explains this security vulnerability and shows how it works. You'll also understand why you should NEVER click suspicious links in your emails or text messages you've received from strangers.

How CSRF Attack Works

A CSRF attack tricks users who are already logged into a web application (a bank account or a company portal) into performing a dangerous activity on that application, such as transferring funds, changing the credentials, or even granting access to some protected resource (think: sensitive company data or the AWS account).

Since the user is already authenticated on the application in one tab, it doesn't prevent them from performing this dangerous activity from the other tab. One moment you were clicking a funny cat picture; next the hacker is gaining access to your company account. Whaaat? How did that happen?

How CSRF Attack Works
How CSRF Attack Works

The Open Web Application Security Project (OWASP) [2], a foundation that works to improve software security, describes this vulnerability as follows.

Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing.

If the victim is a normal user, a successful CSRF attack can force the user to perform state-changing requests like transferring funds, changing their email address, etc. CSRF can compromise the entire web application if the victim is an administrative account.

CSRF attacks are also known by several other names, including XSRF, "Sea Surf", Session Riding, Cross-Site Reference Forgery, and Hostile Linking.

Example

In an early iteration of Twitter, you could create tweets via GET requests rather than the POST requests the site currently uses. This oversight made Twitter vulnerable to CSRF attacks: it made it possible to create URL links that, when clicked, would post on a user’s timeline[2].

Here's an example scenario that demonstrates how a CSRF attack works in three simple steps.

Step One: Hacker Creates a Fraud Website

An attacker creates a fraudulent website that performs some dangerous activity. A very simple example is a website containing a form that's automatically submitted to your application with JavaScript. In this case, submitting the form performs a dangerous activity, and all the hacker needs to do is get you to that website.

<form action="https://your-bank.com/user/email" method="POST">
    <input type="email" value="malicious-email@example.com">
</form>
 
<script>
    document.forms[0].submit();
</script>

This form is submitted as soon as you load a page, even without you doing anything. This is why it's so important not to click any suspicious links you receive in emails or messages. Have I said it enough times?

Step Two: Send the Link to Users

The attacker embeds this link or form into a normal-looking webpage and emails it to you, or links it in many places on the internet, where unsuspecting users are likely to click them, such as social media posts or comments, images, duplicated copies of real websites, etc.

Phishing Email
Phishing Email

Step Three: You Click the Link, Hacker Gets Access

Now, all the hacker needs to do is trick you into visiting the page while you are still logged into your bank website. Once the website loads, it submits the form to the bank's website, passing the browser cookies (discussed in the next section).

In other words, consider the victim is already logged onto the web application (e.g. a real banking website or company portal) in one tab. Now they open the above email in another tab. Then they click the fraud link in the email. This link takes them to the web page where the above fraud form is submitted automatically.

The bank's website thinks you are a genuine user (using the cookies) and performs the dangerous action that the hacker wants.

How CSRF Attack Works Behind the Scenes

Most web applications implement authentication using browser cookies. A cookie is a small piece of data that a server sends to a user's web browser. The browser stores the cookie and sends it back to the same server with later requests. This is how you remain logged in to many web applications after closing the tab, or even the browser.

Cookies have nothing to do with tabs or windows -- they have to do with requests to a domain. Whenever the browser requests the web server for a domain (i.e. yourbank.com), any cookies that the browser has for that domain will be sent in the request header. Since the user was already logged into the banking application in the first tab, the browser sends the cookies from the request made from the second tab.

Browser Sends Cookies to the Server
Browser Sends Cookies to the Server

Upon receiving the fraud request (that happened automatically when you clicked the scammer's link in your email), the server (web application) checks the cookies and authenticates the user since the cookie is still valid.

Now the application is thinking that a valid, logged-in user is performing this request. However, this is the forged request created by the attacker. This request can now do anything that your application allows to logged-in users, such as transferring money from the bank account.  

If you're aware of how HTTP protocol works, you might think that clicking a link or opening an image will make a GET request, which is harmless. Well, as the above example shows, the attacker can easily write JavaScript code that creates and submits a form on the fly upon clicking a link or visiting a web page.

As a user, you should always be careful before navigating to an external webpage from a suspicious link. However, as a developer building these web applications, you can do much more. Let's try to understand how to prevent CSRF attacks on your applications.

How to Prevent CSRF Attacks and Keep Your Users Safe

The main problem behind a CSRF attack is that the server application can not differentiate between a genuine request (one that came from the genuine user) vs. a forged request that came from the attacker's website, after the user accidentally clicked the link (despite their IT repeatedly telling them many times not to).

What if there was a way for the application to identify the requests that came from genuine users, then it could reject all other requests that came from anywhere else?

We can solve this problem by instructing the server application to insert a unique, random token inside each form on the web application. When the form is submitted from the real application by a real user, this token is sent along with it.

How to Prevent CSRF Attack with Tokens
How to Prevent CSRF Attack with Tokens

Upon receiving the request, the server checks if this token is present and matches the token it created earlier. It knows that the request came from a genuine user and is valid if the token is present and matches. It rejects the request if the token is missing or doesn't match.

Since the token is random, the attacker can't guess and insert it into their forged requests. Hence the server rejects all forged requests, keeping the users safe.

In fact, this is how Ruby on Rails prevents CSRF vulnerability using authenticity tokens. When a request reaches your application, Rails verifies the received token with the token in the session.

You should use anti-CSRF cookies to validate HTTP requests made from JavaScript, too, which allows you to also protect PUT and DELETE requests. The JavaScript needs to query out the anti-CSRF token from the HTML, and pass it back to the server in the HTTP request.

In the next article, we'll do a deep dive into how Ruby on Rails prevents CSRF attacks using authenticity tokens. We'll explore how the framework creates the tokens and adds them to the forms, how it verifies the tokens, and how you can disable them for specific requests.

Conclusion

I hope you have a better understanding of how a Cross-Site Request Forgery attack works. You can prevent it by remaining vigilant and verifying the source of the links and emails before clicking them.

Always hover your mouse over the link, before you click it. Make sure that it leads to a legitimate, safe website that corresponds with the content in the email.

We also learned how web developers can mitigate it using authenticity tokens in the forms. If you're a web developer building these applications, learn and use the countermeasures your tools and frameworks provide against these attacks.

As the security team at my company like to say,

Stop, Look, and Think. Don't be fooled.

References

  1. Open Web Application Security Project® (OWASP)
  2. Web Security for Developers, Malcolm McDonald

I hope you found this article useful and that you learned something new. The next post in this series will explain how software developers can prevent CSRF attacks using authenticity tokens in their web applications.

If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I look forward to hearing from you.

Please subscribe to my blog if you'd like to receive future articles directly in your email. If you're already a subscriber, thank you.