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_pwqualityand lockout withpam_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:
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:
- Store only a hash.
- Make the hash slow on purpose, so that trying millions of guesses costs time.
- 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:
A friendlier view of the same fields:
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:
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 -Eends the account;chage -Mages the password;chage -d 0forces a change now.- PAM is the chain every login passes through:
pam_pwqualityenforces quality,pam_faillockenforces 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/shadowfile
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.