If an attacker has already compromised your data store and they can see both the credentials hash and it's salt (whether the salt is random or not), then yes, it is possible to perform dictionary attacks: They can use the discovered salt + a dictionary value as input to the hash function to try to compute a matching value. If the resulting hash matches the stored credentials hash, then they will infer the original plaintext password.
There are 3 options I can think of that you can do to make this more secure: 1. Definitely use more than one hash iteration (this is built into Shiro's Hash concept). The number of hash iterations is usually application-wide, so it is not necessary to store along side the password and the salt. This makes it a) much much harder for dictionary attacks since the number of iterations is one more piece of data they may not have access to, and b) significantly slows down the attacker since they have to perform multiple hashes for _each_ salt+dictionary value pair in real time. I do this for all of my passwords and never use just a single iteration (I usually use somewhere between 500 and 2000 iterations). The speed difference is negligible to end-users but quite noticeable to attackers. Also, because of the speed difference, that gives you more time to discover what is going on and shut things down. For example, maybe some monitoring alert is triggered because your CPU spikes because they're thrashing it or the number of requests is abnormally high and you can investigate quickly. 2. Similar to the concept of the number of hash iterations not being stored along side the password hash & salt, you could pair a server or application-specific salt with the account salt and use that as the total salt supplied to the hash function. For example: salt_bytes = server salt bytes concatenated with user-specific salt bytes credentials hash = SHA-512(salt_bytes + plaintext password bytes) 3. Store the salt in a separate data store. If the attacker compromises one data store, it does not necessarily mean they can compromise the other data store. Note that if you use either a salt or change the number of hash iterations, or both, it virtually eliminates the possibility of rainbow attacks. For those unaware, a rainbow attack uses what is called a 'rainbow table': essentially a huge map of pre-calculated hash values (key: plaintext password and/or dictionary word, value: hashed output). Rainbow attacks are powerful because there is very little computation time for the attacker - they simply look up a value for a given plaintext key. If the hashed value matches what is stored, they immediately know the original password. But the possibility of a pre-computed rainbow table knowing about a salt is nearly impossible if your salts are sufficiently large securely randomly generated numbers - as they absolutely should be - and not say, based on account data such as a username or given name. That's why good secure-random salts effectively eliminate the possibility of rainbow attacks. Anyway, #1 and #2 add that extra bit of difficulty, but then you have to ask yourself - "If they can compromise my data store, then do I consider my application compromised as well?". If so, then #1 and #2 don't matter much. But I still consider them useful and use them myself for that 'extra bit' that makes it that much harder to attack. #3 is also useful, but most of the time considered too impractical for most applications. This stuff is about making it 'sufficiently difficult' to deter attackers. You have to judge for yourself what constitutes being 'sufficiently difficult' for your application. Storing the salt along side the password is perfectly fine for 98% of all applications, which is why it is such a common practice. Doing #3 might only be worthwhile for certain government/NSA type of applications (and believe me, most government apps I've seen have nowhere near this level of security built in, sadly enough). Anyway, that's my $1.02 - I hope it helps! Cheers, -- Les Hazlewood Founder, Katasoft, Inc. Application Security Products & Professional Apache Shiro Support and Training: http://www.katasoft.com
