You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shiro.apache.org by Peter Ledbrook <pe...@cacoethes.co.uk> on 2010/10/30 10:05:38 UTC

Salted hashing of passwords - where to store the salt?

Hi,

I came across the changes to the credential matching and wondered
about the recommendations for generating the salt for passwords. The
Javadoc suggests storing the salt along with the credentials, but
doesn't this defeat the purpose somewhat? If an attacker has gained
access to the hashed passwords, wouldn't they also have access to the
salts? Hence they can still use dictionary attacks. Am I missing
something here?

Thanks,

Peter

-- 
Peter Ledbrook
Grails Advocate
SpringSource - A Division of VMware

Re: Salted hashing of passwords - where to store the salt?

Posted by Les Hazlewood <lh...@apache.org>.
Lol, I thought about that right after I hit 'send'.  I'll add it today
since I have some time to relax for a change.

Cheers,

Les

Re: Salted hashing of passwords - where to store the salt?

Posted by Peter Ledbrook <pe...@cacoethes.co.uk>.
> Wiki worthy, imo.

Agreed. Thanks for the detailed response Les.

What I wondered about is how attackers most typically get access to
the hashed passwords. If they gain access to the passwords (a la
Atlassian's problem), how likely are they to have access to the salt?
I see though that the hash iterations and salt help eliminate the
Rainbow attack, which is a significant win. Thanks for bringing that
to my attention.

Peter

-- 
Peter Ledbrook
Grails Advocate
SpringSource - A Division of VMware

Re: Salted hashing of passwords - where to store the salt?

Posted by "Alan D. Cabrera" <li...@toolazydogs.com>.
Wiki worthy, imo.


Regards,
Alan

On Oct 30, 2010, at 12:49 PM, Les Hazlewood wrote:

> 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


Re: Salted hashing of passwords - where to store the salt?

Posted by Les Hazlewood <lh...@apache.org>.
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

Re: Salted hashing of passwords - where to store the salt?

Posted by Kalle Korhonen <ka...@gmail.com>.
It's a useful thought exercise but go ahead and finish that thought.
Where would you put the salt if not with the password? If you can find
a better, more secure storage location for the hash, why don't you put
the passwords there? Per-password-salt is the best protection against
dictionary attacks and storing hash with the password is a widely
accepted and used practice. You can of course store it somewhere else
but it won't buy you any more security.

Kalle


On Sat, Oct 30, 2010 at 1:05 AM, Peter Ledbrook <pe...@cacoethes.co.uk> wrote:
> Hi,
>
> I came across the changes to the credential matching and wondered
> about the recommendations for generating the salt for passwords. The
> Javadoc suggests storing the salt along with the credentials, but
> doesn't this defeat the purpose somewhat? If an attacker has gained
> access to the hashed passwords, wouldn't they also have access to the
> salts? Hence they can still use dictionary attacks. Am I missing
> something here?
>
> Thanks,
>
> Peter
>
> --
> Peter Ledbrook
> Grails Advocate
> SpringSource - A Division of VMware
>

Re: Salted hashing of passwords - where to store the salt?

Posted by "Alan D. Cabrera" <li...@toolazydogs.com>.
On Oct 30, 2010, at 1:05 AM, Peter Ledbrook wrote:

> Hi,
> 
> I came across the changes to the credential matching and wondered
> about the recommendations for generating the salt for passwords. The
> Javadoc suggests storing the salt along with the credentials, but
> doesn't this defeat the purpose somewhat? If an attacker has gained
> access to the hashed passwords, wouldn't they also have access to the
> salts? Hence they can still use dictionary attacks. Am I missing
> something here?

If the salt is random per password then one cannot use a dictionary attack.


Regards,
Alan