Question

We have a requirement for a security audit that our password policy must disallow the re-use of a previous password from the last 4 used passwords.

We can accomplish this fairly easily by making a call to the server to allow it to compare the password candidate against the database's previous password hashes, but that introduces some lag time in transit. Our managers have asked us to investigate if we can eliminate the delay by implementing a pure client-side solution.

Therefore, my question focuses purely on the feasibility of a safe client-side solution.

Assume that a MITM attacker has found some means to gain access to the payload via HTTPS or client-side application vulnerability.

The Process

The only process I have been able to devise would be to transmit the previous password hashes with their server-side salts to the client ahead of time.

The Risk

The requirement of needing to send the server-side hashes with the password hashes is what presents the inherent risk in my estimation.

Without the salt, then the client would be unable to test the candidate password against the password hashes. However, sending the server-side salt to the client-side exposes it to a potential MITM attacker.

If the attacker was successfully able to bruteforce the current password hash among the previous password hashes, then they could change the password under the nose of the current user.

This exploit could be exasperated if a user requested to change their password, was sent the previous password hashes + salt, and then chose to abandon the changing of the password. This would give a MITM attacker plenty of time to find a suitable entry for the current password hash + salt, and subsequently change the password.

Even if the attacker wasn't able to crack the current password in time, they'd still have plenty of time to crack and use these passwords on other sites where they may not have been updated.

The Question

I've been advised by peers that this might be overly cautious - that hashing functions like Bcrypt would take so long to bruteforce that it's practically impossible even with the salt exposed to the attacker...

In my estimation, this is equivalent to the result of a SQL injection attack. Nonetheless, I'm having trouble convincing my peers...

Is this method of checking if a password candidate would collide with a previous password unsafe? If so, is there another mechanism that would be safe, but which does not require remote calls to a server?

Was it helpful?

Solution

Secrets Are Not Shared

Unless they are not secrets

Ironically from a security perspective that delay, is actually a feature.

To a user, for the most part they will get it right, perhaps they will get it wrong once or twice, after that they'll usually call the help desk anyway. So generally speaking they will pay 1 to 4 times the delay, before they'll switch to the phenomenally slower telephone.

To an attacker they need to guess billions of times and get it wrong before chances start to favour them. Of course the favour is usually due to poor password selection in the first place - most people pick easy to guess passwords, or riff on a basic template by changing say a number on the end. But that aside an attacker using a pure brute-forcing on a 2^512 hash needs to request on average 2^256 checks.

By keeping the hash+salt on the server, each of those request must come to your server. This accomplishes two things:

  1. Your server acts as a bottle neck slowing the attack
  2. You can see from the logs that someone is attacking the account permitting defensive tactics like locking the account, or blocking the ip.

By giving the hash+salt to the client to compare themselves:

  1. The client (being compromised) can distribute those out to a cloud platform bringing parallel and optimised vector machines to bear on the hash.
  2. You cannot see if an attack is being mounted, the first sign you will see is a successful login - is it legitimate? This then brings in two tier auth and other problems, which will slow down authentication again.

What to do

If login/password change is slow, find ways to speed up the server for the first 3/4 attempts. Find the bottleneck and provide resources. After those first requests though specifically slow it down. Legitimate users will divert to the help desk.

Push back on the business and point out how "optimising" this process actually makes it insecure. Point out that it is the first step toward a massive data breach.

OTHER TIPS

We have a requirement for a security audit that our password policy must disallow the re-use of a previous password from the last 4 used passwords.

"Four" sounds a little arbitrary, but anyway ...

We can accomplish this fairly easily by making a call to the server ... but that introduces some lag time in transit.

Really? A lag so long that it's considered a Performance Issue significant enough for you to spend time looking into it?

This delay will only be incurred when a User changes their Password. How often is that going to happen and how much of a delay, proportionally, might this introduce? Say it takes a whole second for each User, once every three months. What return on Investment are the Management expecting to see from this work?

This really does sound like a case of Premature Optimisation to me.

Our managers have asked us to investigate if we can eliminate the delay by implementing a pure client-side solution.

Basic Rule of Thumb: Nothing run on or coming from the Client can be trusted. Anything you write can, in theory at least, be circumvented.

Presumably this would be written in some client-side scripting language; all someone would have to do is comment out the call to the [well-written, nicely encapsulated] password checking function and they would be able to reuse the same password forever more - and you'd never know about it.

Secure stuff must be done in a secure environment and that's the Server that you have control over. Anything else is just smoke and mirrors.

There’s no reason to use the salt from the server, you might as well use a salt created on the client, and a good hash function on the client.

You just have to prepare for the incredibly unlikely case that a password passes the test on the client but not on the server, which will have different hash values.

Whether it’s better to have no client code but to do everything just on the server is another question.

Licensed under: CC-BY-SA with attribution
scroll top