Why need cookies to retain stateful information? - security

I was reading the wiki for cookies and they said it is needed to retain stateful information such as item in cart etc. But why do you need to do it? Why don't just store the state in database table for example?

You can store the state in the db but you need to know who is the owner of that state, so you need to identify the client in between the requests.
Think of the cookies like a caller id for the browser. That is their main use. When you hit my web server the first time with your browser, I say, 'hey, let me set this caller id somewhere on your browser' so next time when you call, I'll just read it and then I know it's you again. Once I know it's you, then I can look in my db for more info, such as your cart items.
Also the caller id I set can't be read or modified by other websites, if they want to identify you they need to set their own.

Cookies are useful to preserve information on the client side.
For instance, in the example you give, with a cookie you could save the cart of someone who isn't logged in or registered yet.
Whereas if you were using a database to retrieve such data, you would need a reliable way to identify the current visitor, and you probably wouldn't have many options apart from asking for a login.
In general, you would want to put in cookies information that would make the life of your visitor easier, but that is not essential to preserve (cookies do expire, they can be emptied, and the visitor could use a different browser etc).

Related

Which back-end design choice is better for handling guest users? Storing guests as users with is_guest feild, or storing guest data on the session?

I am building an ecommerce website which should be able to handle guest checkout. When a user visits the website, they are considered "Guests" unless they register / log-in to their account.
However, even as a guest, certain information needs to be stored about that visitor (partially incase they make an account in the furture, but also just for the website to function for them) like their prefered currency, email (if provided), cart and its contents, and an order_id (if they placed an order)
My question is which of the following choices would be better for handling this?
By the way: I am using NodeJS's express-session in this project.
Creating a "User" object for all new visitors and adding the user_id to the session. In this case that user object would need a feild called is_guest: true/false to tell the two apart, and it would also need a is_logged_in: true/false feild so the front-end can tell whether to load the log-in form or the profile page because a user object would always be present.
Only creating a "User" object after an account has been registered through the register form, and storing all data about the cart and email ect. for guests on the session object instead.
I can see problems with both. 1) could result in a really large database if all new visitors create a user object. 2) could result in information being scattered more and the session object becoming cluttered (especially if the cart becomes large). Having never done something like this before, I would appriciate any ideas about objections or solutions to the approaches and what you think would be the best.
Both solutions are fine, and I've seen both being used.
I would guess that storing things in the database is more common. Since you will probably be logging user interactions in your database anyways, it won't take up much more data. Secondly it's slightly simpler to use the same function to render pages for logged-in and logged-out users.
If you don't use a database, you may wish to use LocalStorage instead of a cookie since there are size limits to cookies (although few carts will get large enough to reach that limit).

How to manage GUIDs offline

Given that clients can tamper with GUIDs if they are generated client-side, wondering how to mitigate this problem if you allow working offline.
Say you have a Todo list application and are working offline. From what I'm thinking, as you create todos, the client is creating GUIDs for the todos, as well as any attachments or associated records. Then say you go back online and it syncs. The GUIDs created on the client could have been tampered with, so something possibly needs to happen during a merge. Maybe all new GUIDs are created server-side, and sent back to the client to overwrite the client-generated ones. Not sure.
Wondering what best-practice is here.
I think yes, ids could be reassigned when sent to the server. One way this could be done is have a client-side id and a server-side id, the latter only assigned if it's saved. The client-side id can then also be removed from the design, but then upon a succesful save all references must be updated.
And then the problem is the inevitable inconsistency, because what happens if the server already received the update, assigned a server-side id, but the confirmation response never made it back to the client. Upon the next download, the client will see a new item on the server which it cannot associate with any client-side item, unless there is some kind of a heuristic to identify duplicates (eg. if all fields are the same in a client item without a server-side id, it is most probably the same).
I think this is less of a security question though, if the format of the id is validated (for example it must be a guid, ie. numbers, letters and dashes), it doesn't really matter what exactly the client sends. So from a security point of view, this is almost purely an input validation question, which of course must be in place, errors must be thrown on already existing ids and so on. Then it touches on access control as well, if multiple users are using the app, but that's a different topic, any access must be authorized anyway, and access control decisions must not be made solely on the id. That is, it's not a good access control model if you can access anything you know the id of.

Is it safe to put the entire user in a session vs just the user ID for node/express?

I am using node/express and was wondering if it is safe to put the entire user object in the session rather than just the Id. If I do just the Id then this means I must make another DB call when I go to get the currentUser.
I have seen people do it, but if it is more safe to just put the Id then I will go about doing that. I should state that I would take the password off the user before attaching it to the session or any other sensitive data.
There's nothing especially unsafe about it, but generally not considered a good practice. When you update your user data, you have to update your session and database, so now you have to keep those in sync, which creates challenges.
Also keep in mind your session store. The more data in your session, the larger the storage requirements for your session store, maybe not a problem, but something to consider.

Is this safe for client side code?

I'm writing a GWT application where users login and interact with their profile. I understand that each form entry needs to be validated on the server, however, I am unsure about potential security issues once the user has logged in.
Let me explain. My application (the relevant parts) works as follows:
1 - user enters email/pass
2 - this info is sent back to the server, a DB is queried, passwords are checked (which are salted and hashed)
3. if the passwords match the profile associated w/ the email, this is considered success
Now I am unsure whether or not it is safe to pass the profile ID back to the client, which would then be used to query the DB for information relevant to the user to be displayed on the profile page.
Is there a possibility for a potential user to manually provide this profile ID and load a profile that way? My concern is that somebody w/ bad intentions could, if they knew the format of the profile ID, load an arbitrary amount of information from my DB without providing credentials.
-Nick
What you are dealing with here is a session management issue. Ideally, you want a way to keep track of logged in users (using random values as the session key), know how long they have been idle, be able to extend sessions as the user is using the site, and expire sessions.
Simply passing the profile ID to the client, and relying on it to send it back for each request is not sufficient - you are correct with your concern.
You want to keep a list of sessions with expiration times in a database. Every time an action is executed that needs user permissions (which should be pretty much everything), check to see if the session is still valid, if it is, extend it by however long you want. If it is expired, kill the session completely and log the user out.
You can store your session keys in a cookie (you have to trust the client at some point), but make sure they are non-deterministic and have a very large keyspace so it cannot be brute forced to get a valid session.
Since you're logging a user in, you must be using a backend that supports sessions (PHP, .Net, JAVA, etc), as Stefan H. said. That means that you shouldn't keep any ids on your client side, since a simple id substitution might grant me full access to another user's account (depending on what functionality you expose on your client, of course).
Any server request to get sensitive info (or for any admin actions) for the logged in user should look something like getMyCreditCard(), setMyCreditCard(), etc (note that no unique ids are passed in).
Is there a possibility for a potential user to manually provide this profile ID and load a profile that way? My concern is that somebody w/ bad intentions could, if they knew the format of the profile ID, load an arbitrary amount of information from my DB without providing credentials.
Stefan H is correct that you can solve this via session management if your session keys are unguessable and unfixable.
Another way to solve it is to use crypto-primitives to prevent tampering with the ID.
For example, you can store a private key on your server and use it to sign the profile ID. On subsequent requests, your server can trust the profile ID if it passes the signature check.
Rule 1 - Avoid cooking up your own security solution and use existing tested approaches.
Rule 2 - If your server side is java then you should be thinking along the lines of jsessionid. Spring Security will give you a good starting point to manage session ids with additional security features. There will be similar existing frameworks across php too (i did not see server side language tags in the question).
Rule 3 - With GWT you come across javascript based security issues with Google Team documents and suggests XSRF and XSS security prevention steps. Reference - https://developers.google.com/web-toolkit/articles/security_for_gwt_applications

Using an automatically generated URL as a kind of a password

Assume I want visitors of my site to be able to fill in a long form. That's not necessary for them to fill it in to use the site, but if they want to send a story to me, they need to fill it in. So, some of them will wish to do it, some won't. The form is quite large so visitor may want to leave it semi-filled to come back later and finish it. To make the process as easy as possible for the visitor, I want him just to click a link "Create a story" that will redirect the visitor to an automatically generated url, like www.mysurveys.com/7Bs3h4vSWEe. Here the visitor works with his form and clicks 'Save' when he wants to save it so that to return back later to finish it. The form data is kept in the database with its generated ID. When the visitor thinks the form is filled properly and is done, he clicks 'Send for review' and then the form goes to me.
The question is: how secure is to use this automatically generated URL as the only credential for the user? I suppose any sniffer could easily get the url visitor uses to fill in the form. How to make a process like this as simple as possible? What are ways to make it a little more safe? I know I can do it using standard user registration pattern but I want to make it simpler.
This ID is a lot like having a session id for the user and in that sense its not a compromise. One difference is that session id's should always expire. If security is a concern then HTTPS should be used to prevent eavesdropping.
This url value should be a Cryptographic Nonce. You should also take brute force into consideration. If someone is guessing a lot of keys that don't exist, prompt them with a captcha.
It's not that secure, BUT sniffing is basically the only attack, AND unless the attacker doesn't care whose URL they get, they would have to target their victim quite specifically.
I wouldn't use this for, for example, financial information, or third-party-confidential information, but for low-risk information it might well be fine.
edit: I've ignored brute force, but much the same applies, and as other answers suggest, there are protections against that, like captcha.

Resources