51

I've seen several blanket statements on the web to the effect that you don't need CSRF protection for GET requests.

But many web applications have GET requests that return sensitive data, right? Then wouldn't you want to protect those against CSRF attacks?

Am I missing something, or are these blanket statements assuming that the data the GET request gives is unimportant?

Examples of blanket recommendations gainst using CSRF tokens with GET:

jtpereyda
  • 1,430
  • 2
  • 16
  • 26

5 Answers5

54

CSRF protection is only needed for state-changing operations because of the same-origin policy. This policy states that:

a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin.

So the CSRF attack will not be able to access the data it requests because it is a cross-site (that's the CS in CSRF) request and prohibited by the same-origin policy. So illicit data access is not a problem with CSRF.

As a CSRF attack can execute commands but can't see their results, it is forced to act blindly. For example, a CSRF attack can tell your browser to request your bank account balance, but it can't see that balance. This is obviously a pointless attack (unless you're trying to DDoS the bank server or something). But it is not pointless if, for example, the CSRF attack tells your browser to instruct your bank to transfer money from your account to the attacker's account. The success or failure page for the transfer is inaccessible to the attacking script. Fortunately for the attacker, they don't need to see the bank's response, they just want the money in their account.

As only state-changing operations are likely to be targets of CSRF attacks, only they need CSRF defenses.

Neil Smithline
  • 14,621
  • 4
  • 38
  • 55
  • so what step should I take to prevent this `CSRF attack` ?? – Nad Dec 11 '18 at 10:01
  • 4
    However, this is not true if CORS is involved, is it? E.g. I have a GET request that returns sensitive data and is CORS enabled, it can be read by a malicious site, or a trusted site that has been compromised by say an XSS. – Leprechaun Mar 06 '20 at 10:15
  • Note that you may want to add CSRF protection against GET requests, even if they don't change state, if you want to prevent timing attacks. For example, you can use timing attacks to extract information from Lucene: https://www.idontplaydarts.com/2015/09/cross-domain-timing-attacks-against-lucene/ – priomsrb Sep 15 '20 at 07:32
  • We have a very strict same-origin policy enabled, but a recent pen-test nevertheless recommended we implement CSRF to protect older browsers that don't support same-origin policies, as these are known to be in use by a subset of our users. Does your advice about GET requests change if same-origin policies are not being enforced? – HappyDog Jul 06 '21 at 15:37
  • Without the same-origin policy, an attacker could potentially extract user-specific data (ie: data that requires authentication) via a cross-site GET request. Adding CSRF protection to GETs will protect against this. I suspect that lack of same-origin policies leads to other security problems. If possible you should force the users to upgrade. (I know - it's complicated.) – Neil Smithline Aug 02 '21 at 14:51
27

Ordinarily safe methods do not have to be protected against CSRF because they do not make changes to the application, and even if they're returning sensitive information this will be protected by the Same Origin Policy in the browser.

If your site is implemented as per standards, your GET requests should be safe and therefore do not need protection.

However, there is a specific case where a "Cross-Site DoS"* attack could be executed. Say your reporting page takes 10 seconds to execute, with 100% CPU usage on your database server, and 80% CPU usage on your web server.

Users of your website know never to go to https://yoursite.example.org/Analysis/GetReport during office hours because it kills the server and gives other uses a bad user experience.

However, Chuck wants to knock your yoursite.example.org website offline because he doesn't like you or your company.

On the busy forum he posts to often, http://forum.walkertexasranger.example.com, he sets his signature to the following:

<img src="https://yoursite.example.org/Analysis/GetReport" width=0 height=0 />

He also know that your company employees frequent the forum, often while also logged into yoursite.example.org.

Every time one of Chuck's posts are read by your employees, authentication cookies are sent to https://yoursite.example.org/Analysis/GetReport, so your site processes the request and generates the report, and your system goes offline because CPU is eaten by these constant requests.

So even though the request is a GET request and doesn't make any permanent changes to your system (aka "safe"), it is infact bringing down your system every time it is ran. Therefore, it would be better to protect this with a CSRF prevention method.

*XSDoS, or Cross-Site Denial if Service, is a phrase coined by me, so don't go Googling for it.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • You mention bypassing the CSRF protection by using an `img` tag. I'm curious. If `https://yoursite.example.org/Analysis/GetReport` actually returned an image of some sensitive report (a JPG for example), would the image load? Is there any way to protect against this? – jmrah Jul 18 '20 at 15:06
  • 2
    Yes it would load if the content type was an image type and it was a valid image. Yes, you could protect this with a csrf token and only run the report code which generated the image if the token is valid. – SilverlightFox Jul 19 '20 at 07:07
  • 1
    Of course the user world need to be logged into `yoursite.example.org` to see the image on the forum, so they're not seeing anything that they wouldn't normally have permission to. However, it'd be out of context and Chuck maybe could use the image to trick employees that he has the data himself. Therefore social engineering is needed too so this scenario is less likely. – SilverlightFox Jul 19 '20 at 07:16
  • I forgot for a moment that Chuck wouldn't be able to *see* the image or actually access it in any way. Thanks for your reply. – jmrah Jul 19 '20 at 10:32
9

CSRF protection is not used to protect data. It is used to protect a user from unknowingly changing state, such as transferring money or logging out of an account.

Thus, if your GET request is changing a state (which it shouldn't be), then you should have CSRF protection. But if it's just returning data, it doesn't need CSRF protection, because CSRF protection wouldn't protect anything in this case.

It may help to go over this page again: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29

d1str0
  • 2,348
  • 14
  • 24
  • 1
    Please don't confuse visitors with the controversial CSRF logout issue. – h4ckNinja Feb 26 '16 at 03:07
  • @Micheal I'm curious how it is controversial? I haven't heard of it being controversial. – d1str0 Feb 26 '16 at 03:09
  • It is controversial because logouts, while state-changing, occur over GET normally, so what are you supposed to do with the anti-CSRF token? Some consider it an issue, some don't. Google for example won't accept bug bounty reports with it. My vote is leave it at changing the account settings. – h4ckNinja Feb 26 '16 at 03:14
  • It's trivial to implement and it does offer benefit. GET can handle CSRF tokens just fine. – d1str0 Feb 26 '16 at 03:26
  • 1
    But you shouldn't put anti-CSRF tokens in the GET, because they'll end up in browser history, proxy logs, and server logs. – h4ckNinja Feb 26 '16 at 03:30
  • I'm not sure how that's a problem if they're a nonce. – d1str0 Feb 26 '16 at 03:35
  • @Micheal post content is also in logs so I'm not sure I understand this argument. – d1str0 Feb 26 '16 at 03:36
  • POST content should not be in the logs, unless the server is misconfigured. – h4ckNinja Feb 26 '16 at 03:37
  • I'm still not convinced a CSRF token should be protected. If you're reusing them that's a problem. – d1str0 Feb 26 '16 at 03:38
  • There's nothing wrong with reusing a token within a session. Exposing the token to a wider audience, even if one-time, gives access to someone to determine the secret used to generate the token and then predict the next token. Least privilege, right? My point being, using account logout as an example of state change for CSRF only causes more confusion. But do whatever you want to do. – h4ckNinja Feb 26 '16 at 03:41
2

CSRF, or Cross-Site Request Forgery, isn't about protecting data from being retrieved, but protecting data from being changed. This is also referred to as state changes. In an application, state changes can include profile data, like the email address, user password, or biography, or transferring funds.

GET requests are to be used for idempotent requests, or requests that do not change state. These requests do not need to have anti-CSRF tokens.

POST requests are to be used for non-idempotent requests, or requests that do change state.

h4ckNinja
  • 3,006
  • 15
  • 24
  • *Idempotent request* means something else! Idempotent operation means it doesn't matter if I run operation *once*, or multiple times. For example `mySet.add(data)` is ideponent, but `myArray.add(data)` is not - multiple calls for adding element to array will produce duplicates. Idempotent requests can change state! For example `deleteUserById(5)`. In fact, there is not so often used term "nullipotent" which means: it doesn't matter if I run operation *zero*, or multiple times. – Mino Nov 25 '20 at 10:39
0

Generally, POST requests should be used for changing the state of something. If you have GET requests set up so that they can change the state (e.g. www.example.com/settings?delete_account=True), then you should use CSRF protection as a Band-Aid fix.

Try to use POSTs to change the state, not GETs.

Stoud
  • 344
  • 1
  • 10
  • 1
    This answer is dangerous for future readers - No, using POST requests does not protect you from CSRF. It is very easy to setup a form with `method=POST` and have it `onload` submit, so POSTs are just as bad as GETs. It's made worse with [Flash or old browsers](https://security.stackexchange.com/questions/170477/csrf-with-json-post-when-content-type-must-be-application-json) that can even send JSON over POST. – Nicholas Pipitone Oct 22 '18 at 18:14