Best Practices for "Remember Me"?
Moderator: General Moderators
Best Practices for "Remember Me"?
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
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
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.
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.
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"?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".
"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.
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.- 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)
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.
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).- 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).
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.
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.)- Encrypt the cookie contents
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.- Limit it to that specific portion of the domain, not *.devnetwork.net
Just the heightened risk and lowered cost to the attacker.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"?
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).
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: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.
Agreed. Its a tradeoff choice, very binary.. either security, or convenience. Weigh the risks and benefits carefully.nielsene wrote: If the "remember me" window is short and doesn't auto-extend, you lose all advantages of the second case.
Technically, the right phrase would be "A usernumber CAN BE equally poor", as you go on to argue that point.nielsene wrote:Of course. However, a usernumber is equally poor.
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: Usernumbers are weak because they are extremely predictable
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 think I would also recommend not-encrypting the contents of the "normal" emphemeral tokens for preformance/lack of exposure window reasons.
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:I'm not sure I see the reason for the general proscription.
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.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.
But then again, I'm clearly paranoid about security.
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.
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.
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.
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.
- John Cartwright
- Site Admin
- Posts: 11470
- Joined: Tue Dec 23, 2003 2:10 am
- Location: Toronto
- Contact:
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 
- Ambush Commander
- DevNet Master
- Posts: 3698
- Joined: Mon Oct 25, 2004 9:29 pm
- Location: New Jersey, US
- John Cartwright
- Site Admin
- Posts: 11470
- Joined: Tue Dec 23, 2003 2:10 am
- Location: Toronto
- Contact: