Skip to content

Account and password policies

Practical 5.3 account-and-password-policies-annex.pdf · PDF

You forgot the password of some website. You click "Forgot password?" and... they e-mail you your old password, in plain text. That should scare you. It means somebody at that company could read it. And so could anyone who breaks in.

On a well-built system, nobody can read your password. Not the website, not the administrator, not even root on your own deb-lab. Today you find out how that is possible, and you write the rules that keep the Tramuntana Apps accounts safe: how long a password must be, when an account ends, and what happens after too many wrong guesses.

What you will learn

  • Why the system stores a salted hash, not the password, and how to read a line of /etc/shadow
  • Set ageing and expiry on an account with chage, and tell "the password expires" from "the account expires"
  • Enforce password quality with pam_pwquality and lockout with pam_faillock
  • Set the same kind of policy on Windows with net accounts
  • Why the old rule "capitals, digits, symbols, change it every 90 days" made passwords worse

Where is your password?

Try it as administrator in deb-lab:

sudo grep "^marta:" /etc/shadow
marta:$y$j9T$6XiHvr7lOdjVw/E6hDMGJ.$/cFdZqZud1/kAcqaVBxfQzSzlpNPe9kQl2xQf4tX.AD:20731:0:99999:7:::

Everyone in class knows marta's lab password is tramuntana. Find it in that line. You can't: it is not there. The system does not know the passwords of its own users. It knows their fingerprints.

Hash: a fingerprint of the password

A hash function turns any text into a fixed-size fingerprint (the hash). The same text always gives the same fingerprint, and there is no way back from the fingerprint to the text.

You have already used one: sha256sum to check an ISO. Look what happens when one letter changes:

echo -n tramuntana | sha256sum     # b4f05ee0e2c4e541...
echo -n tramuntanA | sha256sum     # 7b12a65f1454106c...

Completely different fingerprints. So at login the system never compares passwords. It hashes what you type and compares fingerprints:

flowchart LR
    K["<b>You type</b><br>your password"] --> H["<b>Hash function</b><br>takes the fingerprint"]
    H --> C{"<b>Equal?</b>"}
    S["<b>/etc/shadow</b><br>the stored fingerprint"] --> C
    C -->|"yes"| IN["You are in"]
    C -->|"no"| OUT["Login incorrect"]

Careful: a hash is not encryption

People say "the password is encrypted in /etc/shadow". It is not. Something encrypted can be decrypted with a key. A hash has no key and no way back. An administrator can replace your password, never read it. A website that e-mails you your old password did not hash it.

Two stories: 1979 and 2009

In 1979, at Bell Labs, Robert Morris and Ken Thompson (the same Thompson who added the pipe to Unix) published Password Security: A Case History. Early Unix had kept passwords in clear text. Their fix has three parts, and all three are still in your deb-lab:

  1. Store only a hash.
  2. Make the hash slow on purpose, so that trying millions of guesses costs time.
  3. Add salt.

Thirty years later, in December 2009, the company RockYou was broken into. It kept the passwords of 32 million accounts as plain text. The whole list ended up on the internet. The most used password, about 290,000 times: 123456. That list is still the first thing an attacker tries today.

Salt: same password, different fingerprint

A salt is a random value, different for every account, mixed into the password before hashing and stored next to the result.

Marta and joan both use tramuntana, yet their lines in /etc/shadow are different: different salts. Why does it matter? Without salt, an attacker hashes 123456 once and compares it with every account in the file. With salt, the work must be repeated for every single account.

You can watch salt in action:

openssl passwd -6 tramuntana                 # run it twice: two different lines
openssl passwd -6 -salt abcdefgh tramuntana  # run it twice: identical lines

Each run picks a new random salt, unless you fix it yourself. (-6 is SHA-512, an older method; Debian uses yescrypt today.)

Reading /etc/shadow

Fields are separated by :, like in /etc/passwd:

Field In marta's line Meaning
1 marta User name
2 $y$j9T$6XiH...$/cFd... The salted hash
3 20731 Day of the last password change, counted from 1 January 1970
4 0 Minimum days before the password may be changed again
5 99999 Maximum days the password is valid (99999 = never expires)
6 7 Days of warning before it expires
7–8 (empty) Inactive days allowed, and the day the account expires

Field 2 has its own parts, between $ signs: y is the method (yescrypt, Debian's default since Debian 11), j9T its cost settings, then the salt, then the hash.

To turn field 3 into a real date:

date -d "1970-01-01 +20731 days" +%F

A friendlier view of the same fields:

sudo chage -l marta

On a fresh Debian, it says Password expires : never and Account expires : never. Debian's default is no expiry.

Three kinds of rule

A password policy is the set of rules the system enforces on passwords, so that security does not depend on everyone being careful. An account policy does the same for accounts: when they end, when they lock.

Rule Question Debian 13 Windows 11
Ageing / expiry How long is it valid? chage; defaults in /etc/login.defs net accounts /maxpwage · net user x /expires
Quality Which passwords are accepted? pam_pwquality, /etc/security/pwquality.conf net accounts /minpwlen; Local Security Policy
Lockout What happens after wrong guesses? pam_faillock, /etc/security/faillock.conf net accounts /lockoutthreshold

PAM: one chain for every door

On Linux, every program that asks for a password (the login screen, su, sudo, passwd) passes through the same chain of small modules:

PAM (Pluggable Authentication Modules) is the chain of modules every Linux program uses to check passwords. It is configured in /etc/pam.d/.

Add a module to the chain and every door obeys it. Break the chain and every door stays shut, including sudo. That is why, before touching PAM, you always take a snapshot of the VM and keep a second terminal open with sudo -i: it is your way back in.

The man who regretted his rules

In 2003, Bill Burr, a manager at NIST (the US National Institute of Standards and Technology), wrote eight pages of advice: use capitals, digits and symbols; change your password every 90 days. Every company and website on Earth copied it.

What people actually did: Password1!, then Password2!, then a sticky note on the screen. In 2017, retired, Burr told the Wall Street Journal: "Much of what I did I now regret." NIST rewrote the rules that same year. The current text is SP 800-63B Revision 4 (2025):

2003 habit NIST today
8 characters is enough At least 15 when the password is the only factor (8 if a second factor is also required); accept at least 64
Must mix capitals, digits, symbols Shall not impose composition rules
Change it every 90 days Shall not require periodic change; force a change only on evidence of compromise
Hints and "first pet" questions Shall not use them
Any password that fits the rules Check it against a blocklist of common and leaked passwords
(nothing) Limit failed attempts: never more than 100 in a row

Length beats tricks

Tr4mun! has seven characters and every symbol family on the keyboard; a computer guesses it quickly. quatre gats negres dormen is four everyday words: far harder to guess, and you already remember it. A long passphrase wins.

Practical 5.3: a policy for Tramuntana Apps

The scenario: everybody in your class knows the four lab passwords of Tramuntana Apps, so they are compromised. The boss wants long passwords, no silly ones, an intern's account that ends with his contract, and no unlimited guesses. The full steps are on the Practical 5.3 sheet; here is what each one means.

Ageing and expiry with chage

sudo chage -E 2027-06-30 pau     # pau's ACCOUNT ends with his internship
sudo chage -d 0 marta            # marta must change her password at next login
sudo chage -l pau                # Account expires : Jun 30, 2027
sudo chage -l marta              # Last password change : password must be changed

Careful: two different clocks

chage -E ends the account: contract over, nobody enters, whatever the password. chage -M would end the password: it must be changed. Today you use -M nowhere. That is the NIST decision: no periodic change. chage -d 0 forces a change because there is evidence of compromise.

Quality with pam_pwquality

sudo apt install libpam-pwquality
sudo nano /etc/security/pwquality.conf    # change "# minlen = 8" to "minlen = 15"
grep pwquality /etc/pam.d/common-password

The last line shows password requisite pam_pwquality.so retry=3: the installer added the module to the PAM chain. Now test it with su - marta, which forces the change:

You try The system answers
Tr4mun! BAD PASSWORD: The password is shorter than 15 characters
123456789012345 BAD PASSWORD: The password fails the dictionary check - it is too simplistic/systematic
quatre gats negres dormen Accepted

After three refused tries, passwd gives up (retry=3): just start su - marta again.

Root is warned, not stopped

Run sudo passwd pau and type 1234. You get the same BAD PASSWORD warning... and then it is accepted. The policy binds users, not the administrator, unless enforce_for_root is switched on in pwquality.conf.

Lockout with pam_faillock

The trickiest part, done only with the snapshot taken. You edit /etc/pam.d/common-auth so the chain reads:

auth  required                    pam_faillock.so preauth
auth  [success=2 default=ignore]  pam_unix.so nullok
auth  [default=die]               pam_faillock.so authfail
auth  requisite                   pam_deny.so
auth  sufficient                  pam_faillock.so authsucc
auth  required                    pam_permit.so

Three lines are new, and one number changed: success=2 (it was 1). When the password is right, PAM now jumps over two lines instead of one. Forget that change and you lock every door. You also add account required pam_faillock.so to /etc/pam.d/common-account, and set deny = 3 and unlock_time = 600 in /etc/security/faillock.conf.

Test: three wrong passwords in su - joan, then the right one:

The account is locked due to 3 failed logins. (10 minutes left to unlock)
sudo faillock --user joan            # lists the three failures
sudo faillock --user joan --reset    # empties the list: joan can enter again

Careful: three wrong sudo passwords now lock your own account too. Your open root terminal fixes it: faillock --user student --reset.

The same on Windows

In win11, open Terminal (Admin):

net accounts
net accounts /minpwlen:14 /maxpwage:unlimited /lockoutthreshold:5
net accounts
net user marta *

net accounts shows the current values first. After the change, net user marta * refuses a short password. Why 14 and not 15? Try /minpwlen:15 and read the error: the tool only accepts up to 14. The tool is older than the advice. Going further needs Local Security Policy (secpol.msc), which Windows Home does not have.

Does the policy follow NIST?

NIST says Tramuntana Apps Where
15 characters minimum Yes minlen = 15 (Windows: 14)
No composition rules, no periodic change Yes Maximum days stays 99999
Change on evidence of compromise Yes chage -d 0
Blocklist Partly The dictionary check catches only the obvious ones
Limit failed attempts Yes deny = 3 to test fast; 5 to 10 is usual

Careful: lockout does not make guessing impossible

Lockout only slows down guessing at the door. If an attacker steals a copy of the hashes, they attack it on their own computer, with no lockout at all. That is why the password itself must be long. And even a perfect password can be stolen or phished, so important accounts add a second factor (a code on your phone, a security key). More in Unit 6.

A policy is a decision written where the machine can enforce it. In your report, every line you set needs a reason.

Key takeaways

  • Linux stores a salted hash of each password in /etc/shadow, never the password. A hash has no way back; the admin can replace a password, not read it.
  • The salt makes equal passwords give different hashes, so attackers must work account by account.
  • chage -E ends the account; chage -M ages the password; chage -d 0 forces a change now.
  • PAM is the chain every login passes through: pam_pwquality enforces quality, pam_faillock enforces lockout. Snapshot first.
  • Windows sets the same rules with net accounts (/minpwlen, /maxpwage, /lockoutthreshold).
  • NIST SP 800-63B today: long passwords (15+), no composition rules, no periodic change, a blocklist, limited attempts.

Quick check

1. What does /etc/shadow keep for each user?
  • A salted hash of the password
  • The password in plain text
  • The password, encrypted with root's key
  • Nothing at all about the password

/etc/shadow keeps a salted hash: a fingerprint with no way back. At login the system hashes what you type and compares fingerprints. There is no key that would let root decrypt it.

2. What is the salt for?
  • It makes equal passwords give different hashes
  • It makes the password longer to type
  • It lets root read the password when needed
  • It compresses the /etc/shadow file

A salt is a random value per account mixed in before hashing. Two users with tramuntana get different hashes, so an attacker cannot hash a guess once and compare it with everybody.

3. What does NIST recommend today about changing passwords?
  • Only when there is evidence of compromise
  • Every 30 days, without exception
  • Every 90 days, without exception
  • Once a year, on a fixed date

NIST SP 800-63B says systems shall not require periodic changes: people just make Password1! into Password2!. A change is forced only when the password may be known, as with chage -d 0.

4. Which password is the hardest to guess?
  • quatre gats negres dormen
  • Tr4mun!
  • P@ssw0rd1
  • 123456789012345

Length beats tricks. A passphrase of four everyday words is long and unusual. Tr4mun! and P@ssw0rd1 are short with predictable substitutions, and 123456789012345 fails the dictionary check.

5. Laia's internship ends on 31 March 2027. Which command makes her account stop working that day?
  • sudo chage -E 2027-03-31 laia
  • sudo chage -d 0 laia
  • sudo chage -M 31 laia
  • sudo usermod -aG dev laia

chage -E sets the day the account expires: after it, nobody enters, whatever the password. -d 0 only forces a password change, and -M limits how long the password is valid.

6. As root you run sudo passwd pau and type 1234, with minlen = 15 active. What happens?
  • You get a warning, but the password is accepted
  • The password is refused and nothing changes
  • PAM locks pau's account for ten minutes
  • The system asks for a second factor

pam_pwquality warns root but does not stop it. The policy binds normal users; it binds the administrator only if enforce_for_root is set in pwquality.conf.

7. A company has lockout after 5 wrong attempts. An attacker steals a copy of /etc/shadow. Select the two that are true.
  • The lockout does not slow down guesses made on the attacker's own computer
  • A long passphrase still makes cracking the hashes very slow
  • The attacker can now read every password in plain text
  • The salts let the attacker crack all accounts at once

Lockout only protects the login door. Offline, the attacker can try guesses as fast as their computer allows, so length is what protects you. The hashes have no way back, and salt forces the work account by account.

Now you know who can get in. Next: what each user may do with each file once inside, in Linux permissions.