GUID vs md5 hash for persistent cookie - security

I am researching how to implement a persistent "remember me" type cookie for a site. I was just wondering is using a GUID for a security token as secure an an md5 hash of username and password?

A GUID is more "secure", because there's no possibility of information disclosure in a random identifier. Otherwise, were the username to be known, the password could be extracted using a per-username rainbow table or a concerted attack since you did not add salt before hashing. NB: MD5 is a rather weak hash at this point.
Long story short, if you don't need to store private information in cookies for really really good reasons, don't. Use a random token instead.

Related

Identifying frauds while salting passwords

Im in the works of updating the login process of a site.
Currently, passwords are stored as md5(password), and i'd like to add a salt,
but the unsalted password is being used to identify possible frauds since they
usually uses the same password for new accounts.
20% of the traffic is from mobile devices, which don't necessarily have the same ip.
Any idea how to identify these possible frauds?
You can still add a salt, but you have to do the comparison to the existing passwords while you still have the plaintext password, i.e. you'll have to loop through the passwords table looking for duplicates (by hashing the other account's salt with the new password) at the time the account is created rather than afterwards.
I would say salting passwords is definitely a major benefit over keeping them unsalted for fraud prevention purposes. However, please use a cryptographically secure slow hashing algorithm, such as bcrypt, scrypt or pbkdf2 - not salted MD5.
But you could have your cake and eat it, why not have another table that contains previous passwords that have been used in fraud attempts? These would be hashed, but not salted and would not have any account association stored.
If a user that uses one of these passwords turns out to be non-fraudulent, you could give them a notification to change their password to something else after you have investigated.
Here's how I imagine it would work for adding new passwords to the fraudulent password list after an account is determined to be used for fraud.
Account is marked as fraudulent.
When this user next attempts to log in, and their hashed, salted password matches the hashed, salted value stored in their account record, the unsalted hashed password taken from their user input is stored in the fraudulent password list.
As the fraudulent password list could reduce the security of the accounts of upstanding users because they are stored in here unsalted, you should make "good" users change their passwords upon login if it matches any in the fraudulent password list.

Storing passwords in a database when hashing doesn't apply

There are a lot of questions on Stack Overflow about how to store user passwords, and the general advice of course is to hash the passwords and compare hashes.
However, imagine you are building a shrinkwrap intranet application (like SharePoint) that people deploy in their own environments. And suppose it requires a username/password combination to access an external service via HTTP (solutions that rely on API keys or federated security aren't supported).
In this case, we can't hash the password because we will need to pass the original password to the web service that we call. Encrypting would be the second best solution, but what would we use for the encryption key? If an attacked compromised the database, presumably they would have access to whatever key is used to encrypt the data in the first place?
If it was really a requirement for you to get the plain-text version of a stored password, how would you approach the problem in the most secure way?
This is actually a really interesting question. I'll join in.
You should encrypt it when storing it. No matter how you look at it it's better than storing it in plain text. Let's say an attacker finds an sql injection ad dumps the db, he still don't hold the encryption key. On the other hand, if he gets access to the server he will probably also find the encryption key.
To improve it a bit, you could store the encryption key in the server configuration. Assuming you are using Apache, you could use SetEnv.
I in my environment are required to enter the encryption key when Apache starts, this is then stored as en environment variable, so the key isn't really stored anywhere on my server.
There is no way, unless you require the user to enter a key to decrypt the password that you will be 100% safe.
You could generate the encryption key from the user's password. (Not their password for the external service—their password for your service.) Since you're not storing their password in plain text, an attacker who compromised your database wouldn't be able to decrypt the passwords. The downside is that you have to ask them for their password (for your service) whenever you need their external password.
You have the question inverted. The problem is not how to let the consumer "view" the password; the problem is how to let the consumer verify authentication.
In your implementation provide a means by which the consumer can provide a password and a username and get either a yes or a no. Then you continue to store encrypted (not hashed) passwords in the database.

Remember me Cookie best practice?

I read about many old questions about this argument, and I thought that the best practice is to set up a cookie with username,user_id and a random token.
Same cookie's data is stored in DB at cookie creation, and when users have the cookie they are compared (cookie data, DB data).
Sincerely I can't understand where is the security logic if this is the real best practice.
An attacker who steals the cookie has the same cookie than the original user :|
Forgotten some step? :P
You should NEVER EVER store a users password in a cookie, not even if it's hashed!!
Take a look at this blog post:
Improved Persistent Login Cookie Best Practice (Nov 2006; by bjaspan) (orignal)
Quote:
When the user successfully logs in with Remember Me checked, a login cookie is issued in addition to the standard session management cookie.[2]
The login cookie contains the user's username, a series identifier, and a token. The series and token are unguessable random numbers from a suitably large space. All three are stored together in a database table.
When a non-logged-in user visits the site and presents a login cookie, the username, series, and token are looked up in the database.
If the triplet is present, the user is considered authenticated. The used token is removed from the database. A new token is generated, stored in database with the username and the same series identifier, and a new login cookie containing all three is issued to the user.
If the username and series are present but the token does not match, a theft is assumed. The user receives a strongly worded warning and all of the user's remembered sessions are deleted.
If the username and series are not present, the login cookie is ignored.
You should store the user_id and issue a random token in addition to the user's password. Use the token in the cookie and change the token when the password changes. This way, if the user changes their password then the cookie will be invalidated.
This is important if the cookie has been hijacked. It will be invalidated if the user detects the hijacking, and furthermore because the token is unrelated to the password the hijacker won't be able to derive and then change the user's account password and "own" the account (assuming you require the existing password before changing passwords, the hijacker doesn't own the email account so they can't use "Forgot my password" etc).
Take care that the tokens aren't easily guessable (i.e. they should consist of entirely random data, like from a CRNG).
If you want to go one step further, you can encrypt the cookie before sending it and decrypt it upon receipt. And further to that, don't assume that a hijacker doesn't know the encryption key used, so validate the cookie's contents upon decryption.
But all that said, prefer to use a library's persistent session management instead of rolling your own.
I wouldn't even store the username in a cookie, just a random token generated with a near impossible to crack technique and map that to the user in your database, and never store user's password even hashed in a cookie, it will be open to Brute Force Attack. Yes if someone steal the token he can access user's account but the password will not be compromised and the token will be invalidated as soon as the real user logs out. Also remember that you shouldn't allow sensitive tasks like changing password to a user who just have a valid token, you need to ask for the password again for such tasks.
if your cookies are stolen anyone can log into your accounts. it's actually what firesheep does. the security lies in the random token. the whole system assumes cookies can't be stolen. the only other way to get in then is to guess the random token. if you make it long enough it should be nigh-impossible.
The "step" that you seem to be forgetting is that if the cookie value is properly hashed it would be of a little value to an attacker.
EDIT:
Here's a couple of things you can do to protect your users against cookie theft related attacks:
Regenerate tokens over time, so that an attacker would not be able to impersonate a user unless she has a recent enough cookie. If security is top priority, regenerate tokens on each request (page load). If it isn't, regenerate tokens on password change.
Keep and validate hashes of user agents, so that an attacker would not be able to impersonate a user unless she has both the cookie and the user agent that of the user.
p.s. Cookies should hold (random) tokens and not password hashes (see Hashes or tokens for "remember me" cookies?).
I always knew that the "remember me" feature only converted the session cookie (i.e. the cookie with the session ID) from expiring when closing the browser to a future date, it doesn't involve saving additional data, only extending the session.
And yes, if an attacker gets the cookie, it can impersonate the user. But this is always valid, and has nothing to do with "remember me".
My approach is the following:
Hash the user_id
Generate an unique key for the user - md5(current_timestamp)
Save the key to the DB
Encode everything so it looks like a BS - base64
Save it in the cookie
So far, It has been working great for me :)

Using AES to store passwords

So I need to be able to actually decrypt the password because some old websites don't use OAuth and I need to have some of my users have access to them through there API. Therefore one way hashing does not work for me. I have been told that the best way to store the passwords with AES and using the salted hash of the passwords as the key. How do I store all the keys and where do I store the salt? Basically how would I exactly implement this.
Thank You
If I understand you correctly you have the following situation. Users log in to your system with a username and password. Your system then needs to impersonate these users by logging into another system that you do not control using the user's username and password for that system which they have given to you.
If that is correct, then it might be reasonable to encrypt their credentials for the other websites using AES. In this case, I would not store the key used to encrypt those crendentials. The password that the user uses to access your system should be used as the key, and it should not be stored anywhere. In this way, you have a chance of protecting your users privacy (depending on the design of the rest of the system, of course).
Since you are encrypting rather than hashing, and the encryption key would be differnet for each user, salting is not necessary.
Also, I would encrypt the full credentials, not just the passwords. Your users are showing an incredible amount of trust by giving you their credentials in the first place, so I would do everything possible to justify that trust!
Your approach is essentially to use AES as a hash function but this will not allow you to decrypt the passwords (short of brute force or some yet-to-be-discovered vulnerability).
You might want to consider asymetric key encryption instead (e.g. RSA). You'll need to encrypt the passwords with the public key of each person you expect would need to decrypt it (which would include the user).

Storing password in tables and Digest authentication

The subject of how to store web site users passwords in tables has come up several times on SO and the general advice is to store a hash of the password, eventually an HMAC hash. This works fine for Basic authentication or for forms based authentication (really the same thing). My problem is that I must provide also Digest authentication, aimed at the automated tools connecting to my service. I've been looking at this problem and as I see it, the only hash I can store is the HA1 part of the Digest: the hash of username : realm : password. This way I can validated both Basic/forms and Digest.
My problem is that I don't see any benefit in doing so. Now indeed an attacker cannot use Basic or forms based authentication if he gets hold of my password table (since he only has the hashed value and he needs to send the clear password), but nothing prevents him from using Digest authentication and give a valid response to my service challenge: he simply starts from the pre-computed HA1 from the table and continues the crafting of the response from there (ie. the same thing I'd do to validate a user on the back-end).
Am I missing something? Does the addition of Digest requirement basically makes the storing of hashed passwords a no-op from security pov, an obfuscation at best?
The reason I am using pre-computed hashes is not protection against attacks, but to secure users privacy.
Attacker can indeed authenticate, but he cannot (easily) see password of my precious users and compromise other services they are using etc.

Resources