I am debating using user-names as a means to salt passwords, instead of storing a random string along with the names. My justification is that the purpose of the salt is to prevent rainbow tables, so what makes this realistically less secure than another set of data in there?
For example,
hash( md5(johnny_381#example.com), p4ss\/\/0rD)
vs
hash( md5(some_UUID_value), p4ss\/\/0rD)
Is there a real reason I couldn't just stick with the user name and simplify things? The only thing my web searching resulted was debates as to how a salt should be like a password, but ended without any reasoning behind it, where I'm under the impression this is just to prevent something like a cain-and-able cracker to run against it without being in the range of a million years. Thinking about processing limitations of reality, I don't believe this is a big deal if people know the hash, they still don't know the password, and they've moved into the super-computer range to brute force each individual hash.
Could someone please enlighten me here?
You'll run into problems, when the username changes (if it can be changed). There's no way you can update the hashed password, because you don't store the unsalted, unhashed password.
I don't see a problem with utilizing the username as the salt value.
A more secure way of storing passwords involves using a different salt value for each record anyway.
If you look at the aspnet_Membership table of the asp.net membership provider you'll see that they have stored the password, passwordsalt, and username fields in pretty much the same record. So, from that perspective, there's no security difference in just using the username for the salt value.
Note that some systems use a single salt value for all of the passwords, and store that in a config file. The only difference in security here is that if they gained access to a single salt value, then they can more easily build a rainbow table to crack all of the passwords at once...
But then again, if they have access to the encrypted form of the passwords, then they probably would have access to the salt value stored in the user table right along with it... Which might mean that they would have a slightly harder time of figuring out the password values.
However, at the end of the day I believe nearly all applications fail on the encryption front because they only encrypt what is ostensibly one of the least important pieces of data: the password. What should really be encrypted is nearly everything else.
After all, if I have access to your database, why would I care if the password is encrypted? I already have access to the important things...
There are obviously other considerations at play, but at the end of the day I wouldn't sweat this one too much as it's a minor issue compared others.
If you use the username as password and there are many instances of your application, people may create rainbow tables for specific users like "admin" or "system" like it is the case with Oracle databases or with a whole list of common names like they did for WPA (CowPatty)
You better take a really random salt, it is not that difficult and it will not come back haunting you.
This method was deemed secure enough for the working group that created HTTP digest authentication which operates with a hash of the string "username:realm:password".
I think you would be fine seeing as this decision is secret. If someone steals your database and source code to see how you actually implemented your hashing, well what are they logging in to access at that point? The website that displays the data in the database that they've already stolen?
In this case a salt buys your user a couple of security benefits. First, if the thief has precomputed values (rainbow tables) they would have to recompute them for every single user in order to do their attack; if the thief is after a single user's password this isn't a big win.
Second, the hashes for all users will always be different even if they share the same password, so the thief wouldn't get any hash collisions for free (crack one user get 300 passwords).
These two benefits help protect your users that may use the same password at multiple sites even if the thief happens to acquire the databases of other sites.
So while a salt for password hashing is best kept secret (which in your case the exact data used for the salt would be) it does still provide benefits even if it is compromised.
Random salting prevents comparison of two independently-computed password hashes for the same username. Without it, it would be possible to test whether a person's password on one machine matched the one on another, or whether a password matched one that was used in the past, etc., without having to have the actual password. It would also greatly facilitate searching for criteria like the above even when the password is available (since one could search for the computed hash, rather than computing the hash separately for each old password hash value).
As to whether such prevention is a good thing or a bad thing, who knows.
I know this is an old question but for anyone searching for a solution based on this question.
If you use a derived salt (as opposed to random salt), the salt source should be strengthened by using a key derivation function like PBKDF2.
Thus if your username is "theunhandledexception" pass that through PBKDF2 for x iterations to generate a 32 bit (or whatever length salt you need) value.
Make x pseudo random (as opposed to even numbers like 1,000) and pass in a static site specific salt to the PBKDF2 and you make it highly improbable that your username salt will match any other site's username salt.
Related
I have a database that stores hashed passwords using a "private salt". However I am afraid that at some point the attacker will somehow know my private salt (for example a developer that leaves the company) and then will be able to do something malicious.
The current logic works like follows
function newUser(email, password) {
// hash is a non-reversible function
hashedPassword = hash(password, privateSalt);
databaseStore(email, hashedPassword);
}
function login(email, password) {
hashedPassword = databaseFetch(email);
if (password == hashedPassword) {
loginSuccess();
}
}
Now if I change the privateSalt, all the previously created users will fail with login. Is there a good or standard way to handle this type of situation, so that privateSalt can be changed and previous users can still login?
The solution what you are looking for is a password hash, also known as a PBKDF, a password based key derivation function. For this function there are a few algorithms available: PBKDF2, scrypt and Argon2. PBKDF2 is a NIST improved version, scrypt requires attackers to use a lot of memory, and Argon2 is a more modern version of a password hash.
The current scheme has the following issues:
salts should be random, what you have is essentially a so-called pepper, this means that identical passwords can be found immediately, and if the pepper leaks, then you can perform an attack using a dictionary attack using rainbow tables;
passwords are generally easy to guess, so you need some kind of work factor for each password, which is currently not included.
Now you already have a hash function, probably without a work factor or number of iterations in your DB, so you cannot just perform such a function on your existing database.
I see two (non exclusive) options:
Indicate to your users that they should update their password: verify their old password and use a known-good & correctly parameterized password hash on the new password. Create a transaction to switch one scheme to the new one. I'd use a different column for the new password, and make sure that you can update to a new algorithm or work factor in the future. You want to be able to reliably detect any update/upgrade.
You update the hashed password right now by applying a known-good & correctly parameterized password hash on the already hashed password*, hashedPassword. That way your current users get better protection right away.
The disadvantage of (2) is that the old DB may be found, in which case your users are screwed, so I'd only combine this strategy with (1).
Note that password storage part should only be part of the solution. You want to indicate the strength of the chosen password to users. Preferably you want to keep the option of longer passphrases open (horse staple, XKCD), but still allow shorter more complex ones (as generated by password generators).
I am working on an asp.net application where one of the security requirements is that the application must enfore "password history" - (remember previous 8 passwords).
I would like to know if someone has an experience designing a table (using SQL 2008) for this purpose. So far, I am thinking of just having one table, and one field per previous password and one field for the date of the password.
Any other suggestions / best practices?
I would create a password history table just for storing the old passwords, salted and hashed of course. This is a classic one to many relationship, having 8 fields for 8 different old passwords seems brittle.
You can store the date of each historical password with it in the password history table for aging out when they have changed the password more than 8 times.
Your suggestion sounds fine, but I would recommend storing salted hashes of the password instead. You'd either need to keep the salt constant per user and store it on the user table, or store it with the previous password entry if you want to refresh the salt each time the password is changed. The first option makes for the simplest database query to check previous passwords - the latter you'll have to do each comparison individually.
Remember to implement a rate limit on the password changes. My experience suggest that users will find out if there is none and will change password 9 times in a row to end up with the old one if you leave that chance...
Other best practices really depend on how secure you want the system to be. One thing I've seen doing, for instance, is trying a 10 seconds bruteforcing using the new password as a seed (for existing tools) or with basic iteration. i.e. if you see a password in the form of foobar5, try to see if foobar1/2/3/4 match any of the old hashes.
I was hoping someone could help me sort something out. I've been working on a shopping cart plugin for WordPress for quite a while now. I started coding it at the end of 2008 (and it's been one of those "work on it when I have time" projects, so the going is very slow, obviously!) and got pretty far with it. Even had a few testers take me up on it and give me feedback. (Please note that this plugin is also meant to be a fee download - I have no intention of making it a premium plugin.)
Anyway, in 2010, when all the PCI/DSS stuff became standard, I shelved it, because the plugin was meant to retain certain information in the database, and I was not 100% sure what qualified as "sensitive data," and I didn't want to put anything out there that might compromise anyone, and possibly come back on me.
Over the last few weeks, some colleagues and I have been having a discussion about PCI/DSS compliance, and it's sparked a re-interest in finally finishing this plugin. I'm going to remove the storage of credit card numbers and any data of that nature, but I do like the idea of storing the names and shipping addresses of people who voluntarily might want to create an account with the site that might use this plugin so if they shop there again, that kind of info is retained. Keep in mind, the data stored would be public information - the kind of thing you'd find in a phone book, or a peek in the record room of a courthouse. So nothing like storing SS#'s, medical histories or credit card numbers. Just stuff that would maybe let someone see past purchases, and retain some info to make a future checkout process a bit easier.
One of my colleagues suggested I still do something to enhance security a bit, since the name and shipping address would likely be passed to whatever payment gateway the site owner would choose to use. They suggested I use "one-way encryption." Now, I'm not a huge security freak, but I'm pretty sure this involves (one aspect anyway) stuff like MD5 hashes with salts, or the like. So this confuses me, because I wouldn't have the slightest idea of where to look to see how to use that kind of thing with my code, and/or if it will work when passing that kind of data to PayPal or Google Checkout, or Mal's, or what have you.
So I suppose this isn't an "I need code examples" kind of question, but more of a "please enlighten me, because I'm sort of a dunce" kind of question. (which, I'm sure, makes people feel much better about the fact that I'm writing a shopping cart plugin LOL)
One way encryption is used to store information in the database that you don't need back out of the database again in its unencrypted stage (hence the one-way moniker). It could, in a more general sense, be used to demonstrate that two different people (or systems) are in possession of the same piece of data. Git, for instance, uses hashes to check if files (and indeed entire directory structures) are identical.
Generally in an ecomm contect hashes are used for passwords (and sometimes credit cards) because as the site owner, you don't need to retain the actual password, you just need a function to be able to determine if the password currently being sent by the user is the same as the one previously provided. So in order to authenticate a user you would pass the password provided through the encryption algorithm (MD5, SHA, etc) in order to get a 'hash'. If the hash matches the hash previously generated and stored in the database, you know the password is the same.
WordPress uses salted hashes to store it's passwords. If you open up your wp_users table in the database you'll see the hashes.
Upside to this system is that if someone steals your database, they don't get the original passwords, just the hash values which the thief can't then use to log in to your users' Facebook, banking, etc sites (if your user has used the same password). Actually, they can't even use the hashes to log in to the site they were stolen from as hashing a hash produces a different hash.
The salt provides a measure of protection against dictionary attacks on the hash. There are databases available of mappings between common passwords and hash values where the hash values have been generated by regularly used one way hash functions. If, when generating the hash, you tack a salt value on to the end of your password string (eg my password becomes abc123salt), you can still do the comparison against the hash value you've previously generated and stored if you use the same salt value each time.
You wouldn't one way hash something like an address or phone number (or something along those lines) if you need to use it in the future again in its raw form, say to for instance pre-populate a checkout field for a logged in user.
Best practices would also involve just not storing data that you don't need again in the future, if you don't need the phone number in the future, don't store it. If you store the response transaction number from the payment gateway, you can use this for fraud investigations and leave the storage of all of the other data up to the gateway.
I'll leave it to others to discuss the relative merits of MD5 vs. SHA vs ??? hashing systems. Note, there's functions built in to PHP to do the hashing.
I use asp.net forms authentication to handle hashing/salting to and from plaintext passwords to the DB. This project was set up to use SHA-1 hash as the algorithm, but I am thinking about switching to something like BCrypt or PBKDF2 and was wondering how people usually make a transition like this.
Somehow I have to deal with the current passwords in the db hashed with SHA-1 and then new passwords will be hashed by something else. I could store a bit in the DB that lets me know which one it is, and then force a pw reset on everybody, but I don't know how easy this would be to do since I can't modify the forms authentication authentication code that does this for me. Also, the encrypted password field in the db may be two different column types for the two different hashes (may need a bigger column for new algorithm).
You could first hash with the new algorithm and test to see if that matches. If it does not match then you could hash with the old algorithm and see if that matches. If it does then overwrite with the hashed value from the new algorithm that you computed first. This way you can gradually shift everyone to the new algorithm behind the scenes when they log in.
Also, if you are really worried that storing the older hash values is insecure, you could double-hash them with the new algorithm. So your second check would compute the hash with the old algorithm and then hash that result with the new algorithm before checking for a match.
I am always looking for ways to secure my user's passwords. I am currently using some combination of hashing algorithm with random salt.
The main thing in this problem is when my user set a very very weak password. No matter how hard my mixed-up hashing algorithm, and how long my salt is, I think it can be cracked in less than 1 year.
I've been thinking for a new way. I've made a script that will re-encrypt the password every time the user sign-out by adding a random salt on the old hashed password, then encrypt it again. So, every time the user come back, the encrypted password is different. Get it?
But the main problem on this idea is, I must store the new salt every time the user sign-out. Imagine my code will look like, if the user is sign-in and sign-out everyday?
Any idea?
Oh, I have an idea. How about regenerate new encrypted password every year?
Re-encryption doesn't help with your problem.
The only thing you can do is create a multi part hash, and hope the attacker doesn't get all of them. I usually use a two part salt:
One part is a random per user value stored in the database alongside the password.
The other part is a per application salt. You can store it in the application config or in a special password store the OS offers.
The advantage of that split is that it's not enough if the attacker just gains access to the database, but he needs to get access to wherever your application salt is stored. So for example a simple sql injection stealing your database isn't enough. If the attacker can execute code it probably won't help at all.
And you should use some method to slow down hashing. Typical hash functions are fast, so brute-force is fast too. But if you iterate the hash-function a million times it still doesn't slow down a valid login much, but slows down brute-force a lot.
You can achieve that using a Password Based Key Derivation Function such as PBKDF2.
You could use "key stretching": iterate the hash, say, a million times, after salting.
Then store hash value, salt, and iteration count.
Then an attacker could check a million times fewer passwords per second than when you hash once. But a very short password will still fall: note that you yourself, to verify the legitimate password, need to do the same operation. Suppose you accept a 1 second time for yourself to check, then the attacker can also check passwords at 1 second per password, on a similar machine (and more if he used more or faster machines!). And 1 second per password can still be enough to check for weak and short password, standard dictionaries etc. There really is no defending against it, only making it harder.
There are two problems with your main assumptions. The first one is about the problem of storing the salt. You already do for the salted password solution. With your new approach, salt would change over time, and that's it. So you could have used this method and the only extra cost would be the re-calculation of the hash value at every login (when you actually have the password string itself).
The second problem is the more important one: a re-hashing will not change anything. As soon as your attacker gets hold of one salted hash value, it will be enough to mount a dictionary attack. The fact that you change your salts and the hash in your database will not make it any more difficult. So there is no need to recalculate a hash after the first one is created.