When thinking about security and user experience, what information id OK, acceptable, or even a good idea to store in a cookie?
EDIT:
With the understanding that sensitive info, like user names, passwords, SSN, credit card numbers don't belong there, what does?
Definitely not passwords! Or anything sensitive... remember that cookies are stored on people's computers so from your point of view (as a website developer), they're basically out in the wild, potentially accessible to anyone.
A common practice is to just store a session ID in a cookie, and store all other relevant information in a database (or file, or whatever) on the server, indexed by session ID.
It's a lot easier to answer what's not acceptable to store in a cookie. Anything that should remain secure shouldn't be stored. That includes passwords, credit card numbers, social security numbers, etc.
I think it's okay to store a user's login name, since that information really isn't sensitive. A user's preferences settings for your site should be okay as well.
Remember, cookies are just plain text files that someone (or some application) can open up and read or write, so you shouldn't trust information you receive from a cookie, either. Sanitize it just like any other user input.
One suggestion is that you not store any keys to your database in cookies. i.e. email addresses, column ID's etc. If so, you should encrypt the data.
User customization ID (a set of preferences stored in a db which you fetch on page load)
No personal information
Well other than sensitive and security related data there really is no limit to what you can't and can store but just remember that if that data is not persisted on the server side, it could be lost altogether and it should be assumed that if the user deletes cookies, it won't inconvenience him too much to restore his settings/configuration. There are no guidelines other than using good common sense here.
There are however limits to cookies. You should not exceed 19 cookies per domain and no cookie should be bigger than 4KB (4096 bytes) as per IE limits:
Each cookie begins with a name-value
pair. This pair is followed by zero or
by more attribute-value pairs that are
separated by semicolons. For one
domain name, each cookie is limited to
4,096 bytes. This total can exist as
one name-value pair of 4 kilobytes
(KB) or as up to 20 name-value pairs
that total 4 KB. If the computer does
not have sufficient space to store the
cookie, the cookie is discarded. It is
not truncated. Applications should use
as few cookies as possible and as
small a cookie as possible.
Additionally, applications should be
able to handle the loss of a cookie.
If a Web application uses more than 19
custom cookies, ASP session state may
be lost. Internet Explorer 4.0 and
later versions allow a total of 20
cookies for each domain. Because
ASPSessionID is a cookie, if you use
20 or more custom cookies, the browser
is forced to discard the ASPSessionID
cookie and lose the session.
Don't store anything in a Cookie that will allow your site to be hacked or accessed without going through proper channels. Usually, just a session ID or user ID is stored in a cookie, and often in a form intended to be opaque to anyone but the cookie consumer.
I would avoid storing anything that, if altered, would compromise the functionality of the site.
So, storing something like a user id, shopping cart items' prices, password, user roles, etc. are problematic. I keep this kind of thing in the user's session data on the server.
Storing a user's name or profile info (for display purposes only), customization preferences (colors, text, whatever) are fine.
There is nothing wrong in saving sensitive information on a cookie, as long as that information is encrypted (the data itself is not clear text) and the cookie is a secure cookie (https). Actually it is much worst to have all of the sensitive data in one DB server that might be hacked and then you are facing a potentially much bigger security issue.
Related
My website saves username and MD5ed password of user in cookies for login purpose.
My question is, can trojans in users pc steal that cookie and use it in another pc? If can, what is safe solution for remembering users?
Of course they can.
You can mix user's IP into MD5, but it still doesn't protect user for 100% (since trojan can use user's IP as well as steal cookies).
As long as trojan uses the same computer there is no difference between user and trojan, hence protection is not theoretically possible.
A trojan can access any file stored on the infected PC, inluding cookies. What you can do to mitigate the risk is to store a unique ticket id instead of the hashed password in the cookie, and save some additional information on the server for that ticket on the server - browser version, operating system etc. and only accept the ticket if the metadata match, too. That said, it's still not perfectly safe that way; if your web service is really critical, you better ask for the password every single time. (But since a trojan probably also installs a keylogger, this still isn't enough to be really safe...)
Trojans can also record the keys pressed by the user on the keyboard, so it's not really something you should worry about, because you can't do anything about it. It's the user responsibility to protect against malware.
What you should worry about are man-in-the-middle attacks, the fact that MD5 is not secure and the fact that you should add salt to your hashes.
By the way, most websites use cookies not to store usernames and passwords, but ephemeral session IDs. These session IDs become invalid when the user clicks on the "log out" button.
I found that the cookie in browser is a random string which web server sends to each client for remembering users' information purpose. But I don't understand in programmers viewpoint, what does cookie use for?
For example, I've used EditThisCookie extension in Chrome Browser to read wikipedia.org site's cookie, in the following picture included here. The value of this cookie (sessionId) is useless for programmers (EDIT: I mean I don't extract any information from this cookie, I know the cookie is very important for web developers, so sorry about my poor expression). If I get this cookie, which kind of information I can understand about the users?
Looking for some help! Thank you very much!
The example about cookie
http://i102.photobucket.com/albums/m86/dienkun1/cookie_example_zps455f0dad.png
EDIT: Sorry, I've just expressed my problem in wrong way.
Actually, I am going to write an extension for collecting users' preferences via users' cookie, but I can't understand anything what information can be extracted from cookie. I've read about cookie in many documents, like wikipedia, and all of them just show how to get cookie, the definition of cookie, classified... and nothing about which information we can get from cookie.
Thank you very much!
Why do you say that the sessionId is useless for programmers? It actually can be extremely useful. Somewhere on Wikipedia's servers, they're probably storing quite a bit of information about your session. This could include things like whether you've already hidden one of their fundraising banners (so that it won't keep showing it to you again and again), to things that are required for basic functionality, such as what user you are currently logged in as.
However, Wikipedia is storing this same information for millions of sessions. It needs a way to tie the information back to each individual browser. That sessionId is how it does so. It set the sessionId in a cookie when you first accessed the page, and that cookie gets sent back to the server with every request you make to it now. Then they have code on the back end that reads that sessionId from the cookie and uses it to look up all of the information specific to your session, and do whatever needs to be done with it.
You could of course store the session information itself in the cookies, but there are a couple problems with that. First, there are limits on the size of each cookie, and on the overall size of all cookies for a single domain. Some of the data you want to store might not even fit. But the bigger problem is that cookies can be very easily manipulated by the end user. If you stored the information of who the user is logged in as in a cookie, the user could just change that value to something else, and suddenly be logged in as someone else! Of course, it's also possible that the user could change their sessionId to be some other user's session and suddenly be logged in as them. That's why session IDs need to be as random as possible, and should be long enough that guessing someone else's is basically impossible.
Well, why would someone bother writing a sessionId to a cookie if it's useless?
Cookies are extremely useful when it comes to (e.g) identifying users on your site so you can have them logged in right away, count their visits, track them on your site and even beyond.. only to name a few use cases.
To cite a somewhat popular site (wikipedia.org):
Cookies were designed to be a reliable mechanism for websites to remember stateful information (such as items in a shopping cart) or to record the user's browsing activity (including clicking particular buttons, logging in, or recording which pages were visited by the user as far back as months or years ago).
The most important word here is "stateful".
I have a website (the basic gist of which is described in this question), and I want to have some way to store the username and some information about the user consistently while they use the site (ie, upload and download data).
Right now, given a successful login, I was returning the hash of the password as well as any associated information. Anytime a user tries something, their username, hash, and so forth must match what's in the database. If the user logs out, their local Sinatra session has all information flushed.
I realize that this is a very naive approach. Is there a better way to handle user session information? The wikipedia entry on cookies mentions that a session uid is used instead of this other information; what is the advantage of that approach? I suspect that this approach is also vulnerable to other attacks, but since I verify everything that's done as it's done, I'm not sure what attacks I'm leaving myself open to.
Also, if/when I implement ssl, will these transactions be 'automagically' encrypted, or will I need to do something else to make sure that the strings are protected, if they need to be?
This is actually a very complicated issue. Just to illustrate, you have the problem of account lock-out: If you lock out based on failed attempts, how easy is it for an attacker to DOS your website?
I'll list a few best-practices to get you started:
Store Passwords Salted and Hashed alongside the Username and UserId. (You should also store the salt next to the hash.)
Disallow frequent bad-password attempts. (More frequent than once every few seconds).
If attempts are failing for any given user or any given IP address (more than 3 times a minute) require some form of human-validation, like a CAPTCHA. This allows you to prevent total DOS attacks.
If implementing an auto-login system, use a token authentication system.
For token authentication systems, use a Secure random number generator, send the plain token to the users, but Salt and Hash the token at the database.
Use TLS/SSL if possible, but don't rely on their security once the data is off-the-wire.
If your website is built in asp.net then you can use dot net securities.. which is really very good. and you can also use principle classes in it to make it more secure..
A Note
I have a very good understanding of sessions and the theory of secure web-based authentication, etc., so please don't start with the basics, or give ambiguous answers. I am not looking for Best Practices, because I am aware of them. I am looking for the real risks behind them, that make the Best Practices what they are.
I have read, and agree with the principals that nothing more than a Session identifier should be stored in a Cookie at any given time.
The Story
However... I've inherited a rusty old app that stores the Username, Password, and an additional ID, in a Cookie, which is checked throughout the site as verification/authorization.
This site is always (can only be) accessed via HTTPS, and depending on your stance, is a "low-risk" website.
The application, in its current state, cannot be re-written in such a way as to handle Sessions - to properly implement such a thing would require, essentially, re-writing the entire application.
The Question
When suggesting to the-powers-that-be that storing their user's IDs/Passwords in plaintext, in a Cookie, is an extremely bad idea, what real risks are involved, considering the connection is always initiated and manipulated via HTTPS?
For example: is the only obvious way to compromise this information via Physical Access to the machine containing the Cookie? What other real risks exist?
HTTPS just protects against a man-in-the-middle attack by encrypting the data that goes across the wire. The information would still be in plain text on the client. So anything on the client's computer can go through that cookie information and extract the pertinent information.
Some other risks include cross-site scripting attacks which can enable cookie theft and who knows what kind of browser vulnerabilities which can enable cookie theft.
A given browser's "cookie jar" might not be stored securely, i.e., an attacker might be able to read it without physical access to the machine, over a LAN, or from a distributed filesystem (e.g., if the machine's storing user homes on a storage server, to allow for roaming), or via an application running on the machine.
Some browsers keep cookies in a file that can be displayed on the computer. IE6 comes to mind.
It seems to me that cookies are not all that restricted to a single site. Lots of advertising uses cookies across multiple sites. If I go to NextTag and look for a Nikon D700 camera then
I see NextTag advertisements on slashdot.org. This is an example of a cross-site cookie. Most users use the same password all over the web so if you store the password to one site and make it even a little easy to get to then malicious folks will sooner or later get to it.
To summarize this would be a very very very bad idea. On sites that I work on we don't save users passwords at all. We convert them to a hash key and save the hash key. That way we can validate the user but if we loose the content then there is no exposure of passwords. And this is on the server side, not the browser side!
Most cookies are limited time credentials. For example, session identifiers that expire after a couple hours or are forgotten when the browser windows. Even if the attacker gains access to the session cookie, they are guaranteed neither continued access to the account nor the ability to prevent the original account holder from logging in. Preventing long term account compromise is one of the reasons users are asked for their old password before being allowed to enter a new one.
A cookie containing a username and password, if disclosed, is much longer lived. Also, many users share their passwords between websites. As others have pointed out, the cookie could easily be disclosed via Cross-Site Scripting.
Finally, is the cookie marked with the "Secure" flag? If its not, an active network attack can easily force the browser to disclose it, even if HTTPS is used to serve the entire site.
People here already mentioned the "man in the middle" attack. The thing is that even with https it is still possible. There are different ways to do this - some of them relay on physical access to the network some of them do not.
The bottom line here is that even with https it is still possible for somebody to insert itself between your app and the browser. Everything will be passed through and will look from the browser exactly the same EXCEPT the server certificate. The intruder will have to send his own instead of the real one.
The browser will detect that there are problems with the certificate - usually it will either be issued to a different dns name or, more likely it will not be verified.
And here is the problem: how this violation is presented to the end user and how end user will react. In older versions of IE all indication of the problem was a small broken lock icon on the right side of the status bar - something which many people would not even notice.
How much risk this introduces depends on what is the environment and who (how trainable) the users are
Two two main vulnerabilities are cross site scripting attacks and someone accessing the user's machine.
Have you thought about just storing a password hash in the cookie instead of the raw password? It would require some coding changes but not nearly as many as swapping out your entire authentication system.
I have a internal website that users log into. This data is saved as a cookie. From there the users go on their merry way. Every so often the application(s) will query the authentication record to determine what permissions the user has.
My question is this: Is it more efficent to just query the cookie for the user data when it is needed or to save the user information in viewstate?
[Edit] As mentioned below, Session is also an option.
Viewstate is specific to the page they are viewing, so its gone once they go along thier merry way. Not a good way to persist data.
Your best bet is to use Forms Authentication, its built in to ASP.NET and you can also shove any user-specific information into the Forms Authentication Ticket's Value. You can get 4000 bytes in (after encrypting) there that should hold whatever you need. It will also take care of allowing and denying users access to pages on the site, and you can set it to expire whenever you need.
Storing in the session is a no-no because it scales VERY poorly (eats up resources on the server), and it can be annoying to users with multiple browser connections to the same server. It is sometimes unavoidable, but you should take great pains to avoid it if you can.
Personally, I prefer using a session to store things, although the other developers here seem to think that's a no-no.
There is one caveat: You may want to store the user's IP in the session and compare it to the user's current IP to help avoid session hijacking. Possibly someone else here has a better idea on how to prevent session hijacking.
You can use session data - that way you know that once you have stored it there, users can't fool around with it by changing the query string.
I would use the cookie method. Session is okay but gets disposed by asp.net on recompile, and you have to use a non session cookie if you want to persist it after session anyway. Also if you ever use a stateserver its essentially doing the same thing (stores session in the db). Session is like a quick and dirty fix, real men use cookies.