12

Let's say that in the password policy the password history is defined to remember the last 10 passwords.

I understand password history exists so that if a password is recovered from a compromised database by some attacker, chances are way less likely that password is actually the user's current password.

However, if upon periodic password reset, the users simply appends '1' to his old password, and on the next period reset he appends let's say '2', this greatly decreases the effectiveness of periodic password resets. As soon as the attacker recovers two old passwords of the same user in clear text, he will see the pattern and can guess the actual current password of the user...

The best practice is to hash (+ salt) passwords, however as far as I can see this makes it impossible to check whether the user simply appended a single digit to his old password or not.

The passwords could be encrypted instead of hashed, which would address my concern, however I don't like the idea of passwords being reversible to plain text without bruteforce attacks.

I am wondering what the best solution would be to prevent users from making this minor changes to their old password when resetting it? Can it be technically achieved in a very secure manner, or does this definitely require user awareness?

Stef Heylen
  • 1,726
  • 1
  • 14
  • 16
  • This related question may be of some interest to you http://security.stackexchange.com/questions/101827/how-facebook-knows-my-new-password-is-too-similar-to-my-old-password – Travis Pessetto Jan 12 '16 at 16:11
  • 7
    I believe a similar question has answers that will help: https://security.stackexchange.com/questions/71756/sequential-password-updates/71772#71772 – PwdRsch Jan 12 '16 at 16:45
  • I'd say that question isn't similar, it's almost an exact duplicate. In particular look at the suggestions to store past password hashes, and compare various permutations of a proposed new password against past hashes. – Ben Jan 12 '16 at 17:02
  • 4
    Make them retype the current password and apply a distance metric between the new password and the current one. You can't securely do this for older passwords. And I'll take this opportunity to say that it's absolutely monstruous to make users change their password every other day, especially if they can't use a coping mechanism. – Steve Dodier-Lazaro Jan 12 '16 at 17:43
  • 2
    It's actually very possible to check whether a single digit has been added. Simply subtract a character from the new password, hash that with the old salt, and check for a match. Although just because this is possible does not mean I would recommend it. – Jonathan Gray Jan 12 '16 at 19:01
  • Requiring so many password hurdles (must contain numbers, can't be a word, can't be similar to the last PW) increases the chance that users will write down the password - making the system less secure. – Hannover Fist Jan 12 '16 at 22:10

7 Answers7

38

You can't. Your users are doing this because the reset mechanism has become obtrusive to them getting work done. People are clever enough to get around any of the mechanisms you're going to devise. Those that aren't will quickly learn from those that are. Information like this travels fast.

If you somehow were to figure out how to counter the password1 password2 password3 scheme that people commonly use, you'll almost instantly be confronted with a new scheme. 1password 2password 3password. Now you see a NEW pattern, and simply iterate all numbers. So the user comes up with a yet better scheme. passwordA passwordB passwordC. You'll spend weeks coming up with a counter-measure, only to be defeated in 10 minutes by a clever person who thought of something you didn't.

The point being, that the users ability and cost to get past your counter-measures far outweigh your ability to continually develop new schemes to try to prevent them.

The solution is simply to stop seeing your users as adversaries who you're trying to defeat. They aren't. Users are simply trying to get things done, and you've put up a barrier to do so. If this really bothers you so much, you need to adjust your attitude towards the users and work with them to come up with something that suits BOTH your needs, and doesn't create an adversarial relationship.

Steve Sether
  • 21,530
  • 8
  • 50
  • 76
  • 1
    **You can** Change the reset mechanism so that it generates the password for the user. You won't win any usability awards, but you can get ahead of the counter measures. – emory Jan 12 '16 at 19:24
  • 3
    @emory Sure, you can completely change how passwords are set to make them completely random. But that's changing the nature of passwords entirely. I'd also question why you'd even bother resetting the password, since the whole reason why anyone forces password resets in the first place is that users don't choose passwords with enough entropy to prevent attacks on the hashes. If automation chooses the password, the entropy problem goes away, so why would your force a reset at that point? – Steve Sether Jan 12 '16 at 20:13
  • 4
    I am not really sure of the point of forced password reset. If it is meant to solve an entropy problem, then it seems to be making the problem worse not better. So I would agree with the general point of your answer. – emory Jan 12 '16 at 20:22
  • @emory I think your question about why forced password reset is still so popular can be explained by one of my favorite responses on security.se.com https://security.stackexchange.com/questions/33470/what-technical-reasons-are-there-to-have-low-maximum-password-lengths Just replace DES with NTLM, and the limit being cracking time on a pentium 133. – Steve Sether Jan 12 '16 at 20:44
  • I do agree that this is often burdensome and doesn't lead to improved security... Buy you actually can enforce this... Reversing the hashing process may be impossible with anything but brute force, but you don't actually need to reverse the process. The only thing you need to calculate the hashes for are passwords that are 'similar' to the new one - and you already have the salt of the old one... so generate a list of passwords similar to the NEW one, and see if any pass as the old one. See Sour Lolita's answer below. – Allen Jan 12 '16 at 22:00
  • 2
    @Allen I believe the point of my answer is that whatever algorithm you choose for determining to hash "similar" passwords, the users will quickly come up with something that evades the algorithm. – Steve Sether Jan 12 '16 at 22:03
  • 7
    @emory Don't let users make their own passwords? All that's going to get you is passwords written on stickynotes and attached to monitors. – Blacklight Shining Jan 12 '16 at 22:51
  • @blacklightshining more likely users will just stop using the service. in general I would recommend against it. but I would probably also recommend against forced password resets. if forced password resets are necessary then assigned passwords are the only way to avoid the predictable password problem. – emory Jan 12 '16 at 22:59
  • Besides lowering the password reset requirements, are there other alternatives you would consider? Maybe some form of two factor authentication? – jpmc26 Jan 13 '16 at 00:47
  • A trivial example why similarity comparisons break: `passwordone` `passwordtwo` `passwordthree`. The pattern is trivial to humans, highly non-trivial to password checkers even if they have a dictionary. Same idea, when password changes are forced monthly: `passwordjan` `passwordfeb` `passwordmar`. Remember, you'd have to check not just English but all relevant languages. – MSalters Jan 13 '16 at 08:34
  • @emory Oh, sure, they'll just stop using the service if they have a choice. You get stickynotes on monitors when they _don't_ have a choice (inane enterprise policies, anyone?) – Blacklight Shining Jan 13 '16 at 15:30
  • @blacklightshining wrt inane enterprise policies, I hope no hackers guess my password, login as me, and do my work for me. that would be bad. – emory Jan 13 '16 at 22:14
  • @emory If someone's going to break into your work account, it's more likely that they'll try to steal valuable data. Which you would then be blamed for, because it happened under your account. – Blacklight Shining Jan 16 '16 at 03:30
  • @emory If you're working on software that tracks access to nuclear material, yes, that would indeed be very, very bad. – jpmc26 Feb 27 '16 at 19:47
6

Easy enough: You have a prospective password of "password1". Test "password" and "password0" to see if they work with the old hash. There's no need to see the plaintext of the old password for this to work.

However, this isn't going to work for the reasons Steve Sether lays out.

Loren Pechtel
  • 773
  • 4
  • 9
5

This has been discussed at various points, and most discussions seem to come back to the concept of password topologies - the patterns which lots of passwords have. There is a good OWASP presentation on YouTube, which suggests that a lot of passwords which have to follow complexity rules follow similar patterns:

  • Password1! - If you enforce at least one character from each of uppercase letters, lowercase letters, digits, and special characters, lots of people will pick a capitalised word, followed by a number, with the special character at the end, which will often be ?, !, or . - the topology is UL+DS (using a sort of regex style syntax)
  • Password1 - if you don't enforce a special character, you usually won't get one
  • password1 - if you don't enfore an uppercase letter, you usually won't get one, but if you do, it'll be at the start
  • qwertyuiop - if you don't enforce anything, you get things that are easy to type

There is also some dispute about the value of regularly changing passwords, because they tend to encourage exactly the behaviour you are seeing. However, they are sometimes required due to the relatively slow pace of business choices.

This gives rise to the suggestion of enforcing not just a password change, but a password topology change. The password reset process becomes:

  1. User enters old password (e.g. Password1!), and new password (MyS3cret$) in reset form
  2. System calculates topology of both old password (UL+DS) and new password (ULUDL+S)
  3. System rejects password change if the topologies match, or if the new password does not match the complexity rules

It is also possible to reject certain common topologies completely - maybe you don't want any passwords of the Password1! form, in which case you configure your system to reject any password which has the topology UL+DS.

Never store the topology of a password with it - if your database gets compromised, you would have given attackers a fantastic way to minimise their effort to crack the recovered passwords.

Bear in mind that users will still come up with ways to make weak passwords: they might start alternating Password1! and !2Password, but that suggests that the password change frequency is too high.

Matthew
  • 27,263
  • 7
  • 89
  • 101
  • I don't understand what you mean by "relatively slow pace of business choices" as relevant to passwords. Can you rephrase, or give an example? – dave_thompson_085 Jan 13 '16 at 06:02
  • If your security policy is on a three year review cycle, for example, it's entirely possible that last time it was reviewed, the recommended action was regular password changes. For certain industries (banking in particular), policy changes are required before business process can be updated, meaning that outdated advice can be in use for the entire policy lifecycle, even if technically changes could have been made. Can be frustrating sometimes... – Matthew Jan 13 '16 at 06:55
  • Ah. Got it. (pad) – dave_thompson_085 Jan 14 '16 at 08:57
3

It is straightforward to prevent the specific problem of user's updating new passwords that are too similar to previously used passwords (e.g., only a single digit/character changes).

On the same password change screen, simply require the user to enter their old password, as well as their requested new password. It is good practice anyway to require users to enter their existing password on password change screens (this prevents someone who briefly left their account signed in unattended, having an attacker change their password, and grant themselves access in the future while locking out the real user).

Only accept the new password if you can check server-side that all of the following are true:

  1. The hash of the old password matches the stored hash in the database.
  2. The new password satisfies your strength requirements (either a long passphrase that's potentially all one type of character; or has special characters, capitalization, numbers and is at least 8 characters),
  3. The old and new passwords (both of which you just received in plaintext without saving in your database in plaintext) have a decent edit distance (say greater than 4). If it does not have enough distance, give feedback to the user that the password is too similar to a previous password and should be completely different.
  4. The new password doesn't match any previously used expired hash. (Don't allow password reuse of an older password).

Note this doesn't prevent a determined user from doing

<password>1 -> <other password>1 -> <password>2 -> <other password>2.

If you really wanted to prevent this sort of pattern, you could do it for a few very specific patterns. That is every time a password is saved, you could hash some common modifications of the current password and save them in the database as previously-used expired hashes. This may prevent a few common schemes (e.g., the trailing digit), but users would find ways around them (e.g., increment a character in the middle of the password).

dr jimbob
  • 38,936
  • 8
  • 92
  • 162
2

This is kind of tricky. Its easy to enforce complexity because complexity is relativley easy to discribe but a complex password is in many cases not a good one. For example if your policy forces a min. length of 10 characters, a special char, a number and upper and Lower cases many people will do this:

David1989$

Which is the first Name, the year of birth and a randomly selected special char. This matches the policy but every hacker with a basic knowlege about the person is able to break such password in under a second by using a script that generates such passwords from personal data. Actually some time ago I wrote a script that collected such information from the website of a costumer and related facebook profiles to generate such passwords. It worked pretty fine.

This is why I asked this question some time ago. Since this experience I frequently exract all users passwords from the AD-Server and perform wordlist attacks on them with public available wirdlists and wordlists that are harvested from websites that are technicaly related to the company. Users which passwords where broken need to reset their password and are forced to use a randomly generated password after the second time their password hash is broken.

davidb
  • 4,303
  • 3
  • 20
  • 32
2

This can actually be done, in most cases at least (of course, that doesn't necessarily mean it's a good idea!):

You're right that it is effectively impossible to recover the user's previous password from the stored password hash.

But you don't need to: as part of the password-change process, it's normal to ask for the user's old password, and to check it. This allows you to compare the old and new passwords for similarity.

It's obviously easy to check for adding / incrementing a single digit at the end of the password, but that allows too many simple variations that would be equally obvious to an attacker. Much better would be to calculate the edit distance between the two passwords (there are well-known efficicent algorithms for doing so), and reject if the distance is low (say, <=2) - that will ensure that just changing a few characters (wherever they are in the password) will always be rejected.

Of course, people will still find ways to reuse passwords with small modifications - but hopefully if an attacker recovers one or two historical passwords it will now be much less obvious what the pattern is and hence what password to try now.

One situation in which this doesn't work is if the user has forgotten their password (the "password reset" scenario). In the genuine case where the password has truly been forgotten, this isn't an issue since the new password is unlikely to be a simple modification of one the user can't remember! But there is a genuine risk that users will begin to use "password reset" as a workaround that allows them to change their password to something similar to what went before. (If this is a big concern then the solution suggested in other questions - of generating all passwords within a certain edit distance of the new password, and checking them against the old password's hash - can be used; this is certainly practical for and edit distance of one, and possibly two, but beyond that it starts to become a large amount of computation and likely infeasible.)

psmears
  • 900
  • 7
  • 9
-3

One of the biggest security worry on this is the fact that you're storing the passwords in plaintext if you can distinguish between a single character differences.

Firstly, you should look into storing these passwords as a one way hash, simply because the password storage could potentially be vulnerable to attack. After that, you could implement a mechanism to ensure that none of the newer passwords can ever lead to one of these hashes. This would also mean that you can't tell if they're adding one character or 100 characters after their current password, unfortunately. After all, like the previous posts say, there're always ways to around, and it's not that they're trying to be malicious, they just want to get their work done.

The best way to implement this is to educate your users via some sort of communication platform, be it vocally, or via email or message boards, etc. and also, point them towards the potential problems. After all, people are less likely to find ways around if they know that they're the ones benefiting more from the system than the annoyance caused by it.

adalal
  • 1
  • unless the password hash is stored along with variants from 0-9 at the end – schroeder Jan 12 '16 at 18:00
  • or validation code on the client-side looking for a `[a-z][0-9]^` at the end - there are lots of ways to detect and enforce this without failing to implement a one-way hash of the user's password – schroeder Jan 12 '16 at 18:07
  • Client side validation is no validation.... the only purpose for client side validation is cosmetic / improving user experience. – Jeroen Jan 12 '16 at 18:27
  • 2
    @Jeroen-ITNerdbox yes, I understand that, but it is a way to enforce a set of validation rules. Given that this rule is to protect the user, if the user is sophisticated enough to bypass this validation, they take on their own risks. – schroeder Jan 12 '16 at 18:30
  • I agree that OP suggest the pass are known and talks what storage mechanism to use. Also that plaintext should never ever - not until the death of the universe - be used... 1) the check can be done by asking the user to introduce the old pass - which you check with the hash (and salt) - and compare it with the new one. 2) Education takes - and has already taken - too long to solve this. We need systems that encourage and facilitate to do the right thing. Btw it is moot, with long enough salt and a good pick of hash, similar pass are only a problem if leaked - any pass is a problem if leaked. – Theraot Jan 13 '16 at 09:38