Forum Moderators: phranque

Message Too Old, No Replies

Best way to remember a returning visitor?

Is a long, randomly-generated cookie value good enough?

         

MichaelBluejay

2:52 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'd like my site to remember visitors when they return so they don't have to type in their password every time (like WebmasterWorld). Seems that I could set a cookie in the user's browser with a string of random characters, and store that in my mySQL user database in the user's record, and then when a user returns to the site if I can find their cookie value in the database then I can assume it's them.

But is this secure enough? I know people can edit their own cookies to try to access someone else's account. I doubt that would happen on my site since it's small and insignificant, and I'm not storing any personal or sensitive information like addresses or credit card numbers, but still, when I'm building something I like to try to do it "right", if it's not too much trouble.

I'm thinking that maybe the key is to make the cookie value really long to make it harder to find through trial and error. Originally I was thinking four characters, then ten, then twenty. Then I thought, why not just go up to the maximum size that it will hold (which I assume is 128 or 256 characters)? But then I wondered if this even helps if someone is using a computer to try gazillions of combinations per hour.

Thoughts appreciated.....

jdMorgan

3:14 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Use a coding system. For example, motor Vehicle Identification Numbers (VINs) encode the vehicle's type, maker, engine type, and other info. In addition, they contain a few digits that allow the number to be validated. For a simple example, all of the digits added together in a particular way, plus the check digits, equal some "secret number". Or each digit can be taken as the exponent of a secret key, and only numbers which result in a number than can be factored into the secret "answer" number are valid.

As far as random, that will result in multiple users getting the same cookie value, so you should base it on unique things, such as the time of the cookie generation (in clock ticks since Jan 1970 as provided by Unix), combined with the original IP address and maybe a hash of their browser name. It certainly won't take 128 characters to assign a unique cookie to every person on the planet for the next 100 years.

You can use parity, checksums, cyclic redundancy codes, Hamming codes -- all kinds of fast-to-compute numeric transforms -- to assign a non-random but unique and hard-to-counterfeit number.

Not my specialty, but a search on those terms may turn up some nice methods or algorithms you can use.

Jim

MichaelBluejay

3:31 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



As far as random, that will result in multiple users getting the same cookie value

Well of course I'm going to make sure the value I generate isn't in the database before storing it there!

Anyway, I have no lack of ideas for how to generate a unique ID for each user. The question is, how to make that resistant to hackers who try all the possible values?

gertrijs

4:11 am on Dec 17, 2004 (gmt 0)



The question is, how to make that resistant to hackers who try all the possible values?

At 128 bytes, all possible values will take an extremely long time. If you put an extra 0.1 seconds delay inside your server script that checks the database real users won't notice, but hackers need at least 1 second for 10 checks.

If you only use the characters A-Z for your string, you can have 26**128 unique variations. Assuming you put in the 0.1 second delay, it will take them around 4.1474573942897255639935267271564e+172 years to try all variations. Now, how long does earth exist?

Obviously, it all depends on the quality of your random character generator. If you use an extremely lousy implementation that always outputs the single character 'A'...

Gert

MichaelBluejay

5:30 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks gertrijs, that's exactly what I was looking for. The piece I was missing is that I should wait 0.1 seconds before actually processing the request, in order to slow down the automated attacks. It's obvious in hindsight, but for some reason I couldn't think of it on my own.

I will use all the upper- & lowercase letters plus the digits 0-9 for each character, in a string 20 characters long. It would take 2,233,712,029,258,618,953,971,793,920 to go through all those possibilities which is robust enough for my purposes.

Thanks again.

MichaelBluejay

5:42 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Er, how do I pause for 0.1 seconds in Perl? I hope I don't have to start a new thread over in the Perl forum....

gertrijs

6:00 am on Dec 17, 2004 (gmt 0)



A search for Sleep turned up this link:
www (dot) webclass.ru/eng/Tutorials/Perl/Short_Sleep.html

Perl's own Sleep function seems to allow whole seconds only.

But, do you actually need it? How long does the database check take?

An additional check you could implement is to store the referring IP of failed attempts inside a table (limited to a few 100 rows). Before somebody tries to login, check if it is logged in this table, and make them wait a full second (using Perl's Sleep function).

Gert

MichaelBluejay

7:05 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Thanks, this is all great. I think I'm set now.

john_k

7:15 am on Dec 17, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Another option is an MD5 hash based on the userid + your secret string. Someone trying to get in would have to guess both the userid and the MD5 hash value that goes with it.

The other part of this is that, unlike WebmasterWorld, but like some shopping sites, the cookies only get you part way in the door. Before the user can edit their profile, or even see any sensitive info, they have to enter their password. That would then fully validate them just for that session.