[WEB SECURITY] Idea: different approach to password hashing

John Steven jsteven at cigital.com
Mon Feb 3 15:04:04 EST 2014


Stalwart AppSec educator—thanks for the nod. Paul,

Your problem characterization is thoughtful, considering different forms of attack and the various surfaces upon which they can occur. You’ve even re-considered the (informal) threat model applying your proposed control alternatives. Well-played. Since you’ve taken the problem one or two steps past where most have, it’s worth following up beyond what I’ve posted publicly. 

[Adaptive One-way Functions]
I would not oppose an approach predicated solely on an adaptive one-way function. Research load characteristics and tune for effective results. 

> 1) Throw a lot of hardware at it. Lots.  

You could throw iron at the problem (*1) using the standard adaptive one-way function formulations. Distributing the work from server to client is a natural response, yes, but not one I’ve seen in practice very often. You’re correct that doing so ‘inherits’ another problem: continued support for a user-specific salt (*2). You rightly indicate that it also inherits the problem of obscured credential replay by MitM. 

In essence, this design leads down a slippery slope to a home-rolled challenges/response (C/R) protocol—something to be avoided. We see Existing C/R schemes, such as OAuth, protect plaintext credentials against MitM theft. Bearer tokens (application/end-point ‘passwords') used by these schemes can help designers limit the amount of CPU-intensive server-based credential verification. When designing systems, prefer these to home-rolled schemes; their limitations are well-understood (*3).

As a user, you’re probably familiar with organizations (like social media sites) that rely on PBKDF2 or bcrypt with high work factors to protect databased credentials but also use tokens to reduce the amount of bcrypt-driven password verification that occurs. If you’ve already forsaken OAuth, explore other fancy C/R protocols with Javascript support like SRP (*4).

[Keyed Macs]
> 3) Use a [server-side] HMAC, … [and do it well]

I would suggest this approach and advise carefully solving knock-on problems. 

As stated, I’m a fan of this approach, principally because it is both simple and because it forces the attacker into asymmetric (disadvantaged) warfare with the defender (*5). That is, the defender is subject to only nominal password verification effort whereas the attacker must pay to brute force (or steal) the secret key prior to enjoying the same ease of verification.  

As Jim hedged, one inherits the ‘key protection’ problem with this scheme. Detractors rightly indicate organizations can easily screw key protection up. Within my own experience, it’s been easy to design solutions because the organizations with which I work enjoy benefits like a) separate of duties involved in generating, handling, and using key material, b) reasonable application server configuration, and c) broadly deployed HSM support. Though, even without fancy hardware, organizations often have existing regimes for production secret protection. 

[Paul’s Proposed Design]
Paul, the approach you proposed (*6), as I understand it, may be represented as follows:

(0)  Client C: uname —> Server S
(1)  S: SHA2(server_salt + uname) —> C
(2)  C: bcrypt(salt, pw) —> S
(3)  S: verify(SHA2(<bcrypt result>))

My “brief” analysis of this approach places it (surprisingly?) in an equivalence class with bcrypt itself, once known to an attacker. For those interested in why, contact me offline. 

This scheme does provide some additional protections to credentials in flight (during step (2)). if designers desire this effect, I’d recommend revisiting the C/R section and selecting from that family of approach.

John Steven                 
iCTO, Cigital
+1,703-727-4034   |  @M1splacedsoul

* (1) - http://www.youtube.com/watch?v=8mbkWMEMB9s

* (2) - Some ascribe anti-reversing properties to salts beyond obscuring duplicate plaintext and raising space/time difficulty on targeted individual attack. This results in complaint about salts made public.

* (3) - http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/

* (4) - https://github.com/symeapp/srp-client

* (5) - http://goo.gl/Spvzs

* (6) - Quoted from Paul’s mail:

>> 1) The salt can be generated as hash(server_salt + user_name) - where server_salt is a random number that is unique to the server, public, and the same for all users. The resulting hash appears to have the required properties of a salt.
>> 2) The server should do a single, fast, hash operation on the hash it receives. As an example: the server stores SHA-256(bcrypt(salt, password)). The client sends bcrypt(password) then the server applies SHA-256 and checks the hash. 

* ():
> John Stevens 

...John Steven’s...

More information about the websecurity mailing list