views:

324

answers:

5

Hey everyone,

Further to my question here, I have another question regarding salts.

When someone says "use a random salt" to pre/append to a password, does this mean:

  • Creating a static a 1 time randomly generated string of characters, or
  • Creating a string of characters that changes at random every time a password is created?

If the salt is random for every user and stored along with the hashed password, how is the original salt ever retrieved back for verification?

Thanks!

+4  A: 

The salt has to be stored with the hash for verification to be possible. Best practice would be to use a different salt each time a password is created or changed.

David M
Alright so if I create a random hash unique to the instance of creating MY password, and my password, how can I get the original salt value back in order to check the salt and the password together when I login?
barfoon
You store the salt alongside the hash, as David M said.
TRiG
@TRiG so then when the attacker obtains the hash he will also have the salt and then just break it with John the Ripper. This is not good advice.
Rook
@The Rook - the point of the salt is that a different dictionary attack needs to be mounted against each password, and pre-calculated attacks can't be used. It is the right advice.
David M
@David M No, I could not disagree more. Not providing the salt to the attacker is **far more secure**. You should actually try and break a password hash before talking about it. With John the Ripper you can give it 3 parameters, a dictionary, the salt and the password hash. If the attacker doesn't have the salt, then he can't break the hash.
Rook
@The Rook - nobody is suggesting providing an attacker with the salt **or** the hash. The point is, you can't verify a password against the hash without knowing the salt either, so you have to store both the hash and the salt.
David M
Ultimately, if your back end system can be compromised, **any** system where password hashes are stored is susceptible to a dictionary attack of some kind. This is why password security is only part of a system's security design, and it is also why strong passwords should be encouraged if not enforced.
David M
@David M you should read Rich's new answer its very good. There are also a ton of comments that I would just duplicate here, but I'll spare you.
Rook
@The Rook - I've read them all, don't worry. To be honest, I take issue with your harping on about SQL injection attacks - not every system is susceptible to these. And if your database isn't going to be compromised by a SQL injection attack, then your passwords only become vulnerable if the local system is compromised, in which case the password stored in a file is also compromised. So if you have paid attention to all the aspects of the secure design of your system, I can't see that your proposal there gives anything other than the illusion of more security. Sorry.
David M
@David M that is not a defense in depth approach, please avoid building security systems because the whole point of them is to plan on failure. Passwords are hashed to delay the attacker after a compromise.
Rook
@The Rook - I would have probably found it slightly more satisfactory if you'd attempted to answer my point rather than offering me unwanted career advice. Hey ho. Look, we are both arguing for not getting complacent in security design - I am however advocating making sure that any extra measures you take have been thought through and do actually offer extra security. If I am worried about the system where password hashes are stored being compromised, I'd find a strong password policy far more reassuring than what you are proposing. (TBC)
David M
Your solution adds extra security in the eventuality that there is a DB compromise, but not in the event of a complete system compromise. That's all I'm saying.
David M
@David M Oah sorry I gave up on you after you said you rejected Rich's answer. I don't mean to be a dick but you can't just talk about security you actually have to get your hands dirty and test your hypothesis. (Download jtr and break a hash, then tell me i'm wrong ;)
Rook
@The Rook - JTR doesn't "break hashes", it mounts dictionary attacks against them. Very different thing. I "get my hands dirty" in security matters frequently. And whether or not JTR can find a password doesn't change the point I'm making. Let's leave this - it's clearly going nowhere.
David M
@David M, You need to write exploit code like me http://milw0rm.com/author/677 and then maybe you'll see what i see.
Rook
@David M So have you kept up with Rich Adams's tread, it has taken an interesting twist.
Rook
A: 

Dynamically changing the salt is a lot more secure than having a one off static salt.

Also make the salts unique per user and not one global salt. Change them every time a user logs in for example.

Concatanating the salt to the end of the password then hashing it is OK, but is an easily guessable formula. Best come up with your own one, i.e. weave the salt and password to create a new string then hash, as md5(password + salt) is vulnerable to dictionary attack still.

Tom Gullen
md5(password + salt) as a dictionary attack only works when the attacker knows the salt. If your password database (that lists all the salt+hash combos for every user) is compromised you probably have much bigger problems to worry about.In other words, salt+password or password+salt is perfectly acceptable best practices.
Dan McDougall
'weaving your own' is security trough obscurity. The security is provided by the hashing algorithm, if they know the input pattern, they still do not know anything of value.
Jacco
-1 md5 is insecure.
Rook
Your solution is security though obscurity. Read Rich's answer its a good one.
Rook
+5  A: 

The second alternative is the correct one.

Traditionally, the salt is stored alongside with the hashed password, but non encrypted (typically preappended, for example in unix passwords)

Update: the method used in most newer Unix system is this one.

leonbloy
I think thats the old method for UNIX password storage i'm pretty sure DES is no longer used.
Rook
yes, that's the old method and syntax
leonbloy
+17  A: 

A new salt should be randomly generated for each user and each time they change their password as a minimum. Don't just rely on a site wide salt for example, as that defeats the point of using a salt in the first place.

Using a unique salt for each user is so that if two users have the same password they won't get the same resultant hash. It also means a brute force attack would need to be mounted against each user individually rather then being able to pre-compute a rainbow table for the site.

You then store the result of hashing the salt and password in the database hash(salt + password), along with the salt for each user. You can store these in separate columns, or all in one column (separated by some character not used in the hashes, so ; for example). As long as you can retrieve both you'll be fine.

However, if your database is compromised, either due to someone gaining local access or via SQL injection attacks, then both the salt and final hash will be available, which means a brute force attack on the users' passwords would be trivial. To combat this, as suggested by The Rook you can also use a sitewide secret key stored in a file locally as another input of your hashing method so that an attacker would also need to know this to mount an effective attack. Which means your DB would have to be compromised AND the attacker would need access to local files. So using hash(hash(salt + secret) + password), etc.

When the user enters their password you can retrieve the salt from the DB and the sitewide secret from a local file and validate that the resulting hash matches what you have stored.

If the user changes their password, then you should generate a new salt.

The hashing method you use doesn't matter (but the hashing algorithm does*). Above I suggested hash(hash(salt + secret) + password) but equally it could be hash(hash(salt) + hash(secret) + hash(password)). The method you use doesn't change the effectiveness of your password storage, one is not really any more secure than the other. Relying on the design of how you hash the password and salt together to provide security is called security through obscurity and should be avoided.

*You should not use MD5 or SHA-1 as these are considered insecure. Use the SHA-2 family instead (SHA256, SHA512, etc). (Ref)

Rich Adams
Makes sense. So you'd do something like a SELECT salt where user = user, then check if password = hash(salt+password supplied).Correct?
barfoon
Yes, that's right.
Rich Adams
most common pattern is to store the salt and hash together in 1 column. sub that would be `'salt'.hash('salt'.'password')` your salt has a fixed length (and so has your hashed result), so you can easily lookup the salt.
Jacco
Yup, there's no requirement to store them in separate columns, as long as both the salt and the final hash are available to you in some way for each user, then it will all work fine. Storing it like "sha256:salt:finalhash" in one column seems to be a popular choice.
Rich Adams
So when storing it in one column, Id have to know where the salt originates from and some starting piece of information (like their username or something), correct?
barfoon
It's up to you, you could use the fixed length nature of the salt to know that the first 20 chars are the salt, and chars 20-40 are the final hash for example (or however many chars you make your salt/hash). Or you could use a character like ";" to separate them and just split the string on the ";" character to get the separate values, etc.
Rich Adams
`usertable('userId', 'username', 'passwdHash', 'email');`
Jacco
I would recommend NOT using a fixed length salt. The reason is for future changes. If you use a delimiter, you can detect "old hashes" vs "new hashes" by some identifying factor (say you change the delimiter, etc). So you can store `$salt.':'.$hash.':'.$hashFunc` to get `abc:def:sha1`. That way, if later on you ever decide to switch to a longer salt, or change the hash function, you can detect the legacy passwords and "upgrade them" on the fly...
ircmaxell
Yup, I agree with ircmaxell, if you're going to store all in one field it makes more sense to use a separator rather than fixed length in order to future proof it. Also, one additional point, you should use the SHA-2 family of hashes or stronger. MD5 and SHA-1 should be avoided (http://www.networkworld.com/news/2005/110105-nist-crypto.html).
Rich Adams
-1 This purposed password storage system is trivial to break with sql injeciton and John The Ripper.
Rook
Uh, how? User input will never hit the DB unhashed so I don't see the injection attack here. Or did you mean that if you find some other hypothetical injection attack you can read the password hash column and then decrypt the passwords? Aren't there better things you could do with that SQL injection? What password storage scheme would you propose instead?
Rup
@Rup to start off a message digest is not an encryption function and there for cannot be "decrypted". In terms of "better things to do", that depends on if your data is mis-configured. But the point is building a password storage system, so lets focus on that. A hash cannot be broken until its salt is retrieved, once the attacker has the salt and the hash then plain text can be brute forced using a dictionary or iterative guessing (John the Ripper). Password hashes are obtained from the database using sql injection and you are not taking this into consideration.
Rook
Let me be perfectly clear this is easy to break and the 9 people that voted this up should not be building security systems.
Rook
@The Rook: You're assuming the site is susceptible to SQL injection which is a completely separate issue. If the site is open to SQL injection, there are much bigger issues than storing the passwords. If you have access to the DB in any password storage situation, then you'd be able to brute force to get the plaintext. Do you have some method which wouldn't be susceptible to attack given full access to the DB via SQL injection? What exactly are you proposing as an alternative here?
Rich Adams
@Rich Adams It is very common to see sql injection exploits go after the admin's password hash like this one I wrote (http://www.milw0rm.com/exploits/4547). In fact sql injection should be the number 1 threat when considering password storage in a sql database (what threat are you defending against?). To make this system stronger I would "encrypt" the salt with a key that is stored in a local file. The resulting cipher text is the real salt. In order for the attacker to obtain both the salt and the password hash the attacker would need sql injection **AND** the ability to read local files.
Rook
@Rich Adams Defense in depth is about planning on failure. This is why passwords are hashed, it delays the attack after the database has been compromised.
Rook
@The Rook: But even if the salt is known, an attacker doesn't know what hash function you've used (which you do seem to know in your example). It could've been sha256(sha256(salt) + password), or sha256(password + salt), etc. I don't see how having the salt would change a brute force attack. A brute force attack is just trying every possible combination until you get the password, so having the salt wouldn't make any difference to this surely unless you know the hash method? Knowing the hash method would require access to the code (at which point no matter what method you use, it's broken).
Rich Adams
@Rich, sha256 has an output size of 256 bits, that narrows it down. Obscuring this method would be "security though obscurity" which is a sign of an insecure system. You should actually try breaking a password hash before trying to build a password storage system, you have a warped idea of what an attacker is. John the Ripper takes a salt as parameter and can take a list of words to try. A hash of a known value is still a known value, idk why you would suggest such a thing.
Rook
@The Rook: I still don't understand how your proposed method is any different (Than doing hash(hash(salt) + password) for example). In your proposed method you say you would "encrypt" the salt (known value), and use the result as the "real salt". What I don't understand is how this would then not be a known value if you know the salt? Is it because you would "encrypt" rather than "hash"? How would that be better, surely hash would be better as it's one-way? That's the bit I don't currently understand.
Rich Adams
@Rich Adams Of course the password would be hashed and sha256 is great, it would be a CWE violation if a 2 way function where to be used. Obtaining a true understanding of security is difficult and i believe that its only possible though breaking these systems. If you where to actually break a password hash using John The Ripper then I think this would all make sense and you would agree with my stance (and change your answer).
Rook
@The Rook: Actually I think I understand now (please correct me if I'm wrong). Your method is different because you "encrypt" using another secret value as input. So it's like hash(hash(salt + some_secret) + password). If the salt is known, the some_secret is not unless the attacker has the ability to read local files, and that's what makes it more secure?
Rich Adams
@Rich Adams Yes that is a much more secure approach. I'm happy to see this progress. Change your answer to this and i'll give you a +1.
Rook
@The Rook: Thanks for being patient and explaining. As you say, it's difficult to understand properly without breaking some passwords yourself (and I'll be trying that this weekend to see if I learn anything). I have now updated my answer to include the things mentioned in the comments. Thanks.
Rich Adams
@Rich Adams +1 Awesome answer. I like teaching people about security and thats why I am so active on SO.
Rook
The attack that @The Rook mentions is also why you should be using a proper password hashing function like bcrypt, not a baremetal hash like SHA256. Password hashing functions are designed to have a much higher work factor than a bare hash function (indeed some of them are designed by iterating a normal hash function thousands or tens of thousands of times). This greatly decreases the speed at which your hashes can be tested against a dictionary, even if (when) your salts are known.
caf
@caf using an encryption function to store passwords is a clear violation of CWE-257(http://cwe.mitre.org/data/definitions/257.html). Please do not purpose vulnerabilities on SO, I will give you a -1 if i see it :). Also the point of message digest function is to be fast, slowing them down doesn't make sense to me. NIST will not approve a slow message digest function.
Rook
@The Rook: bcrypt is **not** an encryption function - I think you need to do a little more research. The point of message digest functions is indeed to be fast, which is also why a bare message digest function is a *bad* thing to use as a password hashing function (although it can be used a as a building block for the same). A password hashing function should be *slow*; you only have to execute it once to verify a password, whereas the attacker has to execute it once per candidate password tested.
caf
@The Rook: For example, check out how glibc calculates password hashes. This file implements a password hash based on SHA256, but it iterates it a minimum of 5000 times; see line 258 here: http://sourceware.org/git/?p=glibc.git;a=blob;f=crypt/sha256-crypt.c;h=0131c803ca2bec3485500f94fa3628be6ec792ae;hb=HEAD
caf
@caf your right i thought bcrypt was "blowfish encrypt", there is actually blowfish a library with that same name. I still disagree that iteration helps. This thread is getting loooong Care to post a question on SO? I'll give you my answer and then you can vote it down if you don't like it :p
Rook
@The Rook: I don't have a question ;) You are free to disagree of course, but you are going against the cryptographic mainstream. For example, the latest edition of *Cryptography Engineering* by Ferguson, Schneier OpenBSD uses it (that's where bcrypt came from; FreeBSD uses it (where the original iterated-MD5 algorithm comes from); the PBKDF2 standard uses it. There's a heavily sarcasm-laden article about it here: http://tinyurl.com/yg73x3a
caf
@The Rook: The iteration can certainly help. It's called key stretching (or key strengthening). It's just making it more secure against brute force attacking as it will take longer to test each possible key. It can't stop a brute force attack, it just makes it take much longer (and hence often infeasible, depending on how much longer it will take). http://en.wikipedia.org/wiki/Key_strengthening
Rich Adams
@caf don't throw text books at me. I have read my fair share and I know exactly what I'm saying. Okay I'll go ahead an throw in my 2 cents. bcrypt is a very good password storage system for *some cases*. bcrypt was built for storing OpenBSD passwords, the point in which an attacker can obtain a system password like this then they must have *some* or *all* root privileges. Web Applications are very different...
Rook
@caf On a web application you can hide information from the attacker. For instance sql injection is very common so its *much more* likely that the attacker will have access to the database, and **not** the local file system. In this case then you can store a secret salt that must be retrieved before any password hash can be broken **or** a new account created (by stacking an insert statement, which is not possible with `mysql_query()`). By contrast there is no place to hide from root, thus bcrypt was born.
Rook
@caf also bcrypt is a blowfish based hash function, blowfish is old and twofish is the newer block cipher by the same team. It should be noted that BOTH ciphers suffer from weakness although they are not very threatening. Regardless i think Serpent is a better choice. (serpent was #2 aes finalist, twofish was #3. Also there are no known attacks against serpent, not even theoretical.) But Bruce Schneier is still a bad ass and threefish and skien look awesome.
Rook
@Rich Adams your right, I brushed this off too quickly. Sorry for the length of this thread. Although I must admit its very interesting.
Rook
@The Rook: Well, it's certainly been shown possible to leverage SQL injection into full system compromise; it's hardly "defence in depth" to assume file system access won't fall ;) I realise that bcrypt is blowfish-based, but the attacks against blowfish aren't useable against bcrypt.
caf
It should also be noted that both bcrypt and a hidden secret can be used together to protect a web application. I would then use the secret salt as a blowfish key, the primary key as the IV and a use unique salt column. The salt would only be 1 block, so it doesn't matter what mode you use. Each unique salt would be "encrypted" or "decrypted" (doesn't matter), left in binary form and then appended to the users's password before sending it to `bcrypt()`. (Hopefully you got all that, feel free to ask questions).
Rook
@caf yes attackers can leverage sql injection to full system access by exploiting a mis-configured database **OR** by breaking the administrator's password hash. I have been writing exploit code for web application for more than 4 years (http://milw0rm.com/author/677). This is a very good paper on the topic (http://www.ngssoftware.com/papers/HackproofingMYSQL.pdf).
Rook
A: 

Isn't it that we salt the password hashes that if the database gets in some attackers hands, that he is not able to lookup the hashes. If we store the salt in the database as well he only needs to guess the algorithm for the salted hashing...

what happens if the master salt (the one stored in a file , which is used for all salted hashes) is lost or is changed? then all passwords need to be reset speaking the users cant login anymore...

an0nym