Best Practices for "Remember Me"?

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Best Practices for "Remember Me"?

Post 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
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post 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.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post 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.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post 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. :)
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post 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. :)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post 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.
AGISB
Forum Contributor
Posts: 422
Joined: Fri Jul 09, 2004 1:23 am

Post 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.
Andrus
Forum Newbie
Posts: 7
Joined: Sun Jul 06, 2003 1:00 am

Post by Andrus »

would it be better to log the ip address in the remember me, so that they can login from that computer only?
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post 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.
Andrus
Forum Newbie
Posts: 7
Joined: Sun Jul 06, 2003 1:00 am

Post 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?
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

That still doesn't deal with the NAT problem.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post 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:
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post 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.
Swede78
Forum Contributor
Posts: 198
Joined: Wed Mar 12, 2003 12:52 pm
Location: IL

Post 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)
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

As unique and random as possible.
Post Reply