Security

Password Policy: Why Periodic Password Rotation Weakens Security

If you're forced to change your password every 90 days, this password policy reduces security rather than increasing it. See what NIST says and what to replace it with.

Security

A user messages support saying "your password has expired, you need to change it," and they set the new password to Company@1403. Three months later, the same password with a different number. If this pattern looks familiar, the problem isn't the user; it's the password policy you wrote. Forcing periodic password changes, which was considered the gold standard for years, is now explicitly not recommended in NIST SP 800-63B. The reason is simple: under pressure, people don't make passwords stronger, they just make them more guessable.

What a Periodic Password Policy Actually Breaks

When you enforce mandatory changes every 60 or 90 days, three predictable things happen. First, the incremental pattern: Summer1403! becomes Summer1403!!. Second, rotation between two or three old passwords the user keeps on their phone or in a notebook. Third, a flood of "forgot password" requests that itself opens an attack channel.

Measurements confirm this too. In analyses of leaked password sets, a significant portion of active passwords were exactly the old passwords with one extra character at the end. An attacker who once obtained your old password from a leaked database tries dozens of variants with a simple script. Their success rate is high, because your own policy helped them.

A point that's rarely mentioned: mandatory rotation also has an operational cost. Every password rotation across internal services means updating .env files, CI secrets, database connections, and API tokens. If this is done halfway, the old password remains somewhere and you think you've changed it.

What NIST Exactly Says

SP 800-63B has three specific recommendations that conflict with the common practice of many Iranian panels:

  • Don't force periodic password changes. Change is only necessary when there's evidence of a breach.
  • Prefer length over compositional complexity. A 20-character passphrase is stronger than P@ssw0rd!.
  • Check passwords against lists of leaked and common passwords, not against a simple "uppercase + number + symbol" pattern.

The practical translation is this: instead of putting a hurdle in front of the user every three months, block bad passwords once at the moment of registration. This is both cheaper and more effective.

Practical Alternative: What to Implement in Code

Leaked Password Blocklist

The simplest implementation is checking the entered password against lists like Have I Been Pwned. This API works with k-anonymity: you only send the first five characters of the password's SHA-1 hash, and the rest of the comparison happens on your side. The full password never leaves your server.

# Example with curl for manual testing
echo -n "password123" | sha1sum | cut -c1-5
# Output e.g.: 482c8
curl -s https://api.pwnedpasswords.com/range/482C8 | grep -i "rest of hash"

If the password is in the list, reject the registration and say "this password has appeared in previous breaches." The user won't get angry, because they understand the reason.

Minimum Length and Removing Compositional Rules

Set a minimum of 12 characters, and set the maximum at 64 or more (not 16; a short limit pushes users toward shorter passwords). Allow spaces and Unicode characters. And more importantly: never manipulate the password with trim() or Unicode normalization before hashing, otherwise the user won't be able to log in even with the correct password.

Two-Factor Authentication Instead of Password Rotation

If you're worried about password leaks, the correct answer is TOTP or a hardware key, not mandatory rotation. With 2FA, even a leaked password won't work on its own. For server admin access, we've explained the combination of public keys and disabling password login step by step in SSH Security; From Changing the Port to fail2ban and Public Keys.

Where People Get It Wrong

A common mistake I've actually seen: the team enforces a strict password policy on the user panel, but leaves the database password and API keys in a config.php file inside the web server root. The sign is obvious too; in the access log, GET /config.php or GET /.env requests are recorded with a 200 code. That means the attacker doesn't even bother with user passwords. A strict password policy on the front door, when the back door is open, is just a cost.

Second mistake: forcing password changes with no way for secure recovery. The result is that users send the password in team chat. If this pattern looks familiar, read Password Management in Teams; Why Sharing in Chat Is Forbidden? and set up a real password manager.

Comparing the Two Approaches

CriterionMandatory Periodic RotationLength + Breach Check + 2FA
Real impact on securityLow, even negativeHigh
Load on supportHigh (password recovery)Low
User reactionCircumventing the policyReasonable acceptance
Implementation costAlmost zeroOne-time coding

If I had to choose, I'd go with the second approach. The only condition that makes the first defensible is if the password has actually been leaked or the account has high-level access and you haven't set up 2FA yet. And even then, once, not every 90 days.

What to Do When a Password Is Leaked

A policy without a response process is half-baked. The correct path is:

  1. Invalidate all active sessions of that user, not just change the password. JWT tokens and database sessions are invalidated separately.
  2. Search the audit log for what happened since the breach. If you don't have an audit log or it's tamperable, What Is an Audit Log and How Do We Keep It Intact? is the starting point.
  3. Rotate API keys and service tokens too. A password is just one of the ways in.
  4. Tell the user what happened. Covering it up means next time they won't keep the password in a safe place.

For employee access from outside, instead of opening the database port to the internet, use a tunnel; Comprehensive Guide to Enterprise VPN for Secure Employee Access covers this exact scenario.

Things That Get Forgotten

Hashing passwords with plain MD5 or SHA-1 is still seen in some legacy projects. If your database leaks, these hashes are broken in a few hours with a GPU. Use Argon2id or bcrypt with an appropriate cost, and don't hardcode the parameters so they can be increased later.

Rate limiting is also serious. Without a rate limit on the login endpoint, the password blocklist is useless because an attacker can make thousands of guesses. A simple limit like 10 attempts per 15 minutes per IP and per account shuts down most automated attacks. If attack traffic exceeds the limit, DDoS protection is the next layer.

And one operational point: write any change to the password policy in your own documentation and knowledge base, not just in an email. Six months later, whoever needs to enforce the policy will read those same docs.

If you work on a dedicated or cloud server and want to set up authentication and monitoring layers all in one place without confusion, ServerNet's server security services cover this path. But before anything else, remove that mandatory rotation rule from your user panel. It's the only change you can make today that will increase security.

Frequently Asked Questions

Is periodic password rotation completely forbidden?

No, it's not forbidden, but it's not recommended as a default policy. Since 2017, NIST has said in SP 800-63B to enforce mandatory rotation only when there's evidence of a breach. If your organization has a regulatory requirement, at least lengthen the interval and make 2FA mandatory at the same time.

What should the minimum password length be?

12 characters for regular accounts and 16 characters or more for administrative accounts. More important than the number is allowing long passphrases and checking passwords against breach lists. Also don't set the maximum length limit below 64 characters.

How do I know if my users' passwords have been leaked?

Check with the leaked password list API at login or registration time, and look in the audit log for successful logins from unknown IPs. If you keep logs tamperable, this detection is almost useless.

Is a team password manager a replacement for a password policy?

It's a complement to it, not a replacement. A password manager prevents password sharing in chat and simplifies rotating service passwords, but decisions about length, 2FA, and breach response are still your responsibility.

ServerNet Support

ServerNet engineering & editorial team — specialists in infrastructure, networking and web hosting.

Security Services
Share:

Comments 0

No comments yet — be the first!

Leave a comment

Related service

Security Services

Penetration testing by OSCP-certified specialists, infrastructure hardening and 24/7 security monitoring — reports managers understand and engineers can act on.