Local account drift can turn a routine Linux review into an access-control problem when old users, service accounts, or unexpected administrator grants remain on a host. Auditing the account database shows which names can log in, which accounts hold privileged identifiers, and which password states need follow-up before a handoff or incident review.
Account records come from the system password database visible through Name Service Switch, while password lock and aging data live in /etc/shadow on systems that use the shadow suite. The local files show login shell, home directory, UID, primary group, and supplementary group membership; directory-backed identities may also appear through getent depending on /etc/nsswitch.conf.
Read /etc/shadow and sudoers data with root privileges only on systems where that access is authorized. Password hashes, account names, home paths, sudo rules, and login sources can identify people or expose privilege paths, so copy only the findings needed for the ticket or audit record.
Related: How to investigate a Linux intrusion
Related: How to show logged-in users in Linux
$ getent passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync ##### snipped ##### ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash analyst:x:1001:1001::/home/analyst:/bin/bash deploy:x:1002:1002::/home/deploy:/bin/bash appsvc:x:1003:1003::/home/appsvc:/usr/sbin/nologin
getent passwd shows the account database visible to system tools. On hosts using LDAP, SSSD, or another NSS source, compare this output with /etc/passwd when the audit must separate local file accounts from directory accounts.
$ grep --extended-regexp '^UID_(MIN|MAX)' /etc/login.defs UID_MIN 1000 UID_MAX 60000
Use these values for the range checks below. Many Debian and Ubuntu systems use 1000 through 60000 for regular users, but local policy can change them.
$ awk -F: '$3 >= 1000 && $3 <= 60000 {printf "%s:%s:%s:%s\n", $1, $3, $6, $7}' /etc/passwd
ubuntu:1000:/home/ubuntu:/bin/bash
analyst:1001:/home/analyst:/bin/bash
deploy:1002:/home/deploy:/bin/bash
appsvc:1003:/home/appsvc:/usr/sbin/nologin
Replace 1000 and 60000 when /etc/login.defs uses different values.
$ sudo ls -ld /home/* drwxr-x--- 2 analyst analyst 4096 Jun 13 21:25 /home/analyst drwxr-x--- 2 deploy deploy 4096 Jun 13 21:25 /home/deploy drwxr-x--- 2 ubuntu ubuntu 4096 Apr 21 15:27 /home/ubuntu
World-writable homes or homes owned by the wrong account can let another local user plant shell startup files, SSH keys, or persistence scripts.
$ awk -F: '($3 < 1000 || $3 > 60000) && ($7 !~ /(nologin|false)$/) {printf "%s:%s:%s:%s\n", $1, $3, $6, $7}' /etc/passwd
root:0:/root:/bin/bash
sync:4:/bin:/bin/sync
Expect root. Other package or service accounts may use narrow commands such as /bin/sync, but any unexpected shell-capable system account needs an owner and purpose.
$ awk -F: '$3 == 0 {printf "%s:%s:%s\n", $1, $6, $7}' /etc/passwd
root:/root:/bin/bash
Any account other than root with UID 0 has root-equivalent privileges and should be treated as a high-severity finding.
$ getent group sudo sudo:x:27:ubuntu,deploy
sudo is the common administrative group on Debian and Ubuntu systems.
$ getent group wheel
No output means the group is absent or has no visible entry in the active group database. wheel is common on RHEL, CentOS, Fedora, and related systems.
$ sudo -l -U deploy
User deploy may run the following commands on server:
(ALL : ALL) ALL
(ALL) NOPASSWD: /usr/bin/systemctl status app.service
Unexpected user-specific rules, broad ALL command grants, or NOPASSWD entries can provide administrative access outside group membership.
$ sudo passwd --status --all root L 2026-04-21 0 99999 7 -1 daemon L 2026-04-21 0 99999 7 -1 bin L 2026-04-21 0 99999 7 -1 sys L 2026-04-21 0 99999 7 -1 ##### snipped ##### ubuntu L 2026-04-21 0 99999 7 -1 analyst L 2026-06-13 0 99999 7 -1 deploy L 2026-06-13 0 99999 7 -1 appsvc L 2026-06-13 0 99999 7 -1
The second field reports P for a usable password, L for a locked password, and NP for no password. A locked password does not necessarily block SSH keys or other authentication tokens.
$ sudo awk -F: '$2 == "" {print $1}' /etc/shadow
No output means no empty shadow password fields were found.
An empty password field can allow passwordless authentication when the login stack permits it.
$ sudo chage --list --iso8601 deploy Last password change : 2026-06-13 Password expires : never Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7
Replace deploy with the target account. chage reads shadow password aging data and does not prove every login path on systems that also use directory services, SSH keys, or external identity providers.