passwd
The passwd command is a standard utility in Unix-like operating systems for updating user account passwords and managing associated password attributes.[1] It allows regular users to change their own passwords, while the superuser (root) can modify passwords for any account without needing the current password.[2] When invoked, passwd prompts for the existing password (if required) and the new one twice for verification, then updates the encrypted password in the /etc/shadow file after enforcing system-defined complexity rules, such as minimum length, avoidance of dictionary words, and restrictions on personal information.[1][3]
Beyond basic password changes, passwd supports administrative functions like locking or unlocking accounts by prefixing the password field with an exclamation mark, expiring passwords to force immediate changes on next login, or deleting passwords to enable passwordless access.[1] It also displays account status, including whether a password is set, locked, or rounded to the nearest whole day for aging purposes, and integrates with system-defined password aging policies, such as minimum and maximum days between changes.[2] Historically rooted in early Unix systems, passwd originally used DES-based encryption but now supports stronger methods like SHA-512, depending on the system's ENCRYPT_METHOD setting, to enhance security against brute-force attacks.[1] This command is essential for user authentication management and is available across major distributions, including Linux, Solaris, and z/OS variants.[4][3]
User Account Files
/etc/passwd File
The /etc/passwd file serves as the primary plain-text database for user account information in Unix-like operating systems, located at /etc/passwd and containing one line per user account.[5] This file is world-readable to allow utilities and applications to access basic user details without elevated privileges.[6] Each entry consists of seven colon-separated fields that define essential attributes for login and resource allocation.
The first field is the username, a unique string limited to a maximum of 32 characters in modern systems, though historically restricted to eight.[7] The second field, the password placeholder, originally held the encrypted password but now typically contains 'x' to indicate that actual password hashes are stored elsewhere.[5] The third field is the user ID (UID), a numeric value starting at 0 for the root superuser and generally ranging from 1000 upward for regular users.[6] The fourth field specifies the primary group ID (GID), another numeric identifier linking the user to their default group. The fifth field, known as the GECOS field, provides optional comma-separated comments such as the user's full name, office location, or contact details.[5] The sixth field denotes the home directory path, where the user's personal files and environment are typically stored.[7] Finally, the seventh field indicates the login shell, the command interpreter executed upon login, defaulting to /bin/sh if left empty.[6]
A representative entry might appear as follows:
user:x:1000:1000:User Name:/home/user:/bin/bash
user:x:1000:1000:User Name:/home/user:/bin/bash
In this example, "user" is the username, "x" marks the password placeholder, 1000 is both the UID and GID, "User Name" is the GECOS comment, "/home/user" is the home directory, and "/bin/bash" is the shell.[5]
During system authentication, the /etc/passwd file is consulted to retrieve the UID and GID for mapping user identities to processes and resources after successful login verification.[7] With the adoption of shadow password suites, password validation occurs separately, leaving this file focused on non-sensitive metadata.[6] The file is owned by the root user and maintains permissions of 644 (read and write for owner, read-only for group and others) to balance accessibility and protection.
/etc/shadow File
The /etc/shadow file is a text-based configuration file located at /etc/shadow in Unix-like operating systems, designed to store sensitive user password information and password aging metadata that cannot be safely kept in world-readable files.[8] It enhances security by separating hashed passwords from the publicly accessible /etc/passwd file, reducing the risk of unauthorized access to credential data.[9] This file is owned by the root user and typically belongs to the shadow group, with permissions set to 640 (readable and writable by root, readable by the shadow group) or 600 (readable and writable only by root), ensuring that only privileged processes can access its contents.[9][10]
Each line in the /etc/shadow file corresponds to a user account and consists of nine colon-separated fields, providing comprehensive details on password management.[8] The fields are as follows:
| Field | Description | Example Value |
|---|
| 1. Username | The login name of the user, matching an entry in /etc/passwd. | user |
| 2. Encrypted password | A hashed password using algorithms such as DES (traditional crypt), MD5 ($1$), SHA-256 ($5$), or SHA-512 ($6$); prefixed with the algorithm identifier, salt, and hash; disabled accounts use !, !!, or *. | $6$salt$hashvalue |
| 3. Last password change | Number of days since January 1, 1970 (Unix epoch), when the password was last changed. A value of 0 means the password must be changed at the next login. | 18400 |
| 4. Minimum password age | Minimum number of days required between password changes; 0 allows immediate changes. | 0 |
| 5. Maximum password age | Maximum number of days a password remains valid before expiration; 99999 often indicates no expiration. | 99999 |
| 6. Password warning period | Number of days to warn the user before password expiration. | 7 |
| 7. Password inactivity period | Number of days after expiration before the account is locked. | (empty) |
| 8. Account expiration date | Number of days since the epoch when the account expires. | (empty) |
| 9. Reserved | A field for future use, typically left empty. | (empty) |
These fields enable fine-grained control over password policies, such as enforcing regular changes and automatic account disabling to mitigate brute-force attacks and stale credentials.[11][12]
A representative entry might appear as:
user:$6$abc123$longhashhereabcde...:18400:0:99999:7:::
user:$6$abc123$longhashhereabcde...:18400:0:99999:7:::
Here, the username is user; the encrypted password uses SHA-512 ($6$) with salt abc123 and the subsequent hash; the password was last changed 18,400 days after the epoch (around 2020); no minimum age is enforced; the password expires after 99,999 days; warnings begin 7 days prior; and the remaining fields are empty, indicating no inactivity lock or account expiration.[11][9]
The /etc/shadow file integrates with /etc/passwd by having the latter's password field set to x, signaling authentication modules to consult /etc/shadow for verification.[8] Programs like login, su, and sudo, often via the Pluggable Authentication Modules (PAM) framework—specifically the pam_unix module—read this file to authenticate users against the stored hashes without exposing them system-wide.[13][14]
The shadow password system was introduced in the mid-1980s, first in Sun Microsystems' SunOS, to address vulnerabilities in storing hashes within the readable /etc/passwd file, and was later standardized in System V Release 3.2 (1988) and adopted in BSD variants by 1990.[15][16] This separation became a cornerstone of Unix security, influencing modern Linux distributions and other Unix-like systems.[17]
The passwd Command
Syntax and Basic Usage
The passwd command is a setuid root binary located at /usr/bin/passwd, enabling non-root users to change their own passwords while allowing the root user to manage passwords for any user account.[1][18] This design ensures that password updates, which require elevated privileges to modify system files, can be performed securely without granting full root access to ordinary users.[18] The command integrates with Pluggable Authentication Modules (PAM) to handle authentication and enforce password policies during the change process.[1]
The basic syntax of the command is:
passwd [options] [username]
passwd [options] [username]
Omitting the username argument targets the current user's password, making it suitable for interactive use by regular users.[1] For root, specifying a username allows changing another account's password without needing the current password of that account.[1] The command assumes the target is a local account defined in the system's user database.[1]
In basic interactive usage, invoking passwd without options prompts the user first for their current password (one attempt, skipped if run as root).[1] It then requests the new password twice for confirmation; if the entries match and satisfy PAM-enforced constraints—such as minimum length, complexity requirements, and password aging rules—the command proceeds.[1] Upon success, it computes and stores the hashed new password in the /etc/shadow file.[1] For scripted or non-interactive scenarios, the command supports reading the new password from standard input, as in echo "newpassword" | passwd --stdin username, facilitating automation while still requiring appropriate privileges.[1]
The passwd command returns specific exit codes to indicate outcomes: 0 for success, 1 for permission denied, 3 for unexpected failure with no changes made, and 4 for unexpected failure due to the password file being missing.[1] These codes allow scripts and administrators to detect and handle errors programmatically.[1]
Options and Advanced Features
The passwd command supports several command-line options that enable administrators to manage user accounts beyond basic password changes, such as locking, unlocking, or querying status.[1] The -l or --lock option locks a user account by prefixing the password hash in the /etc/shadow file with an exclamation mark (!), preventing login attempts until unlocked.[1] Conversely, the -u or --unlock option removes this prefix to restore access.[1] The -d or --delete option clears the password field, allowing login without a password, which is typically used for temporary access or in combination with other security measures.[1] To force a password expiration, the -e or --expire option sets the last password change date to zero in the shadow file, requiring an immediate change on next login.[1]
The -S or --status option provides a report on the account's password status, outputting details such as the username, password status (e.g., P for password set, L for locked, NP for no password), last change date, minimum days between changes, maximum days before expiration, warning days, and inactivity period; for example, user P 05/15/2023 0 99999 7 -1 indicates a password set with no expiration constraints.[1] When used with -a or --all, it reports status for all users.[1] Administrators running as root can specify a target username (e.g., passwd otheruser) to modify any account's password without the current user's involvement.[1] For non-interactive scripting, the --stdin option reads the new password directly from standard input as a single line, facilitating automation while bypassing prompts.[1]
Additional administrative options allow direct manipulation of shadow file fields for password aging: -n or --mindays sets the minimum days required between password changes, -x or --maxdays establishes the maximum validity period, and -w or --warndays configures the advance warning days before expiration.[1] These options update the corresponding fields in /etc/[shadow](/page/Shadow) without altering the password itself.[1]
The passwd command integrates with Pluggable Authentication Modules (PAM) for advanced features like password quality enforcement, where modules such as pam_pwquality or pam_cracklib perform checks for strength, dictionary words, and complexity rules during password updates.[1][19] For instance, pam_cracklib rejects passwords resembling dictionary entries or common patterns to mitigate brute-force risks.[20] Input handling supports both cleartext passwords (prompted or via --stdin) and pre-encrypted hashes when provided by administrators, with PAM managing the encryption using system-configured algorithms like SHA-512.[1]
Platform implementations vary slightly; in GNU coreutils (common on Linux distributions), options like -R or --root enable chroot directory specification for restricted environments, while FreeBSD's passwd emphasizes NIS/Kerberos support with options like -l to update only local passwords and -y to force NIS mode.[1][21] These differences stem from project-specific enhancements, with BSD variants emphasizing NIS/Kerberos support.[21]
Common errors include "Authentication token manipulation error," which typically indicates failures in updating the shadow file due to permission issues (e.g., non-root access without sudo), full disk space, or filesystem read-only states; resolution often involves verifying write access to /etc/shadow and related directories.[22]
Historical Development
Origins in Early Unix
The passwd system originated during the development of Unix at Bell Labs, part of AT&T, beginning in 1969 with initial work by Ken Thompson on a PDP-7 computer.[23] Unix evolved as a simplified alternative to the more complex Multics system, on which Thompson and Dennis Ritchie had previously collaborated, incorporating lessons in multi-user time-sharing and file-based resource management.[23] By 1971, the first internal manual described a basic multi-user environment where user authentication relied on a dedicated password file to support login processes.[24]
The /etc/passwd file emerged as the core mechanism for user account management in early Unix, introduced around Version 3 in 1973 as an ASCII text file storing essential user details.[25] Its original design featured colon-separated fields for each user, including the login name, encrypted password, user ID (UID), comment field (such as GCOS job information), home directory, and shell. The group ID (GID) field was added later in Version 7.[25] Passwords were encrypted using an early one-way function based on a simulation of the M-209 cipher machine, where the password served as the key to encipher a constant value, producing an 8-character output stored in the file.[26] This file was made world-readable to allow non-privileged programs, like the login(1) utility, to access user metadata such as UIDs and home directories for authentication and session setup, reflecting the simple security model of small-scale research systems at the time.[23] Thompson and Ritchie, as primary architects, shaped this integrated approach to prioritize ease of implementation over stringent access controls.[23]
A key milestone came with the Seventh Edition of Unix in 1979, which introduced the seven-field format of /etc/passwd, adding the group ID (GID) field and integrating it more firmly with the login(1) program for verifying credentials during user sessions. However, the design exhibited initial limitations suited to its era: passwords lacked aging mechanisms or expiration policies, and the single, readable file combined authentication data with account information, creating risks as user bases grew beyond a handful of developers.[26] These constraints stemmed from the system's origins in a trusted internal environment, where comprehensive separation of concerns was not yet prioritized.[23]
Evolution to Shadow Passwords
The shadow password system emerged in the mid-1980s to address security limitations in the original /etc/passwd file, where encrypted passwords were world-readable, enabling offline cracking by any user. It was first implemented in SunOS during this period and introduced in 1987 by Julianne Frances Haugh for SCO Xenix after experiencing a system break-in; this suite separated sensitive password data into the /etc/shadow file, restricted to root access only, while retaining user account details in /etc/passwd for non-privileged processes like getpwent(). The approach was later adopted in System V Release 3.2 in 1988 and BSD 4.3 Reno in 1990, becoming a standard feature across Unix variants by the early 1990s. These functions for accessing the shadow database were formalized in the POSIX.1-2008 standard to ensure portability.[16][17]
Key drivers for the shift included heightened awareness of vulnerabilities highlighted by password-cracking tools, notably Crack version 4.1 released in 1992 by Alec Muffett, which exploited the readability of DES-encrypted passwords in /etc/passwd to perform dictionary and brute-force attacks efficiently on commodity hardware.) This underscored the need for password aging mechanisms—tracking last change dates, minimum age, and expiration—to encourage frequent updates and limit reuse, features natively supported in /etc/shadow. Concurrently, the 1990s saw a transition from the vulnerable DES-based crypt(3) algorithm to MD5 hashing in many Unix systems, providing longer hashes (128 bits) and slower computation to deter exhaustive searches.[27]
Standardization efforts aligned shadow passwords with cryptographic requirements, including FIPS 140-2 compliance for validated hashing modules used in federal systems, ensuring robust protection against key recovery attacks. In the 1990s, integration with networked authentication protocols like NIS (Network Information Service) and LDAP (Lightweight Directory Access Protocol) extended shadow functionality to distributed environments, allowing synchronized password management across multiple hosts without exposing hashes over the network.
Modern adaptations have focused on enhancing policy enforcement and resilience; the libpwquality library, developed in the early 2010s by Red Hat, provides APIs for checking password strength against configurable rules like entropy scores and cracklib dictionaries during passwd operations. In the 2020s, distributions began adopting newer hashing: Fedora switched to yescrypt (a memory-hard function) as default in 2021, and Red Hat Enterprise Linux added bcrypt support in 2024 (version 8.10), both providing stronger protection against parallel attacks.[28][29] Argon2 support remains limited outside specialized modules. Along this timeline, the 2000s marked the widespread maturation of Pluggable Authentication Modules (PAM), first developed by Sun Microsystems in 1994, integrated into Solaris 2.6 in 1997, and adopted in open-source Linux distributions starting in 1996, which replaced direct /etc/shadow access with modular interfaces for authentication, enabling extensions like multi-factor support without altering core files.
Security Considerations
Vulnerabilities in Traditional Systems
In early Unix systems, the /etc/passwd file stored encrypted passwords alongside user account details in a world-readable format, enabling any local user or attacker with file access to copy the password hashes for offline cracking attempts. This design choice, intended to support utilities like finger that required access to user information, exposed the system to significant risks, as attackers could extract and analyze the hashes without needing ongoing system access.[30]
The traditional encryption relied on the DES-based crypt() function, which used a 12-bit salt to vary the hash output and deter precomputed attacks; however, this short salt length proved insufficient against rainbow table attacks, as it limited the number of unique hash variations to just 4,096 per password, allowing attackers to generate feasible tables for common passwords. The crypt() algorithm itself was vulnerable due to its reliance on a modified DES encryption of a fixed 64-bit block repeated 25 times, which was computationally inexpensive to reverse with growing hardware capabilities by the early 1990s.[31][32][33]
Tools like John the Ripper, first released in 1996, specifically targeted these DES-based hashes from /etc/passwd files, enabling efficient brute-force and dictionary attacks that could crack weak or common passwords in hours or days on contemporary hardware. Variants of John the Ripper further optimized for DES cracking, demonstrating how the exposed, unsalted-equivalent hashes facilitated rapid compromise of user accounts.[34][35]
Although traditional systems included basic password aging mechanisms in the /etc/passwd file, their world-readable nature made them insecure, often leading to stale passwords that users rarely updated, increasing the likelihood of compromise from dictionary attacks or reused credentials. This gap contributed to historical incidents, such as the 1988 Morris Worm, which exploited weak default passwords like "guest" or simple variants of usernames to propagate across Unix networks, infecting an estimated 10% of the internet at the time.[36][37]
The passwd command's setuid root privilege allowed it to modify protected files like /etc/passwd, but this elevated execution model created risks for local privilege escalation if misconfigured, such as through improper permissions on supporting libraries or environment variables that could be manipulated by unprivileged users. In pre-2000 BSD variants, buffer overflows in the passwd utility—particularly when handling long GECOS fields or shell specifications—enabled local attackers to overwrite stack memory and execute arbitrary code as root, as seen in vulnerabilities affecting BSD 4.3 and earlier releases. These flaws in crypt() and related components, along with exposed files, have been linked to real-world reconnaissance in breaches where /etc/passwd leaks aided targeted phishing or brute-force attempts against enumerated usernames. To address these issues, the shadow password system was introduced to segregate sensitive data.[38][39][40]
Modern Best Practices
In modern Linux systems, password hashing for the /etc/shadow file should employ strong, adaptive algorithms to resist brute-force attacks, such as Argon2id, PBKDF2 with at least 600,000 iterations, bcrypt, or scrypt, as recommended by the OWASP Password Storage Cheat Sheet.[41] Algorithms like MD5 and DES-based crypt must be avoided due to their vulnerability to modern hardware.[41] Configuration is typically set in /etc/login.defs using the ENCRYPT_METHOD directive, for example, ENCRYPT_METHOD SHA512 for systems supporting SHA-512, which provides 256-bit security equivalent when combined with sufficient salt and rounds.[42] Newer distributions may prefer yescrypt for its memory-hard properties, enhancing protection against GPU-accelerated cracking.[41]
Access controls for password files are essential to prevent unauthorized reads. The /etc/shadow file should have permissions set to 600 (readable and writable only by root) or 640 (readable by the shadow group) to restrict access while allowing necessary operations, minimizing exposure in compromised environments.[43] Integration with Pluggable Authentication Modules (PAM) via pam_pwquality enforces robust policies, such as a minimum password length of 12 characters, requirements for diverse character classes (e.g., uppercase, lowercase, digits, symbols), and prohibition of password reuse within the last 5 changes.[44] For multi-factor authentication, PAM can stack modules like pam_google_authenticator alongside local passwords, ensuring layered security without relying solely on /etc/shadow.[30]
When using the passwd command, interactive mode is preferred for user-driven changes to avoid exposing passwords in process lists or logs; the --stdin option should only be used in secure, automated scripts with input from protected sources like /dev/urandom or encrypted vaults, and never in multi-user or networked contexts.[1] Regular integrity audits are recommended using tools like pwck, which verifies consistency between /etc/passwd and /etc/shadow, checking for valid fields, duplicate entries, and proper formatting to detect tampering.[45]
For networked environments, local /etc/passwd and /etc/shadow files should not be directly exposed over protocols like NFS; instead, implement centralized authentication using SSSD (System Security Services Daemon) integrated with FreeIPA or LDAP backends to manage credentials remotely while caching for offline access.[46] This approach reduces the attack surface by avoiding replication of sensitive files across hosts.
These practices align with NIST SP 800-63B guidelines (revision 4, 2024), which emphasize verifier-side storage of salted hashes resistant to offline attacks, minimum lengths of 8 characters for user-chosen passwords (with encouragement for longer passphrases up to 64 characters), avoidance of composition rules, and blacklisting of compromised passwords without mandatory periodic changes.[47] Regarding post-quantum threats, memory-hard functions like Argon2 or yescrypt in PAM configurations provide forward resistance, as they complicate Grover's algorithm exploitation on quantum hardware.[41]