Django CSRF protection for mobile apps and chrome extensions - django

I have done a few mobile apps using django as my backend, and now I am working on a chrome extension. I want my users to be able to send POST requests up to the server using the app/extension but is there a way to do it without first asking the server for a CSRF token? It just saves the app from making two requests every time we want to submit data. For example, I want to update my profile on my social media app or update a wallet from a chrome extension. It would be nice to open up the profile view input the data and push it to the server. It's less sleek if I have to open the profile, then wait for it to grab a token from the server and then I can submit the data. Is there another way to do this? Or am I stuck making multiple requests every time I want to submit data?
Also, a little clarification, CSRF prevents sites from submitting forms with user's data. But what is to stop me from making a site that uses ajax or something to grab the real site and steal the CSRF token and then paste that into my cross site request form? I feel like there is a loophole here. I know that I am not quite understanding this all the way.

You can, and should, make any API endpoint CSRF exempt.
Django offers the csrf_exempt decorator for exactly this, see https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views.decorators.csrf.csrf_exempt.
Also CSRF is intended to prevent unintended actions being performed via GET request forgeries. It is not intended to make it impossible for an automated system to submit forms, there are captchas for that.
As for what prevents you from using AJAX to grab the whole site and extract the token is something called the Same-Origin Policy. This is implemented by the browser and prevents any AJAX call from returning data when the target of the AJAX call is a different domain without the correct headers set. (I'm not entirely sure what sandboxing is applied to chrome extensions concerning this). As such it will, or at least should, fail to get data via AJAX for normal websites, e.g. a profile page. If you want to interact with third party websites you should look into whether or not they offer an API.

Related

Do I need CSRF-protection without users or login?

I am building a Django application where people can register for events. Everyone can register, there's no user account or login, i.e. no authentication. Verification is done through an an email with a link that has to be clicked in order to activate the registration.
I'm unsure whether I need to enable CSRF-protection for these forms. It boils down to the following question:
Is CSRF-protection necessary for every POST-request (which doesn't leave the domain) or only for POST-requests by logged-in users?
What could be done with a CSRF-attack? I know you can use it to circumvent the same origin policy and post whatever you want in the name of the user, but can you also use it to alter a real post by the user or steal their data? If a malicious site could learn the data the user posted or silently alter their request that would be a reason for me to use it. If it just means that another website can create additional registrations then no, because so can everyone else.
(I know that it doesn't cost much to just use it everywhere and I might in fact do that, but I'm trying to understand the principle better)
Contrary to the other answer, CSRF fundamentally is not about sending cookies. CSRF is about another website being able to have a user visiting it send a request to your application. If there is a session, it needs to be via something like cookies for this to be successful, because cookies for example will be sent automatically. But there are other forms of authentication that will be sent automatically, for example client certificates.
Also if there is no authentication, even easier, requests can be made. And that sounds like a problem in your case too.
What another website can do is if a user visit them, they can have that user perform actions in your application. For example they can have them register for an event, without them even noticing it. Or the malicious website can deregister people from events if that's possible. They can do whatever in the name of the victim user that is possible on your website, without the victim knowing about it, just by having them visiting the malicious website.
So to put it another way, the probelm is not that another website can perform actions in your application - they could do it with CSRF enabled too if there is no authentication. But without CSRF protection, they can have your users perform actions inadvertently in your application, just by having them visit the malicious website.
Only you can tell, whether this is a problem in your case. Without more info, I think you should have CSRF protection enabled.
CSRF attacks rely on the fact that the browser will send the information that you gave it to identify your users (cookies, typically) along with requests to your site, even ones triggered by a third party (like a malicious script).
If you don't have users, and aren't sending any such information to the browser, your application isn't in danger from CSRF.

Is it safe to use #csrf_exempt to send data from a Wordpress (or other external) site if there is no user authentication?

I’m making a simple Django app that takes data from a user submitted form, creates an image based on the data and displays the image to the user. The problem is that the form needs to be on an existing Wordpress site. The app will only perform this one task, and the image will be discarded, so there will be no user authentication, sessions, or anything like that. Is it safe to use #csrf_exempt to make this work?
Some of the answers to Do CSRF attacks apply to API's? suggest that a csrf token is not necessary if there is no user auth. However, some of the answers also suggest that there should be some other form of authentication in place instead.
And the answer to Django - CSRF verification failed - send data from form on static website to my django app suggests that there is a way to add a csrf token to a third party site, and this would make #csrf_exempt unnecessary.
Which of these approaches is right? If my understanding of csrf is correct it makes sense to me that there is no risk of csrf without user authentication. Such an attack would not be able to achieve anything, since the third party making the attack could not perform any task they can’t perform already?
The importance of csrf protection is emphasised so much in the learning resources, I just want to be really sure I don’t need it before I turn it off!
Thanks for your help!
Your analysis is right.
CSRF protections are necessary because browsers send the target domain's cookies regardless of what domain makes the request. If your server doesn't make use of cookies (for authentication or anything else) then you are not at risk for the kinds of attacks CSRF is designed to prevent.
Some of the answers to Do CSRF attacks apply to API's? suggest that a csrf token is not necessary if there is no user auth. However, some of the answers also suggest that there should be some other form of authentication in place instead.
There are, of course, pros and cons of different forms of authentication (specifically, cookie-and-session-based vs header-and-token-based), but I don't see anyone suggesting that you should use some other form of authentication instead of no authentication at all.

Understanding SessionAuthentication in django-rest-framework?

I am using Django v1.8 and django-rest-framework v3.2.2. I have a site with a public-facing API, which is also consumed by my own site (on the same domain) as the Ajax back-end to a JavaScript application, using GET only.
I want public users of this API to be asked for a key parameter in the URL, which I will issue manually. But I also want my JavaScript application to be able to use the API, in a way that means that other users can't just steal the key and use it.
I have set up my custom key authentication as described here, and it's working well.
However, I'm unclear on how the JavaScript application should use the API. Obviously I could just pass a dedicated key parameter in the URL, but then won't other users trivially be able to spot the key and use it?
I think I need SessionAuthentication, but how do I even start to make this work? I can't see any instructions in the DRF documentation about how I need to change my JavaScript calls to use it.
Also I don't understand how SessionAuthentication allows the Ajax app to authenticate without other users being able to see and copy the authentication.
Very grateful for any advice.
I think I need SessionAuthentication, but how do I even start to make this work? I can't see any instructions in the DRF documentation about how I need to change my JavaScript calls to use it.
SessionAuthentication is the Django's one. It uses session to authenticate a user. It's mostly transparent for ajax request as the browser will send the cookie automatically. However, if you're posting data, you need to make sure you send the CSRF token in both headers and post body.
Also I don't understand how SessionAuthentication allows the Ajax app to authenticate without other users being able to see and copy the authentication.
As said above, it uses cookies for that. They are part of the headers and thus usually not seen on the urls.
To make sure no-one else can steal user's session you need to run the site through https.
This isn't much different from regular websites.

How do I authenticate remotely in Django?

Basically what I'm doing is building a desktop application that needs to connect to a web server, perform some calculations, and then have the resulting values sent back to it. The calculations change over time, and also need to stay somewhat secure, which is why I'm not just coding them into the desktop application.
The issue is that only authenticated users should be allowed to access the server. So what I'm looking for is a way to log-in to Django from my desktop application (i.e. the desktop application will pop up a window asking for a username and password, which will then be sent to the Django site, used to authenticate the user, and if valid, will return the results of the computation. It also needs to work as a session (the user enters their password at the beginning and then doesn't need to log-in again until they close the desktop application, even if multiple computations are performed).
I think I need to use session keys for this, and perhaps the RemoteUserMiddleware described here but I really have no idea where to start as far as coding this. Any suggestions or pointers in the right direction would be hugely appreciated.
Thanks,
-Morag
P.S. If this is important, the desktop application is written in VB.NET.
Interesting. I've never done anything like this, but here is, what I assume, is the basic idea:
1) Get a good view of Django sessions; the basic idea is:
One logs in using the django auth framework login service
Django will create a session for you and handle all the difficult stuff
Django returns a HttpResponse with a sessionid cookie. You will need to send this back with any request following to identify yourself and 'operate within the session'.
One logs out using the django auth logout service and the session is destroyed by Django.
2) Now, the rest is relatively easy.
Setup django urls.py with the appropriate urls for login/logout + computation service
Execute a post request to the login service with the appropriate parameters set
Catch the response, extract the 'sessionid' cookie and save it somewhere
On each subsequent request, include the sessionid
This should get you started. Good luck!

Is QtWebkit needed to fetch data from websites that need login?

As the title implies,
I need to fetch data from certain website which need logins to use.
The login procedure might need cookies, or sessions.
Do I need QtWebkit, or can I get away with just QNetworkAccessManager?
I have no experience at both, and will start learning as I go.
So please save me a bit of time of comparing both ^^
Thank you in advance,
Evan
Edit: Having read some related answers,
I'll add some clarifications:
The website in concern does not have an API. So I will need to scrape web elements for the data myself.
Can I do that with just QNetworkAccessManager?
No, in most cases you don't need a full simulated web browser. In most cases, just performing the same web requests like a web browser would do is enough.
Try to record the web requests in your browser, using a plugin like "HTTP Live Headers" or "Firebug" in Firefox. I think Chrome provides a similar tool out of the box. These tools record the GET and POST requests done by the website when you send a form in the webpage.
Another option is to inspect the HTML code of the login page. Find the <form> tag and its fields. Put them together in a GET / POST request in your application to simulate the same form.
Remember that some pages use randomized "tokens" in their forms, some set the tokens as cookies. In such cases, you need to request the login page itself in your application first (before sending the filled in form). Both QWebView and QNetworkAccessManager have cookie support.
To sum things up, I think QWebView provides a far more elegant way to simulate user interaction with a web page. The manual way is, however, more "lightweight", as you don't need Webkit and your application might be faster (because only the HTML page is loaded, without any linked resources like images, CSS, javascript files).
QWebView as class name states is a view, so it views something (in this case web pages). If you don't need to display loaded page, then you don't need a view. QNetworkAccessManager may do the work, but you need some knowledge about HTTP protocol, and also anything about target site: how does it hande logins, what type of request you have to send to login etc.