57

In some environments, it is required that users change a certain number of characters every time they create a new password. This is of course to prevent passwords from being easily-guessable, especially with knowledge of old passwords such as a departed employee might have for a shared service account.

I have separate questions open to address button-pushing side of this enforcement. However, I'm also curious as to how this enforcement works on the back end. If a cleartext password cannot be derived from a strong hashing algorithm, how does the system determine how many characters have been changed in new passwords?

Iszi
  • 27,027
  • 18
  • 99
  • 163
  • 2
    One could generate and save the hashes of "similar" passwords, or run such an algorithm on the new pass and see if it figures the old pass is similar. More likely they are saving the last n passwords and checking the hash doesn't match any of them.j – ewanm89 Jun 03 '13 at 21:23
  • 1
    Related, regarding storing the old hashes: http://security.stackexchange.com/questions/19458/requiring-regular-password-change-but-storing-previous-paswords – Gilles 'SO- stop being evil' Jun 03 '13 at 23:04

6 Answers6

50

I'm not sure about comparing with all the passwords the user has previously used, as it really depends on the hashing system your using and I would say if its possible to derive any similarity from the hash then its not a very good system to begin with.

But assuming that the user has to supply their current password when setting their new password, you could at least check the new one against the current one as you'll have both as unhashed at that point.

The pam_cracklib module on Linux checks passwords like this and does a few basic checks by default.

  • Is the new password just the old password with the letters reversed ("password" vs. "drowssap") or rotated ("password" vs. "asswordp")?
  • Does the new password only differ from the old one due to change of case ("password" vs. "Password")?
  • Are at least some minimum number of characters in the new password not present in the old password? This is where the "difok" parameter comes into play.

You can find some more details about it here.

Mark Davidson
  • 9,427
  • 6
  • 45
  • 61
  • 10
    That's a good method, and it's the one that actually gets used in the real world. A password history/complexity enforcer could also check against an arbitrary number of historical passwords by hashing variants and derivations when a user first sets the password, and storing those to check against later. – user502 May 26 '11 at 12:29
  • +1 @Mark & @user502. The issue of going back beyond the password being updated deeper into the history for more than just a simple hash comparison (slight changes too) got me thinking about the utility of that anyway. If I am not using the identical password of > 1 generations ago how weak is that compared to a completely new password? My thinking is risk may not justify hashing tons of combinations to store on a phone for that test. – zedman9991 May 26 '11 at 13:51
  • 2
    This can be defeated by changing the password twice in a row. – starblue Jun 06 '11 at 18:37
  • @starblue "_changing the password twice in a row._" can be defeated by enforcing a minimum time between changes. (Something I do not recommend.) – curiousguy Nov 05 '11 at 17:44
  • 3
    In principle, at the time of password change, the system could save the old password (which you have to enter when changing your password) in the clear for future comparison. However this would likely be a very stupid thing to do; an attacker who can see a user's password choice history can likely figure out the user's system for generating passwords, and if it's not random, predict future choices. – R.. GitHub STOP HELPING ICE Mar 17 '14 at 04:17
  • "But assuming that the user has to supply their current password when setting their new password" which is false when the user is resetting a forgotten password. – Damian Yerrick Jan 10 '15 at 20:44
30

This is easily done on password change (where the user is and should be asked to provide both old and new password).

frankodwyer
  • 1,907
  • 12
  • 13
  • 3
    To add to that, it works to check vs the nth password but not the n-1th. I'm not aware of any system that would catch an user using a "washington1", "newyork2", "washington3", "newyork4", "washington5", "newyork6" password sequence – Bruno Rohée Apr 28 '11 at 11:31
  • 2
    Bruno - right, for that you'd have to start storing cleartext passwords I guess (which is not a great idea). – frankodwyer Apr 29 '11 at 09:08
10

Usually, when you change your password, you need to enter the old password first. This is useful for security, to ensure that someone walking by your computer can't very quickly change the password and lock you out while your back is turned. It also allows the server to enforce password distance rules. The server only needs to keep the old password in memory for as long as it takes to verify that the new password is sufficiently different from the old one. It never needs to store the unhashed password.

By the way, such password changing rules are bad for security. (Yes, I know you're the victim here.) If users have to change their password often, they will either choose a password that's very easy to remember, or write it down in an easily-accessible place. There is little advantage in password expiration, and the expected loss in password strength from making users change their password every few months more than offsets those advantages. For a more in-depth treatment of password expiration, see How does changing your password every 90 days increase security? and Is forcing users to change passwords useful? and Requiring regular password change but storing previous passwords?

Gilles 'SO- stop being evil'
  • 51,415
  • 13
  • 121
  • 180
  • Thanks for your answer! I totally forgot about having to enter the existing password again before changing it, and storing it in memory until changed makes sense. Thanks for the two links, I'll be sure to take a look. – Torvero Jun 03 '13 at 21:42
7

Usually, when you change your password, you need to enter the old password first. This is useful for security, to ensure that someone walking by your computer can't very quickly change the password and lock you out while your back is turned. It also allows the server to enforce password distance rules. The server only needs to keep the old password in memory for as long as it takes to verify that the new password is sufficiently different from the old one. It never needs to store the unhashed password, and can erase the old hash as soon as it has stored the new one.

If the server checks equality with older passwords, not just the last one, that's a different story. It's easy enough to check password reuse with old hashes: for each old hash, compute the hash of the new password with the old salt and compare with the old hash value. On a properly configured system, this should take a few seconds.

It's a different matter if the server is checking similarity with older passwords, and not just equality with older passwords plus similarity with the previous one. If the server is using proper hashes, then it must try variations on the new password and hash each variation with all of the old salts. That could take minutes or more with a non-negligible number of variations. So if the server is complaining about similarity with an older password, I would be wary that they may be storing improperly-hashed passwords.

There is another approach for similarity, which is to store the hash of each password variation, each independently salted, as soon as the password is set. But that doesn't buy you much: the server still needs to calculate the hash of the new password with all these salts, which still takes a long time, too long for a typical password change.

A way to recover old passwords that actually works, but that I've never seen implemented anywhere, is to do the following on a password change, after prompting the user for the old password and before erasing the old password from memory:

  • Derive a symmetric key from the new password (using a key strengthening algorithm).
  • Derive a key from the old password in the same way.
  • Decrypt the list of old passwords with the old key.
  • Append the former password to the list.
  • Make the policy checks — all prior passwords are known at this point. If the new password passes the checks…
  • Encrypt the list of old passwords with the new key.
  • Change the password and the encrypted list of prior passwords the database.

This is somewhat risky because if the current password is compromised, all prior passwords are also exposed. But it does allow to enforce a password distance policy to any number of prior passwords with a reasonable computation effort.

Gilles 'SO- stop being evil'
  • 51,415
  • 13
  • 121
  • 180
6

The user should enter both old and new password for a password change. So comparing the new password to the old one can easily be done because the plaintext version is given by the user.

For comparing the new password against previous passwords (other than the current one), checking can only be done by comparing the hash-results. Any method that would allow any other comparison would be a security hole.

Jacco
  • 7,512
  • 4
  • 32
  • 53
6

It can be done only by keeping hashes, it could even be done over several iterations.

The method would be to take the password and iterate it through the hashing algo and check for comparisons against the stored values.

For instance, most users (and service desk folks love to fallback on this as a last resort with angry-important types) will iterate their passwords incredibly simply.

So taking the password: #foob@r1 and making it #foob@r2 which you're likely to see can be tested without knowledge of #foob@r1 by performing a brute force on the algo quickly. With modern processing power you could iterate through the first 4 characters in less than ten seconds.

Though for efficiency sake the last four are typically the ones people change so you're likely to see bigger bang for your buck there. If you're going to do non-consecutive and consecutive you're looking at a pretty big wait for the end user and a big chunk of processor.

Ori
  • 2,757
  • 1
  • 15
  • 29