Description
pam_pwquality (package libpam-pwquality) checks every new password when it is set with
passwd. Its settings live in /etc/security/pwquality.conf and /etc/security/pwquality.conf.d/:
minlen: minimum length;minclass: minimum number of character classes (lower, upper, digit, other);difok: characters that must differ from the old password;maxrepeat/maxsequence: longest run of the same or consecutive characters;dictcheck: reject words from the cracklib dictionary;enforce_for_root: apply the rules when root sets a password too;enforcing: reject a weak password instead of only printing a warning (default 1).
Without libpam-pwquality, Ubuntu only applies the weak built-in obscure check of pam_unix.
Installing the package enables the module in /etc/pam.d/common-password through pam-auth-update.
Rationale
Length is what makes a password resist guessing. The other rules reject the patterns attackers try first (repeated characters, sequences, dictionary words, a one-character change).
Impact
Users must pick passwords that follow the rules when they next change them. Existing passwords are not checked.
Setting
| Location | /etc/security/pwquality.conf.d/60-cirsec.conf |
| Default | Module not installed |
| Recommended | minlen >= {{ minlen }}, minclass >= {{ minclass }}, difok >= 2, maxrepeat <= 3, maxsequence <= 3, dictcheck, enforce_for_root, enforcing not 0 |
Parameters
| Parameter | Core | Server | Server hardened | Desktop | Desktop hardened | Bounds |
|---|---|---|---|---|---|---|
minleninteger. Minimum password length. | 14 | 14 | 16 | 14 | 16 | 8 to 64 |
minclassinteger. Minimum number of character classes. | 3 | 3 | 3 | 3 | 3 | 0 to 4 |
The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.
Audit
dpkg -s libpam-pwqualitymust show the package installed./etc/pam.d/common-passwordmust contain apam_pwquality.soline.- The last value of each setting in
/etc/security/pwquality.confthen/etc/security/pwquality.conf.d/*.confmust be:minlen>= {{ minlen }},minclass>= {{ minclass }},difok>= 2,maxrepeatandmaxsequencebetween 1 and 3,dictchecknot 0, andenforce_for_rootpresent. - Neither the last
enforcingvalue of these files nor thepam_pwquality.soline isenforcing=0.
Automated: every check must pass. Scanners report each check by its id.
package
name: libpam-pwquality
state: installed
module
pam_pwquality is in the password stack.
path: /etc/pam.d/common-password
pattern: ^\s*password\s+.*pam_pwquality\.so
settings
Effective pwquality settings.
script: |
files="/etc/security/pwquality.conf $(ls /etc/security/pwquality.conf.d/*.conf 2>/dev/null)"
get() { cat $files 2>/dev/null | sed -n "s/^[[:space:]]*$1[[:space:]]*=[[:space:]]*\([-0-9]*\).*/\1/p" | tail -n 1; }
minlen=$(get minlen) minclass=$(get minclass) difok=$(get difok)
maxrepeat=$(get maxrepeat) maxsequence=$(get maxsequence) dictcheck=$(get dictcheck)
root=$(cat $files 2>/dev/null | grep -c '^[[:space:]]*enforce_for_root')
echo "minlen=${minlen:-9} minclass=${minclass:-0} difok=${difok:-1} maxrepeat=${maxrepeat:-0} maxsequence=${maxsequence:-0} dictcheck=${dictcheck:-1} enforce_for_root=$root"
[ "${minlen:-9}" -ge "$CB_MINLEN" ] && [ "${minclass:-0}" -ge "$CB_MINCLASS" ] && [ "${difok:-1}" -ge 2 ] \
&& [ "${maxrepeat:-0}" -ge 1 ] && [ "${maxrepeat:-0}" -le 3 ] \
&& [ "${maxsequence:-0}" -ge 1 ] && [ "${maxsequence:-0}" -le 3 ] \
&& [ "${dictcheck:-1}" != 0 ] && [ "$root" -gt 0 ]
enforcing
pwquality rejects weak passwords instead of only warning.
script: |
files="/etc/security/pwquality.conf $(ls /etc/security/pwquality.conf.d/*.conf 2>/dev/null)"
e=$(cat $files 2>/dev/null | sed -n 's/^[[:space:]]*enforcing[[:space:]]*=[[:space:]]*\([0-9]*\).*/\1/p' | tail -n 1)
l=$(grep -E '^[[:space:]]*password[[:space:]].*pam_pwquality\.so.*enforcing=0' /etc/pam.d/common-password)
echo "enforcing=${e:-1 (default)}${l:+; module line: $l}"
[ "${e:-1}" != 0 ] && [ -z "$l" ]
Remediation
- Run
apt install libpam-pwquality. - Create
/etc/security/pwquality.conf.d/60-cirsec.conf:minlen = {{ minlen }} minclass = {{ minclass }} difok = 2 maxrepeat = 3 maxsequence = 3 dictcheck = 1 enforce_for_root enforcing = 1 - Remove any
enforcing=0option from thepam_pwquality.soline.
| Restart | none |
| Disruption | low |
Rollback
Delete /etc/security/pwquality.conf.d/60-cirsec.conf. Remove the package to drop the module.
package
Generated from check package: the engine writes the fix for every output, it sets the expected value and the check runs again after.
settings
f=/etc/security/pwquality.conf.d/60-cirsec.conf
cb_backup "$f"
mkdir -p /etc/security/pwquality.conf.d
printf '%s\n' '# Written by CIRSEC Baselines CB-UBU-AUTH-010' "minlen = $CB_MINLEN" "minclass = $CB_MINCLASS" \
'difok = 2' 'maxrepeat = 3' 'maxsequence = 3' 'dictcheck = 1' 'enforce_for_root' 'enforcing = 1' >"$f"
chmod 644 "$f"
Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.
References
- pam_pwquality(8), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- pwquality.conf(5), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- NIST SP 800-63B - Digital Identity Guidelines, Authentication NIST, standard, accessed 2026-10-19
- ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R31) ANSSI, guide, accessed 2026-10-19
Mappings
| Framework | ID | Relation | Note |
|---|---|---|---|
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R31 | equivalent | |
| NIST SP 800-53 Rev. 55.1.1 | IA-5(1) | partial |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
| Taxonomy | ID |
|---|---|
| MITRE ATT&CK | T1110 |
People and lifecycle
| Authors |
|
| Verified | 2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Weak and short passwords rejected, strong one accepted with pamtester; minlen 14 core, 16 server-hardened; enforcing checked; pwquality.conf.d read. |
| Verified | 2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Weak and short passwords rejected, strong one accepted with pamtester; minlen 14 core, 16 server-hardened; enforcing checked; pwquality.conf.d read. |
| Verified | 2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Weak and short passwords rejected, strong one accepted with pamtester; minlen 14 core, 16 server-hardened; enforcing checked; pwquality.conf.d read. |
| Verified | 2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. Weak and short passwords rejected, strong one accepted with pamtester; minlen 14 core, 16 server-hardened; enforcing checked; pwquality.conf.d read. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-19, 2026-10-19 |
| Translations | fr |