Set Root Lockout Time for Failed Password Attempts
Set root_unlock_time to at least 60 seconds so that, when the root account is locked by pam_faillock after repeated failed authentications, it stays locked long enough to make password guessing impractical instead of being immediately retryable.
Checked against the content of a persistent configuration file, the source of truth that survives reboots.
A mapping is a cross-reference to where each standard places this requirement, anchored and cross-validated, not a claim of equivalence. A passing check is evidence toward these references, how to read it.
Why this rule matters
By limiting the number of failed logon attempts the risk of unauthorized root access via password guessing, otherwise known as brute-forcing, is reduced. Limits are imposed by locking the account.
What Pavois checks
Pavois greps root_unlock_time across /etc/security/faillock.conf and the /etc/security/faillock.conf.d/ drop-in directory, keeps the last occurrence (tail -1, the one pam_faillock itself would honour) and requires the value to be >= 60. Auditing the whole drop-in set, not just the main file, is what catches a lower value re-introduced by a later fragment. Note that root_unlock_time is only meaningful if pam_faillock is actually in the PAM stack and root lockout is enabled (even_deny_root), which are separate controls.
describe command('v=$(grep -rh \'^[[:space:]]*root_unlock_time[[:space:]]*=\' /etc/security/faillock.conf /etc/security/faillock.conf.d/ 2>/dev/null | tail -1 | grep -oE \'[0-9]+\'); { [ -n "$v" ] && [ "$v" -ge 60 ] && echo ok; } || echo ko') do
its('stdout.strip') { should eq 'ok' }
endHow to verify it is applied
Read back the resolved directive:
grep -rE '^[[:space:]]*root_unlock_time' /etc/security/faillock.conf /etc/security/faillock.conf.d/
/etc/security/faillock.conf:root_unlock_time = 60
The live counter is inspected with faillock --user root, which lists the recorded failures and the time they occurred; faillock --user root --reset clears them.
Inspect & investigate
Lockouts are logged by PAM in /var/log/auth.log (Debian/Ubuntu) or journalctl -u sshd (RHEL family):
sshd[4567]: pam_faillock(sshd:auth): Consecutive login failures for user root account temporarily locked
When pam_faillock is configured with the audit option, the failed attempts are also recorded by auditd; grep the raw log rather than relying on ausearch:
grep -E 'ANOM_LOGIN_FAILURES|RESP_ACCT_LOCK' /var/log/audit/audit.log
Remediation
The Pavois harden plan uses a keyval remediation that writes root_unlock_time = 60 into /etc/security/faillock.conf. This resource is aggregated: Pavois rewrites the whole file with the complete set of faillock keys it manages (deny, unlock_time, even_deny_root, audit, …), so the file always reflects the full desired state rather than a patched line. Any hand-added key in that file is therefore overwritten at the next apply, and a plan generated from a stale scan can drop a setting you expected to keep: always regenerate the plan from a current scan.
Pavois applies this with its own harden engine, the plan below, not a shell script:
| file | /etc/security/faillock.conf |
|---|---|
| key | root_unlock_time |
| resource | keyval |
| value | 60 |
pavois harden plan localwhere the target is local, a user@host SSH alias, or a container , Docs
Impact & precautions
Without a root unlock delay, an attacker with access to a root login prompt can retry passwords without any cost. The reverse configuration is the real danger: combined with even_deny_root, a root_unlock_time of 0 means root is locked permanently and can only be recovered from a physical console, single-user mode or a rescue boot. Even the recommended 60 seconds turns repeated failures into a denial of service on root (an attacker can keep the account locked by failing on purpose). Before applying, keep a root session or an out-of-band console open, keep an unprivileged sudo-capable account available as an alternate path, and remember faillock --user root --reset clears the counter immediately.
Standards mapping
| Standard | Reference | Type | Version | Confidence |
|---|---|---|---|---|
| CIS | 5.3.3.1.3 | direct | per OS, see the benchmark table | high |
Each reference is a cross-reference anchored in the upstream benchmark and cross-validated against the SCAP Security Guide and ansible-lockdown, not a claim of equivalence. Direct = a prescriptive, line-level requirement; supporting = an abstract control family (NIST) the check provides evidence toward. How to read a mapping.