DEV Community


"I never sent that!" An Intro to CSRF (Updated)

caffiendkitten profile image DaNeil C Updated on ・7 min read

What is a CSRF attack?

"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. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request." (1)

If that didn't make sense to you, that's ok. It's a lot of technical speak.

In less technical terms...

The CSRF attack is the ability for an attacker to take advantage of a browsers automatic behavior of adding any related cookies to a domain request to perform an action on the user's behalf; generally without them knowing.

How does CSRF work??

Let's say you have a bank site (SiteB) and a second site (SiteA).

  1. You log into SiteB and when you are done you navigate to SiteA, but you never click that "log out" button on SiteB.
  2. Now on SiteA, you are clicking around, but you accidently/are tricked into clicking on a link you didn't mean to.
  3. Nothing might look like it happened or a page might pop open, but really this click activates some script to run on SiteA.

    In the background, that script sends a form post request to SiteB to transfer some money to a different account.

  4. Your browser recognized SiteB as a request address and automatically attaches all related cookies for SiteB that have been saved in your browser.

    Because you didn't sign out from SiteB, your alive cookie session that identifies you and your account information, is sent with the request to SiteB from SiteA pretending to be SiteB that might look something like this:

    POST /sendMoney HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 30
    Cookie: session=yvthwszty3eTAPzeQ5gHgTvlyxHfsAfE;
  5. Once SiteB received the fake request SiteB processes and send away your money to some other bank account. =(


Why does this work?

This works because SiteB can't distinguish between the fake or legitimate request sent by a victim. SiteB accepts the cookies sent to it because the malicious script from SiteA makes it look like the request is really coming from SiteB and all SiteB sees is a request by the victim to SiteB to perform an action.

What else can this look like?

  • In the first case I found this a token in the URL is what caught my attention. The URL had the User Token right in it and it seemed odd to me to have it right there in the open in and being treated as non-sensitive data.
    Alt Text
    This specific one can be difficult to spot even though it's right in front you and understanding what this simple token can do without really seeing it is the hardest for new people to grasp (or maybe just me). I didn't understand what I was looking at at first and it's taken some playing with to get it to exploit. However, once it does it all makes sense.

  • It might also look like a simple form with a hidden value like:

<form action="/action_page.php">
 <label for="fname">First name:</label><br>
 <input type="text" id="fname" name="fname" value="John"><br>

 <label for="lname">Last name:</label><br>
 <input type="text" id="lname" name="lname" value="Doe"><br>

<input type="hidden" name="_token" id="TOKEN" value="{eyd1c2VyIjoiYm9iIIjZ5N3ViZmYzZ0g2In0=}" />
 <input type="submit" value="Submit">
Enter fullscreen mode Exit fullscreen mode

This example is easier to find as it is a web form and that simply requires looking at the page code for any pages that contain a form.

  • It might also look like a simple image or an image that doesn't load. <img src=”” alt=”pwned” height=”1” width=”1”/>

This example is rather annoying and more difficult to find. It's something that needs to be trained to look at/for images that don't load, or ones that are 1x1 pixel image that fails to load, and what they are really doing.

What if you think you found a CSRF vulnerability?

If you think you found a CSRF vulnerability... good for you! It might be part of a vulnerability or something more so make sure to test it out.

In my case, I found the vulnerable point because it was as simple as a token in the URL of an page.

For my case, from here I was able to take that token in the URL and watch in the browser how the network was handling it.

Surprise surprise, it was putting the token it into some form values (with some other information) to perform an POST action to change user settings.

Now, because I wanted something tangible to prove this point, I used the form to change my password for my account from a different URL.

  • First I needed to watch the network and how it was handling the request. Below you can see the network request when I update my password manually with gibberish in it.

    You don't need to have a valid password to see what information is attempting to be sent so this allowed me to build my form in a separate HTML page. (see below)
    Alt Text

  • Now I built a small HTML page that has just form for the token to sit in and the other fields needed to change my password.
    Alt Text
    As you can see above, the form isn't much. It is a simple form with a few input fields. Below is what the simple HTML page looks like in the browser. Nothing much right? But successful.
    Alt Text

NOTE:: This part does need to be done semi quickly as cookies do expire (eventually), but if you are worried about speed you could write a python script to get it done super quick.

  • Once the page is set up I was able to log into my account, take the token from the URL and put it into the HTML page, open the HTML page outside of the domain it belongs to and poof! Password successfully changed just by having the token from the URL in a different HTML page. "Account information saved."

Why is this bad?

To me it seems obvious... because you don't want SiteA performing actions on SiteB. You wouldn't want Facebook to be accessing your banking account. Duh.

In my case, having the token in the URL bad because it is exposing sensitive data to the world (and all their ad partners to see). As URLs are not treated as sensitive data on any website, sensitive user identifying data is being given away in browsing history, shared systems, web logs, third parties, and referer headers to name a few.

What is the root cause/underlying issue???

With CSRF the underlying issue is that browsers automatically send any related tokens for a domain along with a request, and that it can be abused.

For my case, this is abused because the site has an information disclosure issue that is leaking the CSRF token, that is supposed to be protection against CSRF attack. If there is a malicious ad running on the page, or malicious script hidden in an image on the page that can run automatically, then that token is being given away to an attacker to potentially be take advantage of.

NOTE:: Realistically, getting the password changed is probably pretty difficult because you have to know their current password BUT if there was real malicious intent then some social engineering could be done to acquire it, lock the user out of their account, sell the account data, or worse depending on the type of account.

How to avoid CSRF.

As a user the best way to avoid this is by:

  • Logging out of sites after using.

    CSRF attacks rely on the victim having a valid session so when you log out, you invalidate the session on that site, leaving no sessions for the attacker to exploit. (The cookies stored in your browser will no longer work.)

  • Use a different browser for sensitive sites such as Duck Duck Go or Firefox and make sure to clear all cookies when done.

    Because CSRF attacks also rely on the victim’s browser storing the credentials of the vulnerable website, by using separate browsers for sensitive activities, in general, you can make sure that if you do stumble upon a CSRF exploit page or email during casual browsing, the browser that you are using will not have the credentials to sensitive sites.

  • Disable JavaScript.

    This would make a CSRF attack more difficult as JavaScript is a common way for attackers to auto-submit forms quickly.

As a developer the best way to avoid this is by:

  • Use the double-submit cookie pattern approach where the server validates a CSRF token that is sent in the body via script on a page with the CSRF token in the HTTP Header.
  • Not storing sensitive data in areas that are considered not-sensitive, such as URLs, or only in cookies.
  • Encrypt them in a hidden field if they really need to be in the site. This will prevent a site from getting them as the page will only contain the information as specific times.
  • Use the 'HttpOnly' flag. If a token needs to be stored in a cookie then using "this flag tells the browser that the cookie in question shall only be accessible from the server specified. Any attempts made by client-side scripts would be forbidden by this flag, therefore helping to protect against most cross-site scripting (XSS) attacks."
  • Ensure Cookies are sent with the "SameSite" Cookie Attribute.
  • Use user interaction based CSRF defenses such as CAPTCHA, a one-time use token, or re-authentication through an added password to 2FA.

Happy Hacking


Please Note that I am still learning. If something that I have stated is incorrect please let me know. I would love to learn more about what I may not understand fully.

Discussion (0)

Editor guide