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.
I have developed a small application for submitting some data to database server(Oracle 11g). When we are reviewing security of this small application, we observed as follows:
1. We have deployed django with https and all secure configurations like Secure Cookie and Secure Session, No Cache, etc.
2. Using BURP tool for this sample review
3. We have created two different user in this system say Normal User and Admin User
4. Opened 2 browsers(Mozilla and IE 11), On mozilla we login with Admin user and captured session id using burp tool.
5. On second browser we login with Normal user and replaced session id Normal User with Admin User.
6. whoila......On second browser, I got Admin user access by just changing the session id
I have used default session backend for this application.
I would like to know whether this is flaw in django and how to resolve this issue..
Thanks in advance
This is an inherent risk of using session-based identification. It's called session hijacking, and if you search for that term you will find lots of information.
Mitigations generally have one of two goals: making it harder to steal the token, or making the damage less severe if it is stolen. In the former camp are techniques like using HTTPS and SESSION_COOKIE_HTTPONLY. In the latter are things like limiting the length of a valid session (SESSION_COOKIE_AGE). In the end, though, it's difficult or impossible to stop someone from impersonating another user if they get their token, since that's the very thing that establishes identity.
I need to track unregistered users in my Django website. This is for conversion optimization purposes (e.g. registration funnel, etc).
A method I've used so far is using IP address as a proxy for user_id. For various well-known reasons, this has led to fudged/unreliable results.
Can I sufficiently solve my problem via setting a session variable at server-side? An illustrative example would be great.
For example, currently I have a couple of ways in my head. One is doing request.session["temp_id"] = random.randint(1,1000000), and then tracking based on temp_id.
Another is setting a session variable every time an unauthorized user hits my web app's landing page, like so:
if not request.session.exists(request.session.session_key):
request.session.create()
From here on, I'll simply track them via request.session.session_key. Would this be a sound strategy? What major edge-cases (if any) do I need to be aware of?
Cookies are the simplest approach, but take into consideration that some users can have cookies turned off in their browsers.
So for those users you can use javascript local storage to set some data. This information will get deleted once you close the browser, but it's ok for funneling purposes. Still others can have javascript turned off.
Another approach would be to put custom data(key) in every link of the page when generating the template. in other words you would have the session_id stored in html page and send through url parameters at click. Something similar happens with csrf token. Look into that.
In the context of a e-health related service, the end-users (health operators, doctors and physiotherapists) working in the same physical environment and sharing just one client PC to interact with my backend, asked me to provide them with a mechanism to quickly switch among different accounts (security is not a concern most of the time because they are used to work within a LAN but, occasionally, they might work from remote clients, so I must keep an authentication/authorization backend in place). They would log in just once and then, before using the web application, would select their logged-in account from a combobox (sort-of).
The UI model might be the same as in GMail where it's possible to keep multiple logged-in user accounts and switch between them through the account selector in the top right corner.
I'm no django-authentication expert, so I am not able to even tell whether this is possible in the context of a django based app.
Does anyone know of any ready-made app/middleware to get this done? Or maybe point me in the right direction if I have to extend or modify existing code?
Thanks a lot.
I haven't looked for any existing solution for this, so this is how I would go about it from scratch.
You'd need to add storage to the user session to hold multiple users. Currently it looks much like:
{'_auth_user_backend': 'membership.auth_backends.MyCustomAuthenticationBackend',
'_auth_user_hash': 'e2c8ecf1e7ecdbd<snip>',
'_auth_user_id': '3806'}
and I would add an array to the session:
logged_in_users = [{'_auth_user_backend': ... }, {}, {}] # one auth dict per user
Then when you "switch users", edit the session object to move that user's auth details (id, hash and backend) into the top-level ones in the session.
You'll also have to write a custom login function that stores the login into the logged_in_users array, and takes out the bit in the current login function that flushes your session if the key is the same as the session of a different logged in user. Similarly, you'll need to think what happens when you logout.
You're building a web application. You need to store the state for a shopping cart like object during a user's session.
Some notes:
This is not exactly a shopping cart, but more like an itinerary that the user is building... but we'll use the word cart for now b/c ppl relate to it.
You do not care about "abandoned" carts
Once a cart is completed we will persist it to some server-side data store for later retrieval.
Where do you store that stateful object? And how?
server (session, db, etc?)
client (cookie key-vals, cookie JSON object, hidden form-field, etc?)
other...
Update: It was suggested that I list the platform we're targeting - tho I'm not sure its totally necessary... but lets say the front-end is built w/ASP.NET MVC.
It's been my experience with the Commerce Starter Kit and MVC Storefront (and other sites I've built) that no matter what you think now, information about user interactions with your "products" is paramount to the business guys. There's so many metrics to capture - it's nuts.
I'll save you all the stuff I've been through - what's by far been the most successful for me is just creating an Order object with "NotCheckedOut" status and then adding items to it and the user adds items. This lets users have more than one cart and allows you to mine the tar out of the Orders table. It also is quite easy to transact the order - just change the status.
Persisting "as they go" also allows the user to come back and finish the cart off if they can't, for some reason. Forgiveness is massive with eCommerce.
Cookies suck, session sucks, Profile is attached to the notion of a user and it hits the DB so you might as well use the DB.
You might think you don't want to do this - but you need to trust me and know that you WILL indeed need to feed the stats wonks some data later. I promise you.
I have considered what you are suggesting but have not had a client project yet to try it. The closest actually is a shopping list that you can find here...
http://www.scottcommonsense.com/toolbox.aspx
Click on Grocery Checklist to open the window. It does use ASPX, but only to manage the JS references placed on the page. The rest is done via AJAX using web services.
Previously I built an ASP.NET 2.0 site for a commerce site which used anon/auth cookies automatically. Each provides you with a GUID value which you can use to identify a user which is then associated with data in your database. I wanted the auth cookies so a user could move to different computers; work, home, etc. I avoided using the Profile fields to hold onto a complex ShoppingBasket object which was popular during the time in all the ASP.NET 2.0 books. I did not want to deal with "magic" serialization issues as the data structure changed over time. I prefer to manage db schema changes with update/alter scripts synced with software changes.
With the anon/auth cookies identifying the user on the client you can use the ASP.NET AJAX client-side to call the authentication web services using the JS proxies that are provided for you as a part of ASP.NET. You need to implement the Membership API to at least authenticate the user. The rest of the provider implementation can throw a NotImplementedException safely. You can then use your own custom ASMX web services via AJAX (see ScriptReference attribute) and update the pages with server-side data. You can completely do away with ASPX pages and just use static HTML/CSS/JS if you like.
The one big caveat is memory leaks in JS. Staying on the same page a long time increases your potential issue with memory leaks. It is a risk you can minimize by testing for long sessions and using tools like Firebug and others to look for memory leaks. Use the JS Lint tool as well as it will help identify major problems as you go.
I'd be inclined to store it as a session object. This is because you're not concerned with abandoned carts, and can therefore remove the overhead of storing it in the database as it's not necessary (not to mention that you'd also need some kind of cleanup routine to remove abandoned carts from the database).
However, if you'd like users to be able to persist their carts, then the database option is better. This way, a user who is logged in will have their cart saved across sessions (so when they come back to the site and login, their cart will be restored).
You could also use a combination of the two. Users who come to the site use the session-based cart by default. When they log in, all items are moved from the session-based cart to a database-based cart, and any subsequent cart activity is applied directly to the database.
In the DB tied to whatever you're using for sessions (db/memcache sessions, signed cookies) or to an authenticated user.
Store it in the database.
Do you envision folks needing to be able to start on one machine (e.g. their work PC) but continue/finsih from a different machine (e.g. home PC)? If so, the answer is obvious.
If you don't care about abandoned carts and have things in place for someone messing with the data on the client side... I think a cookie would be good -- especially if it's just a cookie of JSON data.
I'd use an (encrypted) cookie on the client which holds the ID of the users basket. Unless it's a really busy site then abandoned baskets won't fill up the database by too much, and you can run a regular admin task to clear the abandoned orders down if you care that much. Also doing it this way the user will keep their order if they close their browser and go away, a basket in the session would be cleared at this point..
Finally this means that you don't have to worry about writing code to deal with de/serialising the data from a client-side cookie, while later worrying about actually putting that data into the database when it gets converted into an order (too many points of failure for my liking)..
Without knowing the platform I can't give a direct answer. However, since you don't care about abandoned carts, then I would differ from my colleagues here and suggest storing it on the client. Why store it in the database if you don't care if it's abandoned?
Then again, it does depend on the size of the object you're storing -- cookies have their limits after all.
Edit: Ahh, asp.net MVC? Why not use the profile system? You can enable an anonymous profile if you don't want to bother making them log in
I'd say store the state somewhere on the server and correlate it to the user's session. While a cookie could ostensibly be an equal place to store things, if you consider security and data size, keeping as much data on the server as possible becomes a good thing.
For example, in a public terminal setting, would it be OK for someone to look at the contents of the cookie and see the list? If so, cookie's fine; if not, you'll just want an ID that links the user to the data. Doing that would also allow you to ensure the user is authenticated to the site in order to get to that data rather than storing everything on the machine - they'd need some form of credentials as well as the session identifier.
From a size perspective, sure, you're not going to be too concerned about a 4K cookie or something for a browser/broadband user, but if one of your targets is to allow a mobile phone or BlackBerry (not on 3G) to connect and have a snappy experience (and not get billed for the data), minimizing the amount of data getting passed to the client will be key.
The server storage also gives you some flexibility mentioned in some of the other answers - the user can save their cart on one machine and resume working with it on another; you can tie the cart to some form of credentials (rather than a transient session) and persist the cart long after the user has cleared their cookies; you get a little more in the way of fault tolerance - if the user's browser crashes, the site still has the data safe and sound.
If fault tolerance is important, you'll need some sort of persistent store like a database. If not, in application memory is probably fine, but you'll lose data if the app restarts. If you're in a farm environment, the store has to be centrally accessible, so you're again looking at a database.
Whether you choose to key by transient session or by credentials is going to depend on whether the users can save their data and come back later to get it. Transient session will eventually get cleaned up as "abandoned," and maybe that's OK. Tying to a user profile will let the user keep their data and explicitly abandon it. Either way, I'd make use of some sort of backing store like a database for fault tolerance and central accessibility. (Or maybe I'm overengineering the solution?)
If you care about supporting users without Javascript enabled, then the server side sessions will let you use URL rewriting.
If a relatively short time-out (around 2 hours, depending on your server config) is OK for the cart, then I'd say the server-side session. It's faster and more efficient than accessing the DB.
If you need a longer persistence (say some users like to leave and come back the next day), then store it in a cookie that is tamper-evident (use encryption or hashes).