4

By "typical", I mean in terms of the value of the data and how hard attackers are likely to try to breach it, as opposed to one that's guarding data sensitive enough that it's worth significant sacrifices to user convenience.

I'd like to know what are considered modern best practices for what to allow users to set their password to.

My current state of knowledge on this is as follows. Password composition rules that I've heard to be good ideas include:

  • Minimum length of 8 characters
  • Disallow common passwords
  • Disallow passwords that have been found in data breaches

Password rules that I've heard to be bad ideas include:

  • Minimum length above 8 characters
  • Maximum length below that imposed by the web server
  • Restrictions on which characters can be used
  • Requirements to use certain combinations of characters

Password rules that I know are sometimes used, but am unsure whether they're good or bad ideas include:

  • Disallow passwords too similar to other user attributes, as in Django's UserAttributeSimilarityValidator
  • Minimum estimated entropy according to some heuristic algorithm
3

Your main three are good, actually the first two are sufficient provided the implementation technique is solid.

Don't allow high speed brute force attempts! Three to five failed attempts in under a minute or two should completely block the IP address for 30-60 minutes. That's short enough for a human to wait out for legitimate errors but long enough to effectively shutdown most brute force attempts. A highly motivated low speed attack over weeks to months is unlikely but even that could be handled with a total error count detection, but realistically this is overkill. Just block high speed.

Make sure you don't create a SQL-injection mechansim. Actually this applies regardless of complexity.

There are other more extreme security measures you could take, but these two address the most common by far attack methods.

The "Best Practice" emphasis on extreme password complexity is misguided in my opinion. Bank ATMs successfully use trivial pins by blocking brute force attempts.

  • The anti-brute-forcing thing isn't really a "password policy" (and SQLi prevention certainly isn't!), but leaving that aside: your approach, at least implemented naively, gives arbitrary unauthenticated users the ability to launch a denial-of-service attack on arbitrary legitimate users. Don't do that. Instead, require a CAPTCHA after the first attempt(s) fail(s), or disable login for that user and email them a one-time-use token (which can be renewed using their credentials) to log in with. – CBHacking Mar 15 at 1:12
  • 1
    Block the IP address not the account to avoid denial of service. – user10216038 Mar 15 at 16:47
  • ATMs are a little different. There is a lot more risk in targeting an ATM compared to a web app. Someone who steals even < $100 from a bank will be more wanted and face steeper consequences than someone that causes trouble on your website. Banks and ATMs have better physical security and surveillance tools. Online banking is different, but banks have teams to respond to things and fraud combating tools that you don't. (Not that banks always do online security well.) To make up for the things banks have that websites don't, it makes sense to use stronger passwords. – Future Security Mar 15 at 18:44
  • @user10216038 Still a problem on widely-shared NAT blocks (see en.wikipedia.org/wiki/Carrier-grade_NAT) where one malicious user could DoS a significant chunk of an ISP's customers, but probably less bad than blocking the user, yes. – CBHacking Mar 15 at 21:22
  • ATMs also have what amounts to two-factor authentication already, with the PIN being the second factor; the primary defense of a debit card is not the card's PIN but the fact that you have physical possession of the card (this is especially true of chip-and-PIN cards). Also, the ability to use the card at any ATM (or probably at any point-of-sale) will be blocked if the wrong PIN is entered a few times, which successfully makes stealing debit cards problematic without massively inconveniencing legit users. – CBHacking Mar 15 at 21:25
3

You asked:

I'd like to know what are considered modern best practices for what to allow users to set their password to.

My go-to for this is NIST Special Publication 800-63B: Digital Identity Guidelines Authentication and Lifecycle Management, section 5.1.1 Memorized Secrets.

Here are some relevant excerpts from that document:

5.1.1.1 Memorized Secret Authenticators

Memorized secrets SHALL be at least 8 characters in length if chosen by the subscriber. Memorized secrets chosen randomly by the CSP or verifier SHALL be at least 6 characters in length and MAY be entirely numeric. If the CSP or verifier disallows a chosen memorized secret based on its appearance on a blacklist of compromised values, the subscriber SHALL be required to choose a different memorized secret. No other complexity requirements for memorized secrets SHOULD be imposed. A rationale for this is presented in Appendix A Strength of Memorized Secrets.

...

5.1.1.2 Memorized Secret Verifiers

When processing requests to establish and change memorized secrets, verifiers SHALL compare the prospective secrets against a list that contains values known to be commonly-used, expected, or compromised. For example, the list MAY include, but is not limited to:

  • Passwords obtained from previous breach corpuses.
  • Dictionary words.
  • Repetitive or sequential characters (e.g. ‘aaaaaa’, ‘1234abcd’).
  • Context-specific words, such as the name of the service, the username, and derivatives thereof.

Tools like zxcvbn (github.com/dropbox/zxcvbn. demo at lowe.github.io/tryzxcvbn, thanks @fread2281) include dictionary-based blacklists and checks for common sequences. For non-government applications, most people consider this sufficient.

To meet the first bullet, you'll need a comprehensive blacklists of compromised passwords -- the best one is the ~12 gb database maintained at haveibeenpwned.com.

To meet the 4th bullet, you'll need to maintain your own blacklist of terms that have special meaning within your app (name of the service, username, roles within your app like "admin" or "instructor", etc)

As you point out, "complexity rules" like One Upper, One Lower, One Symbol are going out of style and should not be used. As the mandotory XKCD points out, "Through 20 years of effort, we've successfully trained everyone to use passwords that are hard for humans to remember, but easy for computers to guess."

1

Your first three, plus the "Disallow passwords similar to other attributes", is a good policy. I personally favor passwords longer than 8 characters in nearly all situations, but that's because I use passphrases for anything where I can't (conveniently) just use LastPass, and don't see any reason to allow something so short as 8 characters; apparently a lot of the world disagrees with me, though. I don't think I've seen an argument for "you shouldn't require the password be longer than 8 characters", though, just that 8 is the minimum level that you should require (and you might want to require more).

The "Disallow similar" rule should ideally also be extended to site attributes (disallow the site name or URL, or prominent strings); this will break people who use a "unique password per site" scheme of "universal strong password + site name", but that is a bad scheme and shouldn't be supported anyhow. Calculated entropy is an interesting notion but I don't think it's a good idea unless the site is very sensitive; blocking passwords that have been used before will suffice to prevent the problems you're likely to see there.

Speaking of which, feel free to be really strict with the "block passwords that have been used elsewhere / breached" thing. I've seen at least one site (one whose whole purpose is to authenticate other services, in fact!) decide to only block the 10,000 most common passwords, and a ton of those were shorter than the site's minimum (as in, their "top 10,000" list included a bunch of stuff like "11111") or otherwise would have already been invalid, so the effective block list was tiny and obvious "rules lawyer" approaches to their password policy (which was, shall we say, not in line with NIST recommendations) like "P@ssw0rd" would be permitted.

There's of course a lot of other auth-related stuff that is outside the scope of a "password policy" (like MFA or anti-brute-force), but I do want to mention one other (pair of related) thing(s): Do not force password rotations upon your users (though obviously they must be possible), but if there is any reason to expect a user's password to be compromised (either through your site or a third-party service), you should force a password reset on all affected accounts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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