Is it a risk to put the CSRF Token in a GET request URL? - security

TL;DR Why is it bad to put a CSRF Token in the GET request parameter?
Set up to the problem.
I have a search form on a SaaS app where the CSRF token is being injected for every form including the GET forms. This seems bad to me, but I can't articulate why and I'm being asked to.
All traffic is encrypted. So the GET parameters can't be wire sharked and scraped.
The worst scenario I can see here is some sort of social engineering where a malicious actor would ask someone to copy the URL and the user just handing it over without thinking it's dangerous.
Otherwise I can't really think of a scenario where a drive by hack is possible without the hacker going through the trouble of setting up a man in the middle scenario, and in which case they would probably be set up to do worse things without that CSRF Token.
what am I missing here?

Have a look at the OWASP CSRF Prevention Cheat Sheet and specially the section about Disclosure of Token in URL

Related

are precautions against CSRF needed for view-only pages?

All the examples of CSRF exploits tend to be against pages which process the incoming request.
If the page doesn't have a form processing aspect do I need to worry about CSRF ?
The situation I'm looking # :
the page in question contains sensitive data
as such users need to establish a session to view the page
... my understanding is that a malicious page will be able to redirect a client to this page by embedding a link to it, however since there's no action on the target to perform there's no harm that can result, right ?
There's no way for said malicious site can view the sensitive page, correct ?
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility, and so I'd like to avoid them if possible.
There's no way for said malicious site can view the sensitive page, correct ?
Correct in terms of CSRF.
The blog you linked is talking about Cross-Origin Script Inclusion, which is a different animal. To be vulnerable to XOSI your sensitive page would have to be interpretable as JavaScript, and you'd have to be either serving it without a proper HTML MIME type, or the browser would have to be an old one that didn't enforce type checking on scripts.
You might also potentially worry about clickjacking, where another site includes yours in a frame and overlays misleading UI elements. There are some sneaky ways that has been used to extract sensitive data (see the next generation clickjacking paper and this amusing info leak in Firefox) so you may wish to disallow framing with the X-Frame-Options header.
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility
You definitely shouldn't be putting a CSRF token in a GET URL. Apart from the ugliness, and breakage of navigation, URLs are easy to leak from the browser or other infrastructure, potentially compromising the confidentiality of the token.
Normal practice is not to put CSRF protection on side-effect-free actions.
In general, CSRF is independent from whether the request causes any side effects or not. The CWE describes CSRF (CWE-352) as follows:
The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
So CSRF is a general request intention authenticity problem.
However, although CSRF is not really feasible without any effects other than data retrieval as the same-origin policy restricts the attacker from accessing the response, the attacker could exploit another vulnerability to profit from retrieval-only requests as well and gain access to sensitive data.

Is this CSRF Countermeasure Effective?

Please let me know if the following approach to protecting against CSRF is effective.
Generate token and save on server
Send token to client via cookie
Javascript on client reads cookie and adds token to form before POSTing
Server compares token in form to saved token.
Can anyone see any vulnerabilities with sending the token via a cookie and reading it with JavaScript instead of putting it in the HTML?
The synchroniser token pattern relies on comparing random data known on the client with that posted in the form. Whilst you'd normally get the latter from a hidden form populated with the token at page render time, I can't see any obvious attack vectors by using JavaScript to populate it. The attacking site would need to be able to read the cookie to reconstruct the post request which it obviously can't do due to cross-domain cookie limitations.
You might find OWASP Top 10 for .NET developers part 5: Cross-Site Request Forgery (CSRF) useful (lot's of general CSRF info), particularly the section on cross-origin resource sharing.
If a persons traffic is being monitored the hacker will likely get the token also. But it sounds like a great plan. I would try to add a honeypot. Try to disguise the token as something else so It's not obvious. If it's triggered, send the bad user into the honeypot so they don't know they've been had.
My philosophy with security is simple and best illustrated with a story.
Two men are walking through the woods. They see a bear, freak out and start running. As the bear catches up to them and gaining one of them tells the other, "we'll never outrun this bear". the other guy responses, "I don't have to outrun the bear, I only have to outrun you!"
Anything you can add to your site to make it more secure the better off you'll be. Use a framework, validate all inputs (including all those in any public method) and you should be ok.
If your storing sensitive data I would setup a second sql server with no internet access. Have your back-end server constantly access your front-end server, pull and replace the sensitive data with bogus data. If your front-end server needs that sensitive data, which is likely, use a special method that uses a different database user (that has access) to pull it from the back-end server. Someone would have to completely own your machine to figure this out... and it would still take enough time that you should be able to pull the plug. Most likely, they'll pull all your data before realizing it's bogus... ha ha.
I wish I had a good solution on how to protect your customers better to avoid CSRF. But what you have looks like a pretty good deterrent.
This question over on Security Stack Exchange has some useful discussion on the subject.
I especially like #AviD's answer:
Don't.
-
Most common frameworks have this protection already built in (ASP.NET, Struts, Ruby I think), or there are existing libraries that have already been vetted. (e.g. OWASP's CSRFGuard).

CSRF: Can I use a cookie?

Is it ok to put the CSRF token in a cookie? (and in every form, as a hidden input, so I can check if they match, of course) I heard someone say that doing so, beats the whole purpose of the token, though I don't understand why. It seems secure to me.
And if it is secure, is it any less secure than puting the token in the URL's ?
Is there any other method?
Where can I read more on the subject?
UPDATE: So far no one can tell me how is the cookie method insecure, if it still has to match the token from the form, which the attacker shouldn't be able to get, unless he uses another hack like XSS, which is a different matter, and still doesn't make a difference between using cookie and url token.
UPDATE 2: Okay, seems like some famous frameworks use this method, so it should be fine. Thanks
Using cookies works, and is a common practice (e. g. Django uses it). The attacker cannot read or change the value of the cookie due to the same-origin policy, and thus cannot guess the right GET/POST parameter.
Check out the Encrypted Token Pattern, which allows stateless CSRF protection without the need to store tokens on the server.
If you decide to put the CSRF-token in a cookie then remember to mark that cookie as HttpOnly. If your site has a cross-site scripting vulnerability the hacker won't be able to read the CSRF-token. You can check the cookies that can be read by JavaScript using the command console.log(document.cookie) in any modern browser console. If you have session cookies or other sensitive cookies these should also be marked as HttpOnly.
Further reading:
https://www.owasp.org/index.php/HttpOnly
"CSRF works because many sites use GET requests to execute commands.", so, many sites don't use the GET method as expected, because these request must be idempotent: see the rfc2616.
"The CSRF parameter is already there in the cookie and it gets sent along with the session.", so how?
The cookie is only used has a token storage, as the DOM when we set the token in a hidden input field. A piece of javascript must get the token value from this cookie, and set it as a parameter in the URL, the request body or in the request header. It will be check on the server with the value stored in the session. That's the Django way to handle the CSRF token.
Javascript can't access the cookie from another domain, due to the cross domain browser protection, so I don't know how a malicious user can force someone to send the correct token along a forged request. With an XSS, yes, but XSS defeat the common CSRF countermeasures.
I prefer giving this clarification, because I think it's an important question and not so easy to handle.
GET request must be used to get a resource and/or display its data, it must not be used to change its state (deletion, property incrementation or any changes).
The CSRF validation must be done server-side, it seems to be obvious, but I put it as a reminder. This method can't be a vector of attack if you observe this recommandations.
Using a cookie defeats the purpose of CSRF. Here's why:
CSRF works because many sites use GET requests to execute commands. So say Bob has some kind of administrative web account and he's logged into it. Some request could be made like:
http://somesite.com/admin/whatever.php?request=delete_record&id=4
So now Bob gets linked to an attack site (someone is trying to mess with his data). The attacker then loads the above URL in an image, probably with another ID and deletes some other record. The browser loads it because Bob is already logged into his admin site so he has a valid session.
CSRF seeks to eliminate this by adding a secure parameter to the transaction. That parameter should rotate on every request and then be resent by the browser. Making the URL look something like this:
http://somesite.com/admin/whatever.php?request=delete_record&id=4&csrf=<some long checksum>
The idea is that now the attacker has to guess "some long checksum" to create an attack. And if that checksum rotates on every request well it should be virtually impossible.
BUT if you store that checksum in a cookie you're back at square 1. The attacker no longer has to guess it. He just crafts the original URL. The CSRF parameter is already there in the cookie and it gets sent along with the session. It doesn't stop the insecure behavior from happening.

XSRF protection GET .net mvc

I have a site which will show sensitive information. I am using Anti Forgery Tokens etc to protect against XSRF in POSTS. However I am worried about someone being able to view sensitive info from a GET. What is the recommended practice for protecting read only data sent via a GET in .Net MVC 2?
If you are sure that GET requests are read-only, then you have nothing to worry from XSRF. Its not possible to steal information from another website using just XSRF, and so you don't need to protect urls via a token. In fact, using tokens in the URL is going to make it impossible to use bookmarks.
Having said that, you should be 100% sure there are no XSS vulnerabilities in your app. If there are, an attacker doesn't need to bother with XSRF and unpredictable tokens.
The XSRF protection on POST data (using tokens like you said) should work on GET data as well. From a hacker's point of view a GET forgery is much easier than POST forgery (at the first you only post a link, at the second you need to point to a malware website with hidden iframe and autosubmit forms), but both of them fail if tokens are checked.
Example:
posting a link like this:
www.domain.tld/page.aspx?get=data&token=token_given_to_hacker
shouldn't return anything, or just an error for those who got other tokens. This way no sensitive action is made for the wrong people.
This is xsrf, with this you can't steal information, but make others submit forms and take action which result only the hackers know. For example:
Changing email, on an email form, to the email of the hacker. Let's assume you have a GET form, with 1 field: the new email (for the sake of simplicity). When submitted the URL looks like this:
www.domain.tld/page.aspx?email=myemail#otherdomain.tld
Now, if a hacker posts a link on your forum with the URL:
www.domain.tld/page.aspx?email=hackers_email#yetotherdomain.tld
Everyone who clicks on it, will get a new email, of the hackers. But if you put a token there, and you'll check it every time, the action will be taken only for those who's the same token was given on page request, in this case the link will work only for the user who posted it, and no one else.
You could also protect sensitive forms, like changing email, password and so on with a password field. Note, that captcha is not much of a help here.

CSRF and ever changing tokens

I've just seen Doctype's episode on CSRF.
In it they say that the best prevention for CSRF is to create a token from some user unique data (e.g. hash a session ID) and then POST that along with your request.
Would it be less secure to generate a difficult to guess value (e.g. GUID) and store that as a session variable and put it into the page as a hidden field?
Each time the page is loaded the value would change, but the test of the POSTed data would come before that.
This seems to me to be just as secure. Am I wrong?
Where the token comes from is probably not that interesting as long as it is not guessable or determinable in any way. But watch out on generating a new token on each request as this will mean that your site will not work for a user who opens two or more browser tabs to your site. By sticking to one token value for the duration of a user's session, you can circumvent this problem.
Changing the token every request is arguably more secure. But the penalty could well be considered too high. Like almost anything when it comes to security, you often find you have to make trade-offs against the ease of the user's experience -- find me one user that enjoys CAPTCHAs!. Finding the right balance for your application and your users is important- to both your security and your usability.
There's some good reading on CSRF (and much more) over at the Open Web Application Security Project
Also bear in mind that if you have just one cross-site scripting vulnerability on a token-protected page, then your CSRF token is now useless. See also the OWASP XSS (Cross Site Scripting) Prevention Cheat Sheet.

Resources