Many operating systems enforce certain constraints on passwords such as changing the password every n days etc.
Some also enforce a policy such as "the new password must differ in at least n characters from your previous password(s)".
My question is: how can you enforce such a policy without actually storing the passwords in clear text. Specifically: If I do not want to store the passwords in clear text but rather als (salted) hashes, how would I enforce this kind of poilicy?
Thanks in advance!
You can't. You can check that the password doesn't match the last N passwords by comparing it to old hashes, but anything that goes down to character level cannot be easily applied.
In theory, if you really wanted to do it, you could probably bruteforce one or two characters difference. (just hash all possible 2-character changes from the new password) But given how new algorithms rely on hashing being slow, this is not realistic with modern password hashing functions.
Just to be clear, I'm assuming that clear-text is the same as locally-encrypted for all practical purposes. Some systems will encrypt and save your original password, so they can verify it or allow recovery. Of course that only provides few benefits of hashing.
I have seen a couple of posts on this, but I haven't seen a definitive answer necessarily. Therefore, I thought I would try to restate the question in a new context (Department of Defense).
According to DISA's "Application Security and Development STIG, V3R2", section 3.1.24.2 Password Complexity and Maintenance, DoD enterprise software has a pretty tough guideline with passwords:
Passwords must be at least 15 characters long.
Passwords must contain a mix of upper case letters, lower case letters, numbers, and special characters.
When a password is changed, users must not be
able to use personal information such as names, telephone numbers,
account names, or dictionary words.
Passwords must expire after 60
days.
Users must not be able to reuse any of their previous 10
passwords.
Ensure that the application has the capability to require that new account passwords differ from the previous password by at least four characters when a password is changed.
Users must not be able to change passwords more than
once a day, except in the case of an administrator or a privileged
user. Privileged users may be required to reset a user’s forgotten
passwords and the ability to change passwords more than once per day.
As stated in NullUserException's post, for the developer to actually be able to check for the last X amount of passwords (and also ensure that new passwords differ from the previous password [bullet 6]), the passwords would have to be encrypted using a reversible method, rather than hashing a password (which is a lot more unsecure, even if I am using NSA approved encryption algorithms). The proposed answer seemed to make a deal of sense, although there seemed to be some discrepancies and arguments, as seen in Dan Vinton's post.
I guess the real question here is, has anyone been able to implement all of these seemingly common password complexity constraints without actually diminishing the security of their systems?
Edit: Vulnerability APP3320.7 (bullet point 6) states "Ensure that the application has the capability to require that new account passwords differ from the previous password by at least four characters when a password is changed." That lead me to believe that I would have to run a string similarity algorithm such as Levenshtein to check similarity. I cannot do this on a hash/salt. Please let me know if I am wrong here?
The character distance requirement as stated is only for the (one) previous password, not the 10 previous. Assuming your password tool requires entering the current password as well as a new one, you just check against that; no need to store anything there. (Also noted on this answer to the post you mentioned.)
The requirement of not matching any of the previous 10 passwords, of course, is handled by just checking against the old hashes.
Using reversible methods to generate password-derived keys is not a secure practice and you must NOT DO IT. You must not store plain-text authentication information either. Since you will be storing keys (and perhaps salts, if you're into that kind of fetish), it is trivial to keep copies of the last 10 keys and check the newly submitted passwords against them.
Requiring that new passwords differ from previous N passwords by M characters is crazy, as it implies that password history is either plaintext or reversibly encrypted, neither of which is safe.
Limiting password history to "last N" and consequently limiting the frequency of password changes to "once per day" made sense when storage space was cost-prohibitive, but makes no sense today, where storage is very cheap. A much more reasonable policy be "new passwords must not be the same as any known old passwords" and leave it at that. Ditch the "last N" and ditch the "max once daily" rule which is only there to prevent users from circumventing history.
Some password management systems support this configuration (and have supported it for many years). Example: https://hitachi-id.com/password-manager/features/password-policy-enforcement.html
Note: This doesn't explicitly relate to programming, but I was hoping this can be explained from a programmers point of view.
There are two things I simply don't understand about current 'password strength ratings'. This all pertains to brute force entry. (If these 'password strength ratings' relate to any other type of breach aside from using a common/popular password please let me know).
1) Why does it matter if I include numbers/symbols/uppercase letters as long as the password system allows for the possibility of using them?
For example lets just say:
a) The systems accepted characters are a-z, A-Z, 0-9, and their "shifted values" '!' to ')', so 72 possible symbols.
b) I use a password of length ten, so 72^10 possibilities.
c) My password is not in the top 10,000 most common/popular passwords used. So 72^10 - 10,000 possibilties remain.
Wouldn't an all lowercase password like 'sndkehtlyo' be identical strength as 'kJd$56H3di' since they both share the same possibility of including the additional characters? Doesn't the brute force algorithm have to include those numbers/symbols/uppercase regardless of whether or not I use them? It seems like these rating systems believe a brute force attempt will try all 26^n lowercase passwords first, all 52^n passwords second, then all 62^n passwords, etc, etc.
2) Why does that even matter? I have yet to come across any password system that doesn't lock you out after some small fixed number of attempts (usually 5). How can brute force approaches even work these days?
I feel like I am missing something fundemental here.
1) Cracking a password doesn't need to happen in one pass. A well implemented brute force crack may iterate first through small ranges of characters and then work its way into caps and numbers. Starting with the simplest ranges first (maybe just lowercase a-z) will find passwords of those unfortunate enough to have constructed a weak password. They may also start with dictionary attacks or Most-common-passwords-used attacks first as they take very little time.
2) Crackers aren't going to brute force right through some online service's login prompt. Anyone truly intent on getting access to an account would retrieve the hash of a user's password and crack it on their own machine, not over the internet. While there are practically infinite ways to hash a password there are some very common methods that can be identified by properties such as the hash's character length. You can read more about common hash algorithms in this Wikipedia article.
1) All man-made passwords are not totally random. In other words, taking the human factor (e.g. memorability), the probability distribution of a password space is not even.
2) The attempt times restriction is used for authentication, which is a means of Access Control. It has nothing to do with the password strength. It is the system level control method and it is usually configurable. Of course, it is an effective weapon against brute force attacks, but one can still design a system without that access control method. Also, hackers may not crack into the system directly but they could intercept the user data from the network which contains encrypted password or anything else and use brute force or other ways to crack it. So a high-strength password scheme, a high-security crypto method and a well-designed access system could live together to make a strong security system.
In general, with a brute force system, you are correct. But, a lot of automated password crackers out there begin their searches by trying common english words and their combinations. For example: sports teams, states, dates, etc etc... So by having those special characters it immediately eliminates a lot of those possibilities. Generally, if you're worried about brute force, a much longer password is more secure than a shorter one with special characters.
Thanks for looking. All sincerely helpful answers are voted up.
I use a password strength meter to let the user know how strong the password they've chosen is. But this password checker obviously doesn't cover how weak under a dictionary attack the password is. How can I check for that, and is it worth it?
Also my regular password checker runs initially with javascript in the browser (no transmission required). If I want to check for dictionary attack weakness, I'd have to transmit it to a script. My understanding is that I shouldn't transmit it in the clear.
Can someone help me sort this out. How do I check the password isn't weak under a dictionary attack and how do I encrypt it before transmitting to my script?
Extra info:
Why do I think I need the dictionary attack check in addition to the regular password meter? As some of you have pointed out, users can choose passwords like P#ssword or Yellow12. But most password strength checkers I've come across will treat this as a good password. At least I'm using Yet Another Password Meter and it does (and I actually think it's one of the better password checkers.) If anyone knows of a stronger password checker, please mention it, but only if you know for sure based on experience that it's stronger ;)
But my question really is: how do I conduct a dictionary attack check on the password? I read somewhere that it's done against the hash, but where do I do the search? Once I find out how to do it, I will then decide whether it's worth it or not.
thanks to everyone who's helped out so far :)
Opinions are going to vary and some people will say that checking for dictionary words is important. I disagree and instead favor requiring different cases of letters, numbers and special characters like !##$%^&*()_-=+. Obviously passwords should be case sensitive.
Dictionary attacks are much less likely to succeed with the presence of numbers and special characters. Lets say that there are 1000 common passwords. Now with the addition of a required upper case letter and special character lets assume the user is "lazy" and they choose to make the first letter capital and add a special character to the end. That 1000 sized dictionary is now over 30,000.
Additionally there should be account lockouts in place to avoid dictionary attacks. And possibly a throttle on how often an IP address can attempt to login depending on your application.
There may still be a case to avoid some very common passwords while running your script. I would for example not allow the word password p#ssword or any variation of password.
Edit: A captcha, while hated by most (including me) may be appropriate as well after a few failed logins to avoid brute force login attempts.
I'm coming to this question later than the others, and I'm surprised that no-one has pointed out that a dictionary check might not be exhaustive. At least no-one has said it in so many words.
I think you need a large dictionary, where each entry is hashed and compared to the hashed password. This will allow you to say the user's chosen password is not in your dictionary, but how will you be sure it's complete?
Obviously, you can't be sure. Do you include foreign words? Technical words?
Do password crackers have access to better dictionaries?
I think all you can do is advise users how to create a good password — show them a few examples — but let it be their choice.
And do the SSL thing.
One additional point - if you control the site, you can stop dictionary attacks by limiting the number of times a user can try a user/pass.
It is great you want your users to have better passwords and you should continue in that direction but a better solution for the dictionary/brute force attack would be an exponential backoff solution to failed login attempts. No real user will try and login 1000 times in 10 seconds with all different passwords.
If you are using proper complexity requirements (length, mix of casing, numbers, symbols, and perhaps forbid repeat a char consecutively) then I'd say it's not really worth it. If you're in a situation where that would be required then probably password authentication would not be good enough for your situation anyway.
SSL
If your website in any way or on any page requests sensitive personal information, including passwords, then you should enable and enforce SSL across the entire site. This will ensure that all passwords are transmitted in encrypted form from the browser to the server, and that nobody can sniff the passwords off the network or modify the pages in transit (and alter the form postback url's).
Password Meter
You should run your password meter entirely in the browser. You should accept any and all passwords (with a min length of, for example, 6 characters) that the user enters, but feel free to hint to the user, from within the browser, whether they have entered a weak or strong password.
I can understand that imposing a minimum length on passwords makes a lot of sense (to save users from themselves), but my bank has a requirement that passwords are between 6 and 8 characters long, and I started wondering...
Wouldn't this just make it easier for brute force attacks? (Bad)
Does this imply that my password is being stored unencrypted? (Bad)
If someone with (hopefully) some good IT security professionals working for them are imposing a max password length, should I think about doing similar? What are the pros/cons of this?
Passwords are hashed to 32, 40, 128, whatever length. The only reason for a minimum length is to prevent easy to guess passwords. There is no purpose for a maximum length.
The obligatory XKCD explaining why you're doing your user a disservice if you impose a max length:
A maximum length specified on a password field should be read as a SECURITY WARNING. Any sensible, security conscious user must assume the worst and expect that this site is storing your password literally (i.e. not hashed, as explained by epochwolf).
In that that is the case:
Avoid using this site like the plague if possible. They obviously know nothing about security.
If you truly must use the site, make sure your password is unique - unlike any password you use elsewhere.
If you are developing a site that accepts passwords, do not put a silly password limit, unless you want to get tarred with the same brush.
[Internally, of course your code may treat only the first 256/1024/2k/4k/(whatever) bytes as "significant", in order to avoid crunching on mammoth passwords.]
Allowing for completely unbounded password length has one major drawback if you accept the password from untrusted sources.
The sender could try to give you such a long password that it results in a denial of service for other people. For example, if the password is 1GB of data and you spend all your time accept it until you run out of memory. Now suppose this person sends you this password as many times as you are willing to accept. If you're not careful about the other parameters involved this could lead to a DoS attack.
Setting the upper bound to something like 256 chars seems overly generous by today's standards.
First, do not assume that banks have good IT security professionals working for them. Plenty don't.
That said, maximum password length is worthless. It often requires users to create a new password (arguments about the value of using different passwords on every site aside for the moment), which increases the likelihood they will just write them down. It also greatly increases the susceptibility to attack, by any vector from brute force to social engineering.
Setting maximum password length less than 128 characters is now discouraged by OWASP Authentication Cheat Sheet
https://www.owasp.org/index.php/Authentication_Cheat_Sheet
Citing the whole paragraph:
Longer passwords provide a greater combination of characters and consequently make it more difficult for an attacker to guess.
Minimum length of the passwords should be enforced by the application.
Passwords shorter than 10 characters are considered to be weak ([1]).
While minimum length enforcement may cause problems with memorizing passwords among some users, applications should encourage them to set passphrases (sentences or combination of words) that can be much longer than typical passwords and yet much easier to remember.
Maximum password length should not be set too low, as it will prevent users from creating passphrases. Typical maximum length is 128 characters.
Passphrases shorter than 20 characters are usually considered weak if they only consist of lower case Latin characters. Every character counts!!
Make sure that every character the user types in is actually included in the password. We've seen systems that truncate the password at a length shorter than what the user provided (e.g., truncated at 15 characters when they entered 20).
This is usually handled by setting the length of ALL password input fields to be exactly the same length as the maximum length password. This is particularly important if your max password length is short, like 20-30 characters.
One reason I can imagine for enforcing a maximum password length is if the frontend must interface with many legacy system backends, one of which itself enforces a maximum password length.
Another thinking process might be that if a user is forced to go with a short password they're more likely to invent random gibberish than an easily guessed (by their friends/family) catch-phrase or nickname. This approach is of course only effective if the frontend enforces mixing numbers/letters and rejects passwords which have any dictionary words, including words written in l33t-speak.
One potentially valid reason to impose some maximum password length is that the process of hashing it (due to the use of a slow hashing function such as bcrypt) takes up too much time; something that could be abused in order to execute a DOS attack against the server.
Then again, servers should be configured to automatically drop request handlers that take too long. So I doubt this would be much of a problem.
I think you're very right on both bullet points. If they're storing the passwords hashed, as they should, then password length doesn't affect their DB schema whatsoever. Having an open-ended password length throws in one more variable that a brute-force attacker has to account for.
It's hard to see any excuse for limiting password length, besides bad design.
The only benefit I can see to a maximum password length would be to eliminate the risk of a buffer overflow attack caused by an overly long password, but there are much better ways to handle that situation.
Ignore the people saying not to validate long passwords. Owasp literally says that 128 chars should be enough. Just to give enough breath space you can give a bit more say 300, 250, 500 if you feel like it.
https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Password_Length
Password Length Longer passwords provide a greater combination of
characters and consequently make it more difficult for an attacker to
guess.
...
Maximum password length should not be set too low, as it will prevent
users from creating passphrases. Typical maximum length is 128
characters. Passphrases shorter than 20 characters are usually
considered weak if they only consist of lower case Latin characters.
My bank does this too. It used to allow any password, and I had a 20 character one. One day I changed it, and lo and behold it gave me a maximum of 8, and had cut out non-alphanumeric characters which were in my old password. Didn't make any sense to me.
All the back-end systems at the bank worked before when I was using my 20 char password with non alpha-numerics, so legacy support can't have been the reason. And even if it was, they should still allow you to have arbitrary passwords, and then make a hash that fits the requirements of the legacy systems. Better still, they should fix the legacy systems.
A smart card solution would not go well with me. I already have too many cards as it is... I don't need another gimmick.
If you accept an arbitrary sized password then one assumes that it is getting truncated to a curtain length for performance reasons before it is hashed. The issue with truncation is that as your server performance increases over time you can't easily increase the length before truncation as its hash would clearly be different. Of course you could have a transition period where both lengths are hashed and checked but this uses more resources.
Try not to impose any limitation unless necessary. Be warned: it might and will be necessary in a lot of different cases. Dealing with legacy systems is one of these reasons. Make sure you test the case of very long passwords well (can your system deal with 10MB long passwords?). You can run into Denial of Service (DoS) problems because the Key Defivation Functions (KDF) you will be using (usually PBKDF2, bcrypt, scrypt) will take to much time and resources. Real life example: http://arstechnica.com/security/2013/09/long-passwords-are-good-but-too-much-length-can-be-bad-for-security/
In .net core 6 I use HashPasswordV3 method that it use HMACSHA512 with 1000 iterations. I tested some password length and it generate a 86 characters hash.
So I set the PasswordHash field in sql server for varchar(100).
https://stackoverflow.com/a/72429730/9875486
Storage is cheap, why limit the password length. Even if you're encrypting the password as opposed to just hashing it a 64 character string isn't going to take much more than a 6 character string to encrypt.
Chances are the bank system is overlaying an older system so they were only able to allow a certain amount of space for the password.
Should there be a maximum length? This is a curious topic in IT in that, longer passwords are typically harder to remember, and therefore more likely to get written down (a BIG no-no for obvious reasons). Longer passwords also tend to get forgotten more, which while not necessarily a security risk, can lead to administrative hassles, lost productivity, etc. Admins who believe that these issues are pressing are likely to impose maximum lengths on passwords.
I personally believe on this specific issue, to each user their own. If you think you can remember a 40 character password, then all the more power to you!
Having said that though, passwords are fast becoming an outdated mode of security, Smart Cards and certificate authentication prove very difficult to impossible to brute force as you stated is an issue, and only a public key need be stored on the server end with the private key on your card/computer at all times.
Longer passwords, or pass-phrases, are harder to crack simply based on length, and easier to remember than requiring a complex password.
Probably best to go for a fairly long (10+) minimum length, restricting the length useless.
Legacy systems (mentioned already) or interfacing outside vendor's systems might necessitate the 8 character cap. It could also be a misguided attempt to save the users from themselves. Limiting it in that fashion will result in too many pssw0rd1, pssw0rd2, etc. passwords in the system.
One reason passwords may not be hashed is the authentication algorithm used. For example, some digest algorithms require a plaintext version of the password at the server as the authentication mechanism involves both the client and the server performing the same maths on the entered password (which generally won't produce the same output each time as the password is combined with a randomly generated 'nonce', which is shared between the two machines).
Often this can be strengthened as the digest can be part computed in some cases, but not always. A better route is for the password to be stored with reversible encryption - this then means the application sources need to be protected as they'll contain the encryption key.
Digst auth is there to allow authentication over otherwise non-encrypted channels. If using SSL or some other full-channel encryption, then there's no need to use digest auth mechanisms, meaning passwords can be stored hashed instead (as passwords could be sent plaintext over the wire safely (for a given value of safe).
Microsoft publishes security recommendations for developers based on their internal data (you know, from running the biggest software enterprise in the history of computing) and you can find these PDFs online. Microsoft has said that not only is password cracking near the least of their security concerns but that:
“Criminals attempt to victimize our customers in various ways and
we’ve found the vast majority of attacks are through phishing, malware
infected machines, and the reuse of passwords on third-party
sites—none of which are helped by very long passwords." -Microsoft
Microsoft's own practice is that passwords can be no longer than 16 and no shorter than 8 characters.
https://arstechnica.com/information-technology/2013/04/why-your-password-cant-have-symbols-or-be-longer-than-16-characters/#:~:text=Microsoft%20imposes%20a%20length%20limit,no%20shorter%20than%20eight%20characters.
I found using the same characters for the first 72 bytes of a password gives a successful verification using password_hash() and password_verify() in PHP, no matter what random string comes after the first 72 bytes.
From PHP docs: https://www.php.net/manual/en/function.password-hash.php
Caution: Using the PASSWORD_BCRYPT as the algorithm, will result in the password parameter being truncated to a maximum length of 72 bytes.
Recent Updates from OWASP now recommend a max length:
https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
Maximum password length should not be set too low, as it will prevent users from creating passphrases. A common maximum length is 64 characters due to limitations in certain hashing algorithms, as discussed in the Password Storage Cheat Sheet. It is important to set a maximum password length to prevent long password Denial of Service attacks.
Just 8 char long passwords sound simply wrong. If there ought to be a limit, then atleast 20 char is better idea.
I think the only limit that should be applied is like a 2000 letter limit, or something else insainly high, but only to limit the database size if that is an issue