Page 1 of 2

Best Practices for "Remember Me"?

Posted: Tue May 24, 2005 12:25 pm
by nielsene
So I've put off implementing "Remember Me" functionality for a long time over security concerns.

I've been using an HMAC-SHA1 based authenticator for my regular session authentication: ie a cookie with the following payload: identifier+expTime+MAC(identifier+expTime). The identifier is not predictable from either username/email/password or registration order. Thus even if someone brute forced the secret key, its roughly equally hard to traget a paticular user for impersonation and unlikely to generate a random, but existing user. expTime is normally 15-30 minutes from last access.

I've played with an automatically rotating authenticator hashing key, that retains the past key to avoid expiring active sessions when the key changes.

All in all I'm pretty happy with this system.

However, now I'm thinking about how I would implement the "Remember Me" type feature. My concerns with the these features is that you can't rotate the signing key in any meaningful way without invalidating all existing tokens. In principle you can't ever rotate the key .... this is bad as you can't constrain the window of vulnerability. While outright brute-force recovery of the secret key from HMAC-SHA1 is extremely unlikely, I don't like the open ended problem.

I know a few systems that force the once a year log-in, probably for this reason.

I've been thinking about using a per-user authenticator key in the DB, so that brute forcing any paticular user doesn't allow maseradeing as another user. The per-user authenticator key can then be rotated any time the user changes thier password (an action that should invalidate all their existing tokens).

Does anyone know of any more developed "best practices" for the long-lived "remember me" authenticators -- most web discussion focuses on the shortly lived ephemeral session authenticators...

Thanks

Posted: Tue May 24, 2005 2:30 pm
by Roja
Congratulations on describing, in very clear terms, an exceptionally secure and well thought out security methodology. Very refreshing to see.

To answer your question, "Remember me" functionality is a bit of a black art. As far as best practices go, it all depends on the risk of the data.

For example, phpbb sets a remember me cookie that expires one year from the day of last login. My yahoo account sets one for something like 6 months. My ebay account is something like 3 months, and finally, my bank doesnt allow one at all.

"Remember me" functionality is a direct choice between convenience and security. It is absolutely a binary choice: If you offer it, you are reducing security to some substantial degree.

That said, there are things you can do to minimize the risks:

- Ensure that bad login attempts (yes, even with remember me cookies) are logged and reviewed often. Once a week is the bare minimum - I highly suggest "daily".
- Set a short window for the remember me functionality
- Force users to renew it with a new manual login with X weeks/months (dont auto-renew on each subsequent access of the site without a login like phpbb does)
- DO NOT STORE USERNAMES OR PASSWORDS IN THE COOKIE. Use identifiers that are hard to identify, like a usernumber (3098475230 is much harder to 'see' than Roja).
- Encrypt the cookie contents
- Limit it to that specific portion of the domain, not *.devnetwork.net

With all of those, you are reducing the convenience, but increasing the security.

Its a tradeoff either way.

Posted: Tue May 24, 2005 9:55 pm
by nielsene
Roja wrote: - Ensure that bad login attempts (yes, even with remember me cookies) are logged and reviewed often. Once a week is the bare minimum - I highly suggest "daily".
What is gained here, or rather are you suggesting anything different than the normal monitoring/logging/reportinng of failed attempts, ie something specific to implementations containing "remember me"?

"Normal" use of such logging handles such things as increasing time-delay between attempts (slow down brute force), block IP/IP ranges for fixed periods of time (similar), report to the user hack attempts (awareness), report to the admin (awarenesss), written record (criminal/civil legal action). In some cases its used for account locking as well. However account locking on internet systems tends to be more of a DOS hole ... increasing retry delays and/or ip blocking tends to block the bad guys while not hurting the user too much....

I'm not seeing how any of these activities are different under a member me functionality -- the authenticator is only issued after a successful normal login.
- Set a short window for the remember me functionality
- Force users to renew it with a new manual login with X weeks/months (dont auto-renew on each subsequent access of the site without a login like phpbb does)
Hmm, this is a prime place for the convience/security trade-off. I tend to few "remember me" funcationality as most useful in two "classes" of web applications: very high frequency (typically forums or web-games) where the user is normally one at least daily, if not more. On this time of site, people are likely to remember their password due to repetition, but the remember me is a nice convienence. The other class are those sites that a person might visit 1-2 times a month. For many people this is not often enough to memorize/retain their password (assuming its a strong, non-duplicated password). Thus using remember me avoids constantly sending "forgotten password" type emails. I've often felt such emails are the weakest part of the security system -- but their isn't a good solution apart from PKI type systems.

If the "remember me" window is short and doesn't auto-extend, you lose all advantages of the second case. The application I'm currently working on falls into the second case, for all but admin-class users. Thus I'm stuck with either having a long auto-login or no auto-login.
- DO NOT STORE USERNAMES OR PASSWORDS IN THE COOKIE. Use identifiers that are hard to identify, like a usernumber (3098475230 is much harder to 'see' than Roja).
Of course. However, a usernumber is equally poor. Especially in things like phpBB (I suspect you agree, just want to make sure some later thread viewer doesn't take your suggestion for usernumbers to heart).
Usernumbers are weak because they are extremely predictable, ie in many cases if you want to hijack the admin account, simply try usernumber 1 or 2 (possibly with some easy to determine large intenger offset). Many sites expose their user ids as well on their profile pages, thus usernumbers and names are interchangeable. I tend to recommend a hashed random value for use as the
identifier -- store it in the DB, not used as a key elsewhere, (but must be unique so you may have to loop to generate the value). This value is only exposed in the authenticator -- taken with only passing authenticators via SSL and your later point about encrypting the token does the best you can about avoiding "selective impersonation". Because its not used as a key elsewhere its also trivial to revokie/reissue, even in poorly designed schemas.
- Encrypt the cookie contents
Agreed. I need to think though a few other ramifications, but I think I would also recommend not-encrypting the contents of the "normal" emphemeral tokens for preformance/lack of exposure window reasons. The empheral tokens should still be sent via SSL only to protect from eavesdroppers and must not use the same hashed random identifier. (You don't want a XSS cookie collector getting a collection of the long term tokens and then using the plaintext from his person emphemeral token to launch attacks on the hijacked users.)
- Limit it to that specific portion of the domain, not *.devnetwork.net
I'm not sure I see the reason for the general proscription. I would agree in the case I'm currently working on as I have a beta. and a www. subdomain pair that require different logins. However in general, you often do want the remember me to cross sub domains -- as long as the SSL only flag is set you are aren't exposing the cookie in cleartext on non-ssl protected subdomains, I think you're ok.

Posted: Tue May 24, 2005 10:42 pm
by Roja
nielsene wrote: What is gained here, or rather are you suggesting anything different than the normal monitoring/logging/reportinng of failed attempts, ie something specific to implementations containing "remember me"?
Just the heightened risk and lowered cost to the attacker.

In a "well designed" (like what you described) login system, you'll be lowering security by adding the remember me functionality.

Lets take an example. With the system you described, you've made most normal logins fairly secure. That makes the remember me cookie the "weakest link". It can be attacked more easily, brute force has a smaller range, and it wont lock out the user. That makes it a very attractive alternative for an attacker to the fairly secure normal login sequence.

Since the cost for the attacker is lower, the need for monitoring is higher - there is more likelihood of a bruteforce attempt, which you need to be aware of as soon as possible (once it begins).
nielsene wrote:I'm not seeing how any of these activities are different under a member me functionality -- the authenticator is only issued after a successful normal login.
Because the remember me token could be brute force attempted, sniffed, or any number of other scenarios - all of which lower the cost for the attacker, and thus increase the need for better monitoring and awareness.
nielsene wrote: If the "remember me" window is short and doesn't auto-extend, you lose all advantages of the second case.
Agreed. Its a tradeoff choice, very binary.. either security, or convenience. Weigh the risks and benefits carefully. :)
nielsene wrote:Of course. However, a usernumber is equally poor.
Technically, the right phrase would be "A usernumber CAN BE equally poor", as you go on to argue that point.
nielsene wrote: Usernumbers are weak because they are extremely predictable
As implemented in some/most applications. Your described security is FAR beyond "the typical web application", so I thought it was a fair stretch to think that you'd have usernumbers that weren't (transparent, visible, predictable, 1:1 tied to usernames, etc). The rest of your comments on this item just described how you'd implement exactly what I figured you would, based on the original post. ie, we agree.

nielsene wrote:I think I would also recommend not-encrypting the contents of the "normal" emphemeral tokens for preformance/lack of exposure window reasons.
Performance of encryption on the small values that will be stored in a cookie (limited to 4k by convention, generally) is really trivial. The exposure argument isn't bad, but isn't enough to sway me. If you are already encrypting part of it, there is no significant cost in encrypting everything in the cookie. Might as well - it'll make the attackers job more difficult, and thats never a bad thing.
nielsene wrote:I'm not sure I see the reason for the general proscription.
Reduction of impact. If that cookie only works on forums.example.com , and not on game.example.com, and an attacker gets access to that cookie, we only have to limit the damage he did in one area - forums. Even better, if he wanted access to game.example.com, he'd have to hunt for cookies for that - and arguably, there would be fewer users in game v. forums.. making a smaller target for the attacker.
nielsene wrote:However in general, you often do want the remember me to cross sub domains -- as long as the SSL only flag is set you are aren't exposing the cookie in cleartext on non-ssl protected subdomains, I think you're ok.
I wouldn't say you are okay, but I would agree that there is a value to the convenience that may/does outweigh the security needs in some situations.

But then again, I'm clearly paranoid about security. :)

Posted: Wed May 25, 2005 12:16 pm
by nielsene
Roja wrote: But then again, I'm clearly paranoid about security. :)
I'm glad to hear that someone took over that role after I stopped hanging out here all the time. :)

Posted: Wed May 25, 2005 5:27 pm
by McGruff
Hi nielsene - long time no see.

I'd personally be pretty relaxed about the risk of brute-forcing a private key (as long as it's a "strong" key which isn't vulnerable to dictionary attacks). When you consider other potential vulnerabilities like cookie theft, it doesn't look like the weakest link in the chain. Careful protection against cross site scripting in the rest of site would also be vital.

In case anyone else reading the thread is interested, here's a class which creates and checks signed messages:

----
edit: moved to code snippets.

Posted: Sat Jun 04, 2005 1:33 pm
by AGISB
I think there is a middle way between remember me and security.

In a normal secured area there are certain parts that need to be more secure than others.

I inplement a remember function for the less important parts like memos and the daily stuff. If someone wants to view things like bank info or other important info I would reauthenticate once per session. Changing any data will always require using the password.


The main thing mostly overlooked is an important one. Most attacks aren't issued by an intruder form outside but come from the inside. Highjacking a cookie is really rare but finding the password at the top drawer of you collegue is much more frequent. A very tight security will have the user write the password down somewhere and people can easily find it. To low security might open brute force attemps. I think this is a problem that can never be solved.

Posted: Sun Jun 05, 2005 11:41 pm
by Andrus
would it be better to log the ip address in the remember me, so that they can login from that computer only?

Posted: Mon Jun 06, 2005 12:19 am
by McGruff
IP checks can only work in certain situations ie if the user has a static IP. Many don't. Some might not even have the same IP throughout a session. Also, machines behind a NAT all present the same IP to the internet.

Posted: Mon Jun 06, 2005 12:31 am
by Andrus
if it was used in conjunction with cookies, say the site remembers who is remembered and their ip address, if it isnt their ip but they are remembered, re-authenticate?

Posted: Mon Jun 06, 2005 3:23 pm
by McGruff
That still doesn't deal with the NAT problem.

Posted: Mon Jun 06, 2005 3:27 pm
by John Cartwright
In mine, if the ip doesnt match the ip they used to remember them, and along with a unique 32 char string in the db that matches the cookie (which is regenerated every time they visit the site) I don't allow them to be remembered. Too bad, So Sad is the attititude I have for people who complain about it :wink:

Posted: Fri Jun 10, 2005 11:57 am
by Ambush Commander
See, I think that's a pretty draconic approach. I salt the password, and then rotate salts every month so they must re-validate when a new month rolls around. Other than that, if they have a valid cookie, they're logged in.

Posted: Wed Jun 15, 2005 11:15 am
by Swede78
Which is a better way to store the identifier data in a "Remember Me" cookie, and why?

A) identifier+expTime+MAC(identifier+expTime)
B) 2-Way encryption(identifier)

Posted: Wed Jun 15, 2005 3:49 pm
by John Cartwright
As unique and random as possible.