Live data from Hacker News

How to build (and how not to build) a secure “remember me” feature

troyhunt.com

51–60 of 65 posts

Re: How to build (and how not to build) a secure “remember me” feature

#51
post #22

Remember me cookies are a specific case of some data sent to the client that the server would like to verify at a later point in time. The most direct way that comes to mind for solving this type of problem is to send the client just a random identifier and have the server look it up in a persistent store upon use. The other way of solving it is to have the server sign whatever data is sent to the client via an HMAC.…

This is where most cookie schemes wind up -- sending and retrieving HMACs.

I wrote my honours dissertation on an opt-in scheme that used cookies, HTTPS and javascript to track users visiting multiple websites.

What you have here is what I called "Protocol 1": the first elaboration of the naive protocol. An additional elaboration (Protocols 2 and 3) is to remove user identification from cookies entirely. Each cookie is regenerated on each HTTP request with a new ID and HMAC. This means that if a cookie is successfully harvested, its useful lifetime is limited.

There are more attacks after this. I got as far as Protocol 10; it transpires that Protocol 10 is broken anyhow. Depending on the sophistication of your attacker, there's no safe way to do what I was trying to do.

Re: How to build (and how not to build) a secure “remember me” feature

#52
post #44
post #8

Good article, but one thing is explained in a weird way: Don't bother with cookie expiration. That's the wrong approach, because the cookie is controlled by the user . Always do a server-side check whether or not the auth token in the cookie is allowed to continue the session. So you could simply set the expiration date for a cookie until 2030 but make sure that the auth token from that cookie cannot be used after $E…

I wouldn't go as far as "Don't bother with cookie expiration.", but you're certainly right in that you can't _rely_ on "the browser" to honor them (or even actually be a browser). I'd still recommend setting reasonable expirations, even if it's only to be seen to be doing the right thing. Far future expirations aren't useful (as you explain) and they only serve to make it look like you're "doing in wrong". (And, for…

Good point. Especially the "make it look like you're doing it wrong". You don't want to look like a data kraken in the eyes of customers.

Re: How to build (and how not to build) a secure “remember me” feature

#53
post #17

Can someone explain how the example of the JSON encoded cookie could be used for XSS?

It's really unclear, but I think it's a loose reference to an older hack that involves patching javascript's Array to steal data when parsing JSON. The references to 'old array' and 'new array' in the screenshot seem to be the tipoff. This is my best guess at least.

See http://flask.pocoo.org/docs/security/#json-security for info. Most modern browsers don't let you patch Array like this anymore.

Also, that's more a csrf issue so, I could be totally wrong.

Re: How to build (and how not to build) a secure “remember me” feature

#54

Regarding how long to keep the "remember me" cookie for, this is one of the overlooked reasons why native apps are eating the web's breakfast. When was the last time you have to re-authenticate on a native mobile app? Maybe it happens on some finance/banking apps, but I don't recall seeing it on apps like Facebook or Kindle for example. Web developers could, for example, add longer times if the user agent is mobile.…

Yup. Mozilla persona browser integration should already be here. Then, web apps can delegate auth to the browser much as native apps delegate to the operating system.

Re: How to build (and how not to build) a secure “remember me” feature

#55

Or you can do this: Client generates random value, puts it into cookie and passes it to server along with valid credentials. Server remebers it for this user and whenever at later time it sees this value in the cookie it logs in this user. Server forgets this value when this user logs out and after some time. If client does't have javascript or you don't trust randomness it can generate you can create this value on s…

What is the point of generating this value on the client? The second scenario you describe seems to work the same, minus the need to generate values on the client, with the same outcome.

I guess no point. Pick the one that you feel better with.

Re: How to build (and how not to build) a secure “remember me” feature

#56
post #35

Help! Most of this discussion I understand. One point is, it all involves lots of work with browser cookies stored on the user's computer. My approach so far is to send the user the character string version of a GUID (globally unique identifier, supposely unique in all space and time, on all computers or some such) in an HTML text box marked as "hidden" so that it doesn't show on the screen. Then I use that GUID valu…

You are a bit confused, but I'm not sure why you're being downvoted...

> GUID

GUIDs are really not the best idea, they can be (sort of) predicted - an attacker can guess which GUIDs are in use as session identifiers. Better to use a random string (generated by a cryptographic random number generator)

> without cookies

Browsers can store user's password when they request it. It is a security hole, consciously made by the user for added convenience. Also, only the user who made this decision can fall into this hole - it's his credentials that get stolen.

> mobile devices ... do not permit cookies

they do (although some might not store the cookies for as long as the expiration would require). However, they don't allow the user to store the password (as in the previous paragraph, the remember me function as you call it)

To round it up, it's a good thing you're experimenting with your own key/value store and session implementation, but it's usually better to use tested components in production (especially for the session stuff - it's very easy to get wrong). Anyway, keep experimenting, that's the best way to learn - I just hope somebody reviews your stuff before you shoot yourself in the foot :)

Re: How to build (and how not to build) a secure “remember me” feature

#57

Earlier quoted context omitted.

What is the point of generating this value on the client? The second scenario you describe seems to work the same, minus the need to generate values on the client, with the same outcome.

I guess no point. Pick the one that you feel better with.

Also the server should keep it hmac-ed in case db silently leaked.

Re: How to build (and how not to build) a secure “remember me” feature

#58
post #50

Earlier quoted context omitted.

I don't see why you have to store the hash of the token. You know the key you used for HMACing, why can't you just check that the cookie contains a valid hash of the rest of its data (which is as extensive as you need: session id, expiry, IP, whatever)? To prevent the use of old sessions just make the session id a counter. A single session counter per user is probably less hassle (and more useful) to store than the w…

To avoid the problem of storing the token's hash, you have introduced: * parsing a structured cookie, vs a meaningless 128-bit string * securely storing and managing a secret HMAC key (which may be used to forge or modify credentials) * securely verifying an HMAC using a constant-time string comparision So what, exactly, is the benefit of your proposal over mine? You've removed the (useful) distinction between an aut…

you have introduced: parsing a structured cookie, vs a meaningless 128-bit string

You're going to need some logic for dealing with session, user, etc. metadata. Stipulating that parsing metadata out of a cookie is in some sense harder than reading it from a DB, keeping it in the database requires more storage (in addition to the 128-bit hash), more syncing among the various masters and slaves, and higher security. (An attacker who gets a DB dump can't see account metadata that isn't stored in the DB. Sure I'm storing a counter but what can he do with that?)

securely storing and managing a secret HMAC key

How do you run an online service without doing key management? Whatever techniques you use for your other keys, use them for this key too. It isn't as if we need a separate key for each user.

You've removed the (useful) distinction between an authentication token and the user's session.

I don't understand this claim. If I want to generate a new token for the current session, what's stopping me?

And you've increased the attack surface for security vulnerabilities.

Because HMAC collisions are easy now? I've moved some things around, but I'd say there is a tradeoff between the CAP costs of the "store everything" technique you propose and the slightly more involved validation process I describe. It's cool if you prefer your method for your situation, but can't we admit that "I'm going to describe best practice" was a bit overstated?

Re: How to build (and how not to build) a secure “remember me” feature

#59
post #22

Remember me cookies are a specific case of some data sent to the client that the server would like to verify at a later point in time. The most direct way that comes to mind for solving this type of problem is to send the client just a random identifier and have the server look it up in a persistent store upon use. The other way of solving it is to have the server sign whatever data is sent to the client via an HMAC.…

This is where most cookie schemes wind up -- sending and retrieving HMACs. I wrote my honours dissertation on an opt-in scheme that used cookies, HTTPS and javascript to track users visiting multiple websites. What you have here is what I called "Protocol 1": the first elaboration of the naive protocol. An additional elaboration (Protocols 2 and 3) is to remove user identification from cookies entirely. Each cookie i…

This sounds interesting. Can you provide a link to this dissertation?

Re: How to build (and how not to build) a secure “remember me” feature

#60
post #56
post #35

Help! Most of this discussion I understand. One point is, it all involves lots of work with browser cookies stored on the user's computer. My approach so far is to send the user the character string version of a GUID (globally unique identifier, supposely unique in all space and time, on all computers or some such) in an HTML text box marked as "hidden" so that it doesn't show on the screen. Then I use that GUID valu…

You are a bit confused, but I'm not sure why you're being downvoted... > GUID GUIDs are really not the best idea, they can be (sort of) predicted - an attacker can guess which GUIDs are in use as session identifiers. Better to use a random string (generated by a cryptographic random number generator) > without cookies Browsers can store user's password when they request it. It is a security hole, consciously made by…

Thanks, I needed that!

I've done a lot of programming, some quite advanced, and likely for longer than 99% of the HN audience. But this is my first effort with a Web site, HTML, CSS, etc. So, I believe I can write good code and think through design issues well enough, but I am missing some information about mobile devices and browsers.

My little session state store code is working great. It was fast, fun, and easy to write, and it's been working flawlessly as I use it while developing more code.

My main alternative was to use what Microsoft's ASP.NET offered. First they offered storing session state in the same application (whatever that is, maybe just an address space). That alternative would give problems once my site is busy enough to need more than one Web server unless I had some front end box, maybe from Cisco, implement something like session affinity. The second alternative was using SQL Server. I'm trying to keep down the use of SQL Server, especially for something as light as a session state store where relational database, with ACID, etc. is gross overkill.

Thanks for the information on cookies: I don't want to assume or ask that a user's Web browser accept cookies.

When my site goes live, there will be no reason for users to have a user ID or password or log in -- later there will be. So, when I have some users log in, there is some question just how to handle that in a way both secure enough and also really easy for the users. If the user lets their Web browser store the user ID and password (not in a cookie) and a user wants to use that facility, so far fine with me -- that browser functionality is an industry standard and, thus, not to be too embarrassed about. Maybe I can get some actual documentation of that browser feature in pages for programmers at Web sites of the Web browsers -- Firefox, IE, Chrome, etc.

For using a GUID as a random key, I don't see what's wrong. I just ask for a new GUID whenever I need one. I use GUIDs for so many things inside my server code that no user can see a sequence of GUIDs from one of my servers. So, all a user could see would be just a few GUID values and should have one heck of a time guessing GUID values for other users. But, a well regarded generator of random strings would be easy to use also. I'm familiar with high quality random number generation, mostly would want assembler code for the arithmetic, don't want to try to write Intel x86 assembler to be called from Microsoft's Visual Basic .NET, would not want to use such a random number generator for session ID, and am not thrilled about writing my own random string generator. That's why for now I used GUIDs for session IDs. But I could ask ASP.NET to encrypt the GUIDs. Then a user could grab the encrypted string and maybe reuse it but would have to decrypt to see a GUID to guess the GUID sequence and extrapolate to a GUID of another connected user and then encrypt! Seems a bit much! Besides, they'd also have to guess the IP address of the other connected user and fake the IP/TCP/HTTP or whatever headers that report IP address. Maybe the NSA, some guys in a big basement in China, or some brilliant, bored wacko in Belarus wouldn't have anything better to do!

For what is stored in session state, I add to that right along as I write the rest of my Web pages. So I have a class, marked as

   
and add properties to it as I want something persistent during the user's logical session.

I read somewhere that Web browsers on smart phones don't support cookies. Good to learn that this is not correct.

Since cookies are now a privacy concern, I'm still reluctant to ask my users to have cookies enabled for my site. For persistence a session ID, I don't need a cookie and can use just a GUID (or a random string) in a hidden field. For persistence for user ID and password, my site doesn't use those yet!

Thanks for the answers!

Post reply on HN