Unix Permissions: The Mode Bits That Control Access
How Linux Decides Who Can Do What
Every file and directory on a Linux system has a set of permission bits that determine which users can read, write, or execute it. Understanding these bits is fundamental to system security — misconfigured permissions are one of the most common causes of data breaches and privilege escalation.
The Permission Structure
Unix permissions are divided into three categories:
- Owner (u): The user who owns the file. Usually the user who created it.
- Group (g): The group that owns the file. All members of that group share the group permissions.
- Other (o): Everyone else — all users who are not the owner and not in the group.
Each category has three permission bits:
- Read (r): For files, allows viewing the content. For directories, allows listing the contents (ls).
- Write (w): For files, allows modifying the content. For directories, allows creating, deleting, and renaming files within.
- Execute (x): For files, allows running the file as a program. For directories, allows accessing files within (cd into the directory).
Reading Permission Bits
# View permissions in long format
ls -l /etc/passwd
# Output: -rw-r--r-- 1 root root 2847 Jan 1 12:00 /etc/passwd
# Breakdown:
# - rw- r-- r--
# | | | |
# | | | +-- Other: read only
# | | +------- Group: read only
# | +------------ Owner: read + write
# +---------------- File type (- = regular file, d = directory, l = symlink)
The first character indicates the file type:
-Regular filedDirectorylSymbolic linkbBlock devicecCharacter devicesSocketpNamed pipe (FIFO)
Octal Notation
Permissions can also be represented as a three-digit octal number:
| Permission | Binary | Octal |
|---|---|---|
| --- | 000 | 0 |
| --x | 001 | 1 |
| -w- | 010 | 2 |
| -wx | 011 | 3 |
| r-- | 100 | 4 |
| r-x | 101 | 5 |
| rw- | 110 | 6 |
| rwx | 111 | 7 |
Common permission combinations:
755(rwxr-xr-x): Owner can do everything; group and others can read and execute. Standard for directories and executables.644(rw-r--r--): Owner can read and write; group and others can read. Standard for regular files.600(rw-------): Only the owner can read and write. Standard for sensitive files like SSH keys.777(rwxrwxrwx): Everyone can do everything. Almost never correct.400(r--------): Only the owner can read. Used for files that should not be modified.
Special Permission Bits
In addition to the standard rwx bits, there are three special bits:
SUID (Set User ID) — s in the owner execute position
When a SUID binary is executed, it runs with the privileges of the file owner, not the user who executed it. The classic example is /usr/bin/passwd — it is owned by root and has SUID set, allowing ordinary users to modify their own password in /etc/shadow (which is only writable by root).
# Find all SUID binaries on the system
find / -perm -4000 -type f 2>/dev/null
# Example output:
# /usr/bin/passwd
# /usr/bin/sudo
# /usr/bin/chsh
SUID is dangerous when applied to unnecessary binaries. If an attacker finds a SUID binary that can be exploited (e.g., through a buffer overflow or command injection), they gain the owner's privileges — often root.
SGID (Set Group ID) — s in the group execute position
When a SGID binary is executed, it runs with the privileges of the file's group. When set on a directory, new files created within inherit the directory's group ownership.
# Find all SGID binaries
find / -perm -2000 -type f 2>/dev/null
Sticky Bit — t in the other execute position
When set on a directory, only the file owner, directory owner, or root can delete or rename files within. The classic example is /tmp — world-writable but with the sticky bit set, so users can create files but cannot delete other users' files.
# Check the sticky bit on /tmp
ls -ld /tmp
# Output: drwxrwxrwt 10 root root 4096 Jan 1 12:00 /tmp
# The 't' at the end indicates the sticky bit
Ownership: Who Owns What
Every file has an owner (user) and a group. Ownership determines which permissions apply:
# View ownership
ls -l /etc/shadow
# Output: -rw-r----- 1 root shadow 1234 Jan 1 12:00 /etc/shadow
# Owner: root, Group: shadow
# Change owner
chown root:shadow /etc/shadow
# Change only the owner
chown root file.txt
# Change only the group
chgrp developers file.txt
# Change ownership recursively
chown -R www-data:www-data /var/www/html
The principle: files should be owned by the account that needs to manage them, and the group should reflect who needs access. A web application's files should be owned by the web server's user (e.g., www-data), not by a developer's personal account.
Dangerous Permissions and How to Find Them
The Misconfigurations That Lead to Breaches
Permission misconfigurations are among the most common findings in security audits. They are also among the easiest to fix — if you know what to look for.
World-Writable Files
A world-writable file (mode o+w) can be modified by any user on the system. If that file is a configuration file, a script, or a binary, any user can modify it to gain elevated privileges.
# Find all world-writable files
find / -perm -0002 -type f 2>/dev/null
# Find world-writable files excluding /tmp and /proc
find / -path /proc -prune -o -path /tmp -prune -o -perm -0002 -type f -print 2>/dev/null
Why this is dangerous: If /etc/cron.d/backup is world-writable, any user can add a cron job that runs as root. If /usr/local/bin/backup.sh is world-writable, any user can modify it to execute arbitrary code the next time it runs.
World-Readable Sensitive Files
Files containing passwords, API keys, or private keys should never be world-readable.
# Find world-readable files in sensitive locations
find /etc /home /root -perm -0004 -type f 2>/dev/null | grep -E '(passwd|shadow|key|secret|credential)'
# Check SSH key permissions
ls -la ~/.ssh/
# Correct: -rw------- (600) for private keys
# Correct: -rw-r--r-- (644) for public keys
# Dangerous: -rw-rw-rw- (666) for private keys
Why this is dangerous: If /etc/shadow (which contains password hashes) is world-readable, any user can crack the hashes offline. If an SSH private key is world-readable, any user can impersonate the key's owner.
SUID/SGID Binaries
Every SUID binary is a potential privilege escalation vector. Attackers scan for SUID binaries and check whether they are exploitable.
# Find all SUID binaries and check against known exploits
find / -perm -4000 -type f 2>/dev/null | while read binary; do
echo "SUID: $binary"
ls -la "$binary"
done
# Check if a specific binary is a known-vulnerable SUID
# Use tools like LinEnum or linux-smart-enumeration
Why this is dangerous: If a SUID binary has a buffer overflow, command injection, or path traversal vulnerability, an attacker can execute arbitrary code as the binary's owner (often root). The 2021 Pwn2Own contest demonstrated SUID exploitation in pkexec (CVE-2021-4034), which affected every major Linux distribution.
Unowned Files
Files with no valid owner or group (UID/GID that does not correspond to any user) may indicate a deleted user's files or a malicious upload.
# Find files with no valid owner
find / -nouser -o -nogroup 2>/dev/null
Why this is dangerous: An attacker who creates a file as root and then deletes the root account (or exploits a vulnerability that changes ownership) can leave files that are owned by a high-privilege UID but not associated with any named user. These files may be overlooked in audits.
Permission Auditing Script
#!/bin/bash
# Comprehensive permission audit script
# Run as root for complete results
echo "=== World-Writable Files ==="
find / -path /proc -prune -o -path /sys -prune -o -path /tmp -prune -o -perm -0002 -type f -print 2>/dev/null
echo ""
echo "=== SUID Binaries ==="
find / -perm -4000 -type f 2>/dev/null
echo ""
echo "=== SGID Binaries ==="
find / -perm -2000 -type f 2>/dev/null
echo ""
echo "=== Unowned Files ==="
find / -nouser -o -nogroup 2>/dev/null
echo ""
echo "=== World-Readable SSH Keys ==="
find /home /root -name "id_*" -perm -0004 2>/dev/null
echo ""
echo "=== Files in /etc with Wrong Permissions ==="
find /etc -type f -perm -0002 2>/dev/null
Setting Correct Permissions
# Web application files
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# Configuration files (readable only by owner and group)
chmod 640 /etc/myapp/config.yml
chown root:myapp /etc/myapp/config.yml
# SSH keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys
# Cron jobs
chmod 600 /etc/crontab
chown root:root /etc/crontab
# Log files
chmod 640 /var/log/myapp.log
chown root:adm /var/log/myapp.log
The principle: grant the minimum permissions necessary. A file that only needs to be read by its owner should be 600. A file that needs to be read by a group should be 640 or 644. A file that needs to be executed by everyone should be 755. Anything more permissive is a risk.
Practice Problems
Solution
The permissions `rwsr-xr-x` (octal 4755) mean: owner has read, write, and execute with SUID set (the 's' in the owner execute position); group has read and execute; others have read and execute. The SUID bit means the binary runs with the owner's privileges, not the user who executes it. This is potentially dangerous because if the binary has any vulnerability (buffer overflow, command injection, path traversal), an attacker can exploit it to gain the owner's privileges — often root. Investigation steps: (1) Identify the file: ls -la /path/to/file. (2) Check if the SUID bit is necessary — is this a known system binary like /usr/bin/passwd, or an unknown binary? (3) If unknown, check the binary's origin, hash, and digital signature. (4) Search for known CVEs affecting this binary. (5) If the SUID bit is not required, remove it: chmod u-s /path/to/file. (6) If it is required, ensure the binary is patched and monitor for exploitation attempts. Solution
The risk: with permissions 644, any user on the system can read the database credentials. If an attacker gains a low-privilege foothold on the server (e.g., through a vulnerability in another application), they can read the database credentials and access the database directly, bypassing the application's access controls. The correct configuration: (1) The file should be owned by the web server user (www-data) or by root with the web server's group. (2) Permissions should be 640 (rw-r-----) — owner can read and write, group can read, others have no access. (3) If the web server runs as www-data, set ownership to www-data:www-data with permissions 640. (4) Better yet, move the configuration file outside the web root so it cannot be accessed directly through the web server even if the web server is misconfigured. Commands: chown www-data:www-data /var/www/html/config/database.yml && chmod 640 /var/www/html/config/database.yml. Even better: mv /var/www/html/config/database.yml /etc/myapp/database.yml && chown www-data:www-data /etc/myapp/database.yml && chmod 640 /etc/myapp/database.yml. Quiz
1. A file has permissions `rwxrwxrwx` (777). Which statement accurately describes the risk?
2. What does the SUID bit do when set on an executable file, and why is it a security concern?
3. Why is a world-writable directory without the sticky bit a security risk?
Flashcards
Question
What are the three permission categories in Unix?
Click to reveal answer
Answer
Owner (u) — the user who owns the file; Group (g) — the group that owns the file; Other (o) — everyone else.
Question
What do the octal values 755, 644, and 600 represent?
Click to reveal answer
Answer
755 = rwxr-xr-x (owner: all, group: read+execute, other: read+execute) — standard for directories and executables. 644 = rw-r--r-- (owner: read+write, group: read, other: read) — standard for regular files. 600 = rw------- (owner: read+write only) — standard for sensitive files like SSH keys.
Question
What does the SUID bit do and what is the security risk?
Click to reveal answer
Answer
SUID causes a binary to run with the owner's privileges, not the executing user's. Security risk: if the binary is exploitable, the attacker gains the owner's privileges (often root). Audit with: find / -perm -4000 -type f
Question
What does the sticky bit do on a directory?
Click to reveal answer
Answer
When set on a directory, only the file owner, directory owner, or root can delete or rename files within. Prevents users from deleting each other's files in shared directories like /tmp.
Question
How do you find all world-writable files on a Linux system?
Click to reveal answer
Answer
find / -perm -0002 -type f 2>/dev/null — finds all files where the write bit is set for 'other'. Exclude /proc, /sys, and /tmp for more relevant results.
Question
What are the correct permissions for an SSH private key?
Click to reveal answer
Answer
600 (rw-------) — only the owner can read and write. The .ssh directory should be 700 (rwx------). Public keys can be 644 (rw-r--r--). World-readable private keys are a critical vulnerability.
Revision Notes
Key Takeaways
- 1. Unix permissions split into owner/group/other with read/write/execute bits
- 2. 755 for directories, 644 for files, 600 for sensitive files — 777 is almost never correct
- 3. SUID binaries run as the file owner and are privilege escalation vectors — audit regularly
- 4. The sticky bit on directories prevents users from deleting each other's files
- 5. World-writable configuration files allow any user to modify service behavior
- 6. SSH private keys must be 600 — world-readable keys are a critical vulnerability
Interview Tips
- • Be ready to interpret permission strings in both symbolic and octal notation
- • Explain the security risk of SUID binaries and how you would audit for them
- • Discuss how you would respond to finding a world-writable configuration file on a production server
- • Describe the correct permissions for common file types (web files, config files, SSH keys, cron jobs)
- • Connect file permissions to privilege escalation — misconfigured permissions are a common escalation path
Cheat Sheet
File Permissions and Ownership Cheat Sheet
Phase: Operating System Hardening and Permissions | Level: beginner
Permission Structure:
- rw- r-- r--
| | | +-- Other
| | +------- Group
| +------------ Owner
+----------------- File type (- file, d dir, l link)
Common Octal Values:
- 755 (rwxr-xr-x) — directories, executables
- 644 (rw-r--r--) — regular files
- 600 (rw-------) — sensitive files (SSH keys, credentials)
- 777 (rwxrwxrwx) — almost never correct
Special Bits:
- SUID (4000): runs as file owner — audit with
find / -perm -4000 -type f - SGID (2000): runs as file group
- Sticky (1000): only owner can delete in directory (e.g., /tmp = 1777)
Dangerous Configurations:
- World-writable files:
find / -perm -0002 -type f - World-readable secrets: check /etc/shadow, ~/.ssh/id_*
- Unnecessary SUID binaries:
find / -perm -4000 -type f - Unowned files:
find / -nouser -o -nogroup
Correct Permissions:
- Web files:
chown -R www-data:www-data /var/www/html - Config files:
chmod 640 /etc/app/config.yml - SSH keys:
chmod 600 ~/.ssh/id_rsa - Cron jobs:
chmod 600 /etc/crontab