Information Security Stack Exchange is a question and answer site for information security professionals. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

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?

share|improve this question

marked as duplicate by Gilles, Neil Smithline, Xander, Deer Hunter, WhiteWinterWolf Jan 13 at 9:28

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
This related question may be of some interest to you security.stackexchange.com/questions/101827/… – Travis Pessetto Jan 12 at 16:11
7  
I believe a similar question has answers that will help: security.stackexchange.com/questions/71756/… – PwdRsch Jan 12 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 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 DL Jan 12 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 at 19:01
up vote 34 down vote accepted

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.

share|improve this answer
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 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 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 at 20:22
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 at 22:03
6  
@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 at 22:51

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.

share|improve this answer
    
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 at 6: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 at 6:55
    
Ah. Got it. (pad) – dave_thompson_085 Jan 14 at 8:57

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.

share|improve this answer

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).

share|improve this answer

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.

share|improve this answer

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.)

share|improve this answer

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.

share|improve this answer
    
unless the password hash is stored along with variants from 0-9 at the end – schroeder Jan 12 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 at 18:07
    
Client side validation is no validation.... the only purpose for client side validation is cosmetic / improving user experience. – Jeroen - IT Nerdbox Jan 12 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 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 at 9:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.