views:

662

answers:

14

Hi

I am using asp.net mvc 2.0 and I am wondering how secure is it to put information in a cookie?

Like I put in my cookie a forms authentication ticket that is encrypted so can I put information that could be sensitive in there?

   string encryptedTicket = FormsAuthentication.Encrypt(authTicket)
   HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

Like I am not storing the password or anything like that but I want to store the UserId because currently every time the user makes a request to my site I have to do a query and get that users Userid, since every table in my db requires you to use the userId to get the right row back.

So these start to add up fast so I rather have it that if a user is authenticated once then that's it till they need to be re-authenticated again. If I would store this userId I could save so many requests to the database.

Yet I don't want it floating around in clear text as potential someone could use it to try to get a row out of a database when they really should not be.

Show how good is this encryption that Authentication uses?

+1  A: 

The use you are looking at is the exact intended purpose of being able to store information in the Forms Auth Ticket.

Chris Marisic
+8  A: 

The encryption is good enough, that's not the weak link.

The weak link is that the cookie value could be intercepted, and someone else could impersonate the user.

So, the information in the cookie is safe enough, but you can't protect the cookie itself.

Guffa
-1 this is a gross misuse of cryptography, it is best to avoid the problem altogether.
Rook
@The Rook: So what is wrong with the answer? Are you voting down my answer because you think that there is something wrong with the question?
Guffa
@Guffa I voted you down because I don't want anyone attempting this mistake. Sessions are to correlate a browser with server side data, there the use of a cipher in a cookie defeats the purpose.
Rook
@The Rook: So why only this answer that doesn't say anything about whether it's a good idea or not, and not any of the answers that actually say that it's a good idea to encrypt cookies?
Guffa
@Guffa unfortunately this post has a security tag, and there for I vote anyone down who proposes an insecure approach. This is a bit of an authoritarian dick move, but the spreading of weak designs hurts people and there for should be suppressed. Don't take this personally, if you change your post saying encryption only adds more attack scenarios which could be easily avoided, i'll give you a +1.
Rook
@The Rook: Your motivation doesn't make sense, as you clearly haven't voted down any of the anwers that actually promote the encryption.
Guffa
@Guffa I have updated my post and I think you would find it interesting. I also voted down other posts that where incorrect. I vote based on the post not the person ;).
Rook
@The Rook: best way is to not even store the salted hash in the cookie
Frank Computer
@Frank Computer I'm not sure why you would put a salted hash in a cookie. A cookie should be a very large random value, if it is a password hash then you don't need to break the hash to authenticate.
Rook
@The Rook: Perhaps the whole concept of using cookies is flawed!.. There has to be a beeter method. I never like the idea of websites being able to collect website-visitors profile info. When I surf the net, I use IE's InPrivate Browsing. There's also several other aspects of the web which I consider to be security holes. Another reason why none of my customers run their business apps on a system connected to the web. They have another stand-alone system for that.
Frank Computer
@Frank Computer Wow thats a new one. Security to me is about making things less useful. Networks are incredibly useful and many businesses can not function without it, and many attacks are not possible without network access. Cookies are too useful, and when implemented properly they are can be very safe. However, I don't think you have a very good understanding security because you use IE, which is without a doubt the lest secure software ever made. (That is going by number of vulns found and number of days left unpatched.)
Rook
@The Rook: Thought you would find my remarks a novelty!.. Cookies implemented properly?..That's the problem, they're not!.. There's just to much complexity with HTML, .NET, etc. which creates security holes. It all needs re-design, including hiding source code, cookies and all the other stuff. Best way to protect is to prevent access to any info, including cookies.. So if IE8 InPrivate browsing is the least secure, what's better?.. I use a separate computer exclusively for browsing the web and dont store personal info on it.. Thats the best I can do to safeguard sensitive info.
Frank Computer
@Frank Computer Do everything on the OWASP A3: Broken Authentication and Session Management, then use httponly cookies. After you do that, an attacker is going to look elsewhere for weaknesses. In terms of browser security I would use Firefox or Chrome running on Linux. Also use Evince or another PDF reader instead of Adobe Acrobat Reader. Unfortunately flash is still a weak spot. But its better than the month long "Help Centre" IE 0-day that was patched... yesterday (Hopefully you have updated :)
Rook
-1 the asp.net oracle padding attack came out after this post. But it totally supports my argument. @Guffa do not write security systems, your approach is flawed.
Rook
A: 

Hi,

if it is secured by a cipher, it is OK.

But as Guffa said:

The weak link is that the cookie value could be intercepted, and someone else could impersonate the user.

But what is more important - the cookie solution you describe isn't very smooth. For storing user specific data, ASP.NET has Session object. Use it and you'll find it very useful ;-).

Tomas
Sorry about the -1, but I can't let people spread bad security advice. I know you only have 9, err 7 points, please try and post in areas that you are masterful.
Rook
+6  A: 

As you've stated, a good practice for storing any data in cookies is to encrypt the data. Encrypt before putting into the cookie, and decrypt after reading it.

In the example of storing a user identifier, choose something that's not likely to be used against your system. For the user id, use a guid rather than the likely incrementing integer that's the PK on the database table. The guid won't be easily changed to successfully guess another user during an attack on your system.

Once the user has been identified or authenticated, go ahead and store the user object, or key properties in Session.

p.campbell
You might want to see the following http module for automatically encrypting cookies: http://www.codeproject.com/KB/IP/CookieEncryptionModule.aspx?msg=2577001#xx2577001xx
Chris Lively
A: 

To ensure proper auth cookie protection, you should make sure that you specify a secure encryption/hashing scheme (usually in the web.config) by setting the machineKey validation="SHA1" property (I use SHA1 but you can replace that with a different provider if desired). Then, make sure that your forms auth has the protection="All" attribute set so that the cookie is both hashed AND encrypted. Non-repudiation and data security, all in one :)

ASP.NET will handle encrypting/decrypting [EDIT: only the auth cookie!] the cookie for you, although for custom cookies you can use the FormsAuthentication.Encrypt(...) method, so just make sure that you're not sending the UserId via other cleartext means like the querystring.

Josh E
Not exactly. This doesn't ecrypt ALL cookies, just role cookies when using the membership provider.
Chris Lively
true, but he's using FormsAuthentication.Encrypt(authTicket), which will use the web.config encryption settings
Josh E
A hashing algorithm is not an encryption algorithm.
Rook
right, which is why I stated that the cookie would be both "hashed AND encrypted"
Josh E
+6  A: 

Along with cookie encryption, you should also implement a rotating token to prevent replay attacks.

The idea being that the encrypted cookie contains some value which can be compared to a known value on the server. If the data matches, then the request succeeds. If the data doesn't match then you are experiencing a replay attack and need to kill the session.

UPDATE
One of the comments asked if I meant to store the value in the cookie. The answer is yes. The ENTIRE cookie should be encrypted, which can be automatically done through the use of an HttpModule. Inside the encrypted cookie is any of your normal information + the changing token.

On each post back, check the token. If it's valid, allow the transaction, create a new random token, store in the cookie, and send that back to the browser. Again, in an encrypted form.

The result is that your cookie is secure (you are using 3DES?) and any attacker would have an extremely limited window of opportunity to even attempt a replay attack. If a token didn't pass muster, you could simply sound the alarm and take appropriate measures.

All that's needed server side is to keep track of the user and their current token. Which is usually a much smaller db hit than having to look up little things like the users name on each page load.

UPDATE 2
I've been trying to figure out whether this is better or worse than keeping the changing value stored in session. The conclusion I've come to is that storing a rotating value in session on the web server does absolutely nothing to prevent replay attacks and is therefore less secure than putting that value in a cookie.

Consider this scenario. Browser makes request. Server looks at the session id and pulls up the session objects, work is then performed, and the response is sent back to the browser. In the meantime, BlackHat Bob recorded the transaction.

Bob then sends the exact same request (including session id) to the server. At this point there is absolutely no way for the server to know that this is a request from an attacker. You can't use IP as those might change due to proxy use, you can't use browser fingerprinting as all of that information would have been recorded in the initial exchange. Also, given that sessions are usually good for at least 30 minutes and sometimes much longer, the attacker has a pretty good sized window to work in.

So, no matter what, to prevent replay you have to send a changing token to the browser after each request.

Now this leaves us with the question about whether to also store values such as the user id in an encrypted cookie or store it server side in a session variable. With session you have concerns such as higher memory and cpu utilization as well as potential issues with load balancing etc. With cookies you have some amount of data that is less than 4kb, and, properly done, in the 1kb or less range that gets added to each request. I guess it will boil down to whether you would rather add more / larger servers and internal networking equipment to handle the requests (session) or pay for a slightly larger internet pipe (cookie).

Chris Lively
You should be more specific. I assume that you do not mean to store the token in the cookie?
mikerobi
@mikerobi: bad assumption. see update.
Chris Lively
@Chris Lively, that makes sense, I thought you might be referencing to an anti CSRF token, which can't be stored in a cookie. This is a great solution to storing secure data in a cookie, but I don't see any advantage over traditional sessions.
mikerobi
+1  A: 
Joel Coehoorn
I find it rather unhelpful to suggest storing an id in a cookie that is used to look up data when that is exactly what the OP questioned.
Chris Marisic
@Chris - I added a few sentences to the end that hopefully make things clearer.
Joel Coehoorn
I believe you mean "asymmetric", not "asynchronous".
rmeador
Session falls down when running multiple web servers. At that point, session needs to be stored / retrieved either back in the database server or in a memcache farm. If you aare storing session in the database, then you've effectively increased the number of database calls as .net will happily query, deserialize, serialize, and query again for each page call.
Chris Lively
Which brings us to balancing whether a small cookie coming over the wire is better or worse, than increasing site complexity and having the web server make calls to other machines on your network (db or memcache) to retrieve the data. Given that a number of sites happily send down content in the 40 to 50kb+ range, a small 1kb or less cookie isn't really all that much overhead.
Chris Lively
+3  A: 

For your very specific scenario (user id), the short answer is NO!

For the long answer, imagine this hypothetical scenario:

  1. You navigate to stackoverflow.com;
  2. Fill your username/password and submit the form;
  3. The server sends you a cookie containing your user ID, which is going to be used to identify you on the next requests;
  4. Since your connection was NOT secure (HTTPS), a bad guy sniffed it, and captured the cookie.
  5. The bad guy gains access to your account because the server didn't store, let's say, your IP address, and thus, can't distinguish between your machine and the bad guy's.

Still in this scenario, imagine the server stored your IP address, but you're on a corporate LAN, and your external IP is the same of another 100 machines. Imagine that someone that has access to one of these machines copied your cookie. You already got it, right? :-)

My advice is: put sensitive information on a HTTP session.

UPDATE: having a session implies a cookie (or at least an ugly URL), thus leading us back to the very same problem: it can be captured. The only way to avoid that is adding end-to-end encryption: HTTP+SSL = HTTPS. And if someone says "oh, but cookies/sessions should be enough to discourage most people", check out Firesheep.

jweyrich
There are ways to sniff out sessions as well, but I agree with the principle here that you need to be careful with cookies.
Joel Coehoorn
+1  A: 

No. It have been shown with Padding oracle attack that receiving encrypt data (CBC) can be dangerous because of the errors leakage.

I'm definitely not a crypto expert but I recently saw a demo where encrypted view-state was decrypt using this attack.

h3xStream
A: 
HttpCookie c;
c.Secure = true;

Obviously this only works when transmitting via SSL, but this setting tells the browser not to send the cookie unless the connection is SSL, thus preventing interception via man-in-the-middle attacks. If you are not using a secure connection, the data in the cookie is totally visible to anyone passively sniffing the connection. This is, incidentally, not as unlikely as you'd think, considering the popularity of public wifi.

Brian
+3  A: 

In an ideal world with an ideal cipher this wouldn't be a problem. Unfortunately in the real world nothing is ideal, and there never will be an ideal cipher. Security is about solving these real world threats. Cryptographic systems are always vulnerable to attack, weather it be a trivial(brute force) attack or by a flaw in the primitive its self. Further more it is most likely that you will botch the implementation of the primitive, common mistakes include non-random or null IV, Key management, and incorrect block Cipher mode.

In short this is a gross misuse of cryptography. This problem is best sovled by avoiding it all together by using a session variable. This is why sessions exist, The whole point is to link a browser to state data stored on the server.

edit: Encrypting cookies has led to the ASP.NET oracle padding attack. This should have been avoided all together by using a Cryptographic Nonce. Like i said, this is a gross misuse of cryptography.

Rook
I completely agree. The right way is to store the user id in the session object and avoid the problems that come with the current solution: pick good algorithm, implement encryption properly, protect and store the keys, avoid replay attacks, etc. The rule should be: "If it is not needed in the client side, it should not go to the client side."
fms
This blog entry by Jeff Atwood last year is about this very topic: http://www.codinghorror.com/blog/2009/05/why-isnt-my-encryption-encrypting.html
Todd Owen
The OP's question completely revolves around security, and Jeff's blog entry ignored a very real problem of replay attacks. Simply putting it in session and forgetting about it is, imho, on the same level as not understanding what your encryption code does.
Chris Lively
@Chris Lively i agree, most programmers think encryption is just some kind of magic wand, they don't realize how difficult it is to implement.
Rook
A: 

The first thing to address is whether the connections involved are secure. If they are not, assume the cookie or anything else between you and the client will be intercepted.

A cookie can be a liability once it is on the client machine. Review cookie theft, cross-site request forgery, confused deputy problem.

Rab
This has nothing to do with the OPs question.
Rook
It is relevant. OPs question is "is putting [this] data in cookies secure." My 1st statement is that any non-secure connection compromises the cookie, subjecting to misuse. That's likely the weakest link, and s/he stated that the information should not be "floating around in clear text." Well, it had might as well be clear text if anyone can get it and use it the same way the client can.2nd is that cookies can be exploited on the client machine once out of OPs control; select methods used for such are listed. Question answered, not secure.Good for you for suggesting an alternative approach.
Rab
+1  A: 

Encrypting the userid value in the cookie only prevents the user from knowing what the value is. It does not

  • prevent cookie replay (use SSL to prevent an attacker from intercepting a victim's cookie)
  • prevent tampering (an attacker can still blindly flip bits in the encoded cookie with a chance that it will decode to a valid userid, use an HMAC to prevent this)
  • completely prevent a user from getting the decrypted value (the user can brute force the value off line, use a strong encryption key to make success less probable)

Encrypting the cookie also introduces a key management problem. For example, when you rotate the encryption key you have to make sure "live" sessions with the old key won't immediately fail. You thought about managing the encryption key, right? What happens when admins leave? It's compromised? etc.

Does your architecture (load balancers, server distribution, ...) preclude using server-side session objects to track this information? If not, tie the userid to the session object and leave the "sensitive" data on the server -- the user only needs to have a session cookie.

A session object would probably be a lot easier and more secure for your stated concern.

Mike
+1 I agree with this post.
Rook
A: 

Cookies limitations: size, may be disabled and security risk(tampering). Of course if you encrypt cookie, there could be a performance hit. Session and Viewstate would be good alternative. If you want it to be stored at client side, viewstate would be better. You can encrypt the string userid and store in viewstate. Session would be best option. If your database calls are slow, consider caching

Viewstate

PRR