2

My thinking: A cookie created by FormsAuthentication.SetAuthCookie is always encrypted.

This is my understanding when looking at Microsoft's website, where it says that tickets are encrypted using machineKey inside Machine.config: https://support.microsoft.com/en-ca/help/910443/understanding-the-forms-authentication-ticket-and-cookie

To be 100% sure it is encrypted, I ran the following code:

On one page:

FormsAuthentication.RedirectFromLoginPage(user.user_name, false);

On the next page:

HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

FormsAuthenticationTicket authTicket = 
FormsAuthentication.Decrypt(authCookie.Value);

I see that the value of the cookie was encrypted, and that it decrypted fine.

However, when looking at the top answer here: FormsAuthentication: Is it secure? it seems like it is not recommended to store sensitive information in the cookie. In the above link, he even says "I presume you were storing the cookie in plain-text".

Also the same thing when looking at the second-rated answer here: Storing more information using FormsAuthentication.SetAuthCookie

Why is it assumed that they are storing it in plain text, if the cookie is automatically encrypted using machineKey? Why is there a problem in storing sensitive information there?

P.S. I need to store sensitive information about logged in users.

  • Just because it's encrypted doesn't mean someone can't decrypt it with enough time and effort. Decrypting a temp auth token isn''t so bad as by the time you've figured it out, it will have expired. Decrypting a users password on the other hand... – DavidG Jul 13 '17 at 21:59
  • Thank you. Sorry that I'm kind of new to this, but doesn't that imply that sending users' passwords through HTTPS is also not that secure? – user5928486 Jul 14 '17 at 14:30

1 Answers1

4

Isn't it always encrypted?

If you use vanilla forms authentication, the cookie is encrypted by default. However, it's a framework-- you can customize it-- in fact you can set any cookie you want if you know your way around the APIs. But you'd have to go out of your way to make that happen.

What about that other poster?

As for the SO question "Forms authentication...Is it secure?". I don't agree with the answer. The correct answer is: you should never store the password, in the cookie or anywhere else, encrypted or in plain text. Passwords should be hashed, not stored.

Can I store the password in the cookie?

The way forms authentication is supposed to work, you don't need to store the password in it. The cookie is tamper-resistant, and if only your web site can create the cookie, and your web site only creates the cookie when the user has provided valid credentials, then the mere presence of the cookie is enough to infer that a proper password was presented at some point earlier. The cookie should however contain the user ID or some means of obtaining the user ID.

Why shouldn't I put all my user data in the cookie?

The main reason for not storing much in the cookie is that it consumes bandwidth for every single request, including requests for images, style sheets, and scripts. A cookie is added as a header to every single GET and POST that is passed up by the browser. Also, the decryption of the cookie takes up CPU each and every time, and this processing is not offloaded even if you terminate SSL at an earlier stage. So if you want to store a couple flags or strings in there, fine, but don't store any large data structures. If you need to store a lot of data that persists within the session, consider using session variables instead. Or if you are striving for a stateless web app, maybe store the session data in the database, and store a database identifier in the cookie.

If the cookie is encrypted, why do I need to be careful about putting sensitive data in it?

Because every now and then, vulnerabilites like this one crop up. If the data isn't needed on the client machine, it isn't needed in encrypted form either. And it's best if you keep that stuff only where it is absolutely needed.

If you choose to use session state

If the secrets are sensitive then you should only use in-proc session state. If you use SQL Server session state, your data can be easily decrypted. The alternative is to encrypt the credentials in session state and only decrypt them when you use them, which would be something of a chore and easily overlooked. You could also write a custom session state provider that overlays encryption over everything, but then you'd see a loss in performance, since session state retrieval is done with nearly every page request. So I'd go in-proc.

Also, be sure to follow Microsoft's guidance on securing session state.

If you want to be modern about it

If you're following the microservice and REST fads, you can do something like this:

  1. Build a RESTful microservice whose sole purpose is to store these credentials securely. The service should only be available on your web server's local subnet, not the internet, and should be secured using client certificates and IP white listing.

  2. Implement cache-control on both your REST client and REST server, and set the cache expiration fairly high, maybe 24 hours.

  3. When the web site needs a credential, call the microservice. If you honor the cache headers then your REST client should also cache the value, which will avoid calling the service repeatedly.

But if you really want to use a cookie

If the credentials you need to store are the user's own credentials, e.g. you are acting as a pass-through to the API for some Google app that they use, then I think you may be OK putting that stuff in the cookie. After all, the user probably has it on their own machine somewhere. AES-128 pretty much can't be brute forced, and you could use AES-256 just to prove you mean business, if you want.

If the credentials are something no regular citizen of the planet should have, e.g. the application password to a banking host, I wouldn't do it.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Great answer. It leads me to 2 follow up questions: 1. Why is the cookie encrypted in the first place by default, if ideally we shouldn't put any sensitive information there? 2. It seems like up to a certain size, storing in the cookie would be better. And after that size, it's better to store elsewhere like session. Of course this might be a matter of opinion, but roughly where would you say this threshold is in say kb? – user5928486 Jul 14 '17 at 14:00
  • So if I really need to store some sensitive information, you would recommend session over the encrypted cookie (assuming HTTPS)? Not as sensitive as a password, but still sensitive: some access tokens for an external API. I realize usually it's easy to get away without storing sensitive information, but for my specific case, I don't have much of a choice. – user5928486 Jul 14 '17 at 14:05
  • Thank you John Wu – user5928486 Jul 16 '17 at 05:37