The Locked Drawer: Passwd and the Shadow File
·TechSoftware Development

The Locked Drawer: Passwd and the Shadow File

Pull back the curtain on Linux identity. Master the architecture of user storage. Understand why passwords don't live in '/etc/passwd' and deep dive into the hashed world of '/etc/shadow'. Learn to manage password aging and identify weak hashes.

Identity Files: Passwd and Shadow

In the early days of Unix, your username AND your password (hashed) were stored in a file called /etc/passwd.

The Problem: Anyone on the system could read that file. Even though the password was hashed, a hacker could just copy the file home and spend a week guessing passwords until they broke in.

The Solution: The Shadow File (/etc/shadow).

Today, /etc/passwd is open to everyone (it just contains metadata like your home folder), but the actual password hashes are locked in /etc/shadow, which is readable only by the root user. In this lesson, we will learn to read and manage these critical files.


1. /etc/passwd: The Directory

Every line in this file represents one user. sudeep:x:1000:1000:Sudeep,,,:/home/sudeep:/bin/bash

  1. Username: sudeep.
  2. Password Placeholder: x. This tells the system: "Go look in the shadow file."
  3. UID: 1000. The numerical ID the kernel uses.
  4. GID: 1000. The primary group ID.
  5. GECOS: Real name and info.
  6. Home: /home/sudeep.
  7. Shell: /bin/bash.

2. /etc/shadow: The Vault

This is where the security happens. Each line has 9 fields. sudeep:$6$Abc123...:19000:0:90:7:30::

The Hash (Field 2)

The string between the colons is the "Salted Hash."

  • $1$: MD5 (Ancient, insecure).
  • $5$: SHA-256 (Secure).
  • $6$: SHA-512 (Modern standard).
  • $y$: yescrypt (The NEW state-of-the-art for super-resistance to GPUs).

3. Password Aging: Forced Discipline

Security isn't just about complexity; it's about movement. You can force users to change their passwords in /etc/shadow.

  • Field 3: Date of last change (in "Days since 1970").
  • Field 4: Min age (Wait X days before changing again).
  • Field 5: Max age (Password expires after X days).
  • Field 8: Expiration date (The date the account itself dies).
# Set Sudeep's password to expire every 90 days
sudo chage -M 90 sudeep

4. Practical: Locking an Account

If an employee leaves the company, you shouldn't delete their files immediately. You should Lock their account.

When you lock an account, Linux puts a ! in front of the password hash in /etc/shadow. This makes the hash impossible to match, preventing all logins.

# Lock the account
sudo usermod -L sudeep

# Unlock it later
sudo usermod -U sudeep

5. Troubleshooting: The "Root password" Reset

If you lose the root password, you can't use sudo.

  1. Reboot the server.
  2. Enter the GRUB menu and edit the boot line to add init=/bin/sh.
  3. The system boots into a root shell without a password.
  4. Mount root as writeable: mount -o remount,rw /.
  5. Run passwd root to set a new key.

6. Example: A Weak Hash Detector (Python)

If your server has been around for 10 years, some old accounts might still be using $1$ (MD5) hashes. These can be cracked in seconds on a modern laptop. Here is a Python script that audits your shadow file for legacy hashes.

import subprocess

def audit_hashes():
    """
    Parses /etc/shadow for weak algorithm identifiers.
    """
    print("--- Password Hash Algorithm Audit ---")
    print("-" * 35)
    
    try:
        # We need sudo to read /etc/shadow
        res = subprocess.run(["sudo", "cat", "/etc/shadow"], capture_output=True, text=True)
        lines = res.stdout.split('\n')
        
        for line in lines:
            if not line: continue
            parts = line.split(':')
            user = parts[0]
            password_hash = parts[1]
            
            # Skip locked (!) or empty (*) accounts
            if password_hash in ["!", "*", "!!"]:
                continue
                
            if password_hash.startswith("$1$"):
                print(f"[!!!] DANGER: User '{user}' is using MD5! Forced change required.")
            elif password_hash.startswith("$6$"):
                pass # Modern SHA-512
            elif password_hash.startswith("$y$"):
                pass # Modern yescrypt
            else:
                print(f"[??] Unknown Hash for '{user}': {password_hash[:5]}...")
                
    except Exception as e:
        print(f"Error reading shadow file: {e}")

if __name__ == "__main__":
    audit_hashes()

7. Professional Tip: Use 'nologin' for Service Accounts

If you create a user to run a database (like mysql), they should never be allowed to log in to a terminal. In /etc/passwd, set their shell to /usr/sbin/nologin. This means even if a hacker steals the password, they can't get a shell.


8. Summary

Identity security is about hiding the hashes.

  • /etc/passwd is for metadata (Shells, Homes, UIDs).
  • /etc/shadow is for security (Hashes, Aging, Locks).
  • $6$ and $y$ are the only hashes you should trust in 2026.
  • Password Aging prevents stale credentials from being exploited.
  • /usr/sbin/nologin is the shield for non-human accounts.

In the next lesson, we will move from local security to network privacy: SSH Tunneling and Dynamic Port Forwarding.

Quiz Questions

  1. Why is it important that /etc/shadow is only readable by root?
  2. What does a ! symbol in the password field of /etc/shadow indicate?
  3. How do you find out the UID of a specific user without looking at their home folder?

Continue to Lesson 5: Secure Tunnels—SSH Tunneling and Port Forwarding.

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn