3.5. Lab: Permissions Management#
Practice setting up secure projects and managing permissions. All exercises use your home directory, so no sudo required.
3.5.1. Part 1: Understanding Permissions#
3.5.1.1. Exercise 1.1: Reading ls -l Output#
# Create test files
$ mkdir ~/lab/permissions
$ cd ~/lab/permissions
$ touch document.txt script.sh config.ini secret.key
# List with details
$ ls -l
total 0
-rw-r--r-- 1 user user 0 Jan 15 config.ini
-rw-r--r-- 1 user user 0 Jan 15 document.txt
-rw-r--r-- 1 user user 0 Jan 15 script.sh
-rw-r--r-- 1 user user 0 Jan 15 secret.key
# For each file, determine:
# 1. Who owns it?
# 2. What group does it belong to?
# 3. Can the owner write to it?
# 4. Can others read it?
# 5. What would 644 be in symbols?
3.5.1.2. Exercise 1.2: Octal Notation Conversion#
Convert between symbols and octal:
# Symbol to octal
# rwxr-xr-x = ? (answer: 755)
# rw-r--r-- = ? (answer: 644)
# rw------- = ? (answer: 600)
# rwxrwxrwx = ? (answer: 777)
# Octal to symbol
# 700 = ? (answer: rwx------)
# 640 = ? (answer: rw-r-----)
# 444 = ? (answer: r--r--r--)
# 755 = ? (answer: rwxr-xr-x)
3.5.2. Part 2: Modifying Permissions#
3.5.2.1. Exercise 2.1: chmod with Octal Notation#
# Make a file private (owner read/write only)
$ chmod 600 secret.key
$ ls -l secret.key
-rw------- 1 user user 0 Jan 15 secret.key
# Make a script executable by owner and group
$ chmod 750 script.sh
$ ls -l script.sh
-rwxr-x--- 1 user user 0 Jan 15 script.sh
# Make a document world-readable but not writable
$ chmod 644 document.txt
$ ls -l document.txt
-rw-r--r-- 1 user user 0 Jan 15 document.txt
# Challenge: How would you set config.ini to rw-rw-r--?
# Answer: chmod 664 config.ini
3.5.2.2. Exercise 2.2: chmod with Symbolic Notation#
# Add execute permission for owner
$ chmod u+x script.sh
$ ls -l script.sh
-rwxr--r-- 1 user user 0 Jan 15 script.sh
# Remove all permissions, then add read for all
$ chmod a-rwx,a+r document.txt
$ ls -l document.txt
-r--r--r-- 1 user user 0 Jan 15 document.txt
# Add write for group
$ chmod g+w config.ini
$ ls -l config.ini
-rw-rw-r-- 1 user user 0 Jan 15 config.ini
# Remove read permission for others
$ chmod o-r secret.key
$ ls -l secret.key
-rw------- 1 user user 0 Jan 15 secret.key (already was)
3.5.2.3. Exercise 2.3: Recursive Permissions#
# Create a directory structure
$ mkdir -p project/{src,docs,data}
$ touch project/src/{main.sh,lib.sh}
$ touch project/docs/{README.txt,INSTALL.txt}
$ ls -lR project
# Set permissions recursively
$ chmod 755 project
$ chmod 644 project/docs/*
$ chmod 644 project/src/*.sh
# Challenge: Give group write permission to all files in 'data' directory
# Answer: chmod g+w project/data
3.5.3. Part 3: Understanding Umask#
3.5.3.1. Exercise 3.1: Exploring Default Umask#
# Check current umask
$ umask
0022
# Create files and directories to see default permissions
$ cd ~/lab/umask
$ touch newfile.txt
$ mkdir newdir
$ ls -ld newdir
drwxr-xr-x 2 user user 4096 Jan 15 newdir
$ ls -l newfile.txt
-rw-r--r-- 1 user user 0 Jan 15 newfile.txt
# Calculate what happened:
# File: 666 - 022 = 644 ✓
# Directory: 777 - 022 = 755 ✓
3.5.3.2. Exercise 3.2: Changing Umask Temporarily#
# Change to restrictive umask
$ umask 0077
$ umask
0077
# Create new files
$ touch private_file.txt
$ mkdir private_dir
$ ls -l private_file.txt
-rw------- 1 user user 0 Jan 15 private_file.txt
$ ls -ld private_dir
drwx------ 2 user user 4096 Jan 15 private_dir
# Calculation:
# File: 666 - 077 = 600 ✓
# Directory: 777 - 077 = 700 ✓
# Reset umask
$ umask 0022
3.5.3.3. Exercise 3.3: Umask for Team Collaboration#
# Set team-friendly umask
$ umask 0002
$ touch shared_file.txt
$ mkdir shared_dir
$ ls -l shared_file.txt
-rw-rw-r-- 1 user user 0 Jan 15 shared_file.txt
$ ls -ld shared_dir
drwxrwxr-x 2 user user 4096 Jan 15 shared_dir
# Results:
# File: 666 - 002 = 664 (owner and group can write)
# Directory: 777 - 002 = 775 (owner and group can write/enter)
# Challenge: What umask gives directories rwxr-xr-x and files rw-r--r--?
# Answer: umask 0022
3.5.4. Part 4: Special Permissions#
3.5.4.1. Exercise 4.1: Understanding setuid#
# Compare regular vs setuid program
$ ls -l /bin/passwd /bin/cat
-rwxr-xr-x 1 root root 42136 Jan 1 /bin/cat
-rwsr-xr-x 1 root root 68208 Jan 1 /bin/passwd
^
Notice the 's' instead of 'x' in owner execute
# The setuid bit allows passwd to run as root even when you execute it
$ whoami
user
$ passwd user
# This actually modifies /etc/shadow, which requires root!
# Because passwd has the setuid bit and is owned by root
# Demonstrate with a simple example:
$ cd ~/lab/special
$ cat > myscript.sh << 'EOF'
#!/bin/bash
echo "Running as: $(whoami)"
EOF
$ chmod 755 myscript.sh
$ ./myscript.sh
Running as: user
# Set setuid (you'd need root for this, so just show the concept)
# sudo chmod u+s myscript.sh
# ./myscript.sh would then say "Running as: root"
3.5.4.2. Exercise 4.2: Understanding setgid and Sticky Bit#
# Check setgid on directories
$ ls -ld /var/tmp
drwxrwxrwt 10 root root 4096 Jan 15 /var/tmp
^^
sticky bit (t) and setgid (s)
# Create a group-shared directory with setgid
$ mkdir team_project
$ chmod g+s team_project # Set setgid
$ chmod 2770 team_project # Alternative: octal notation
$ ls -ld team_project
drwxrws--- 2 user user 4096 Jan 15 team_project
^
's' means setgid
# Any files created in this directory inherit the group
$ cd team_project
$ touch file1.txt
$ ls -l file1.txt
-rw-r--r-- 1 user user 0 Jan 15 file1.txt
# file1.txt will have the group of team_project, not user's default group!
3.5.4.3. Exercise 4.3: Sticky Bit Protection#
# In /tmp directory, anyone can create files but only delete their own
$ ls -ld /tmp
drwxrwxrwt 10 root root 4096 Jan 15 /tmp
^
sticky bit (t)
# Set sticky bit on a directory
$ chmod 1777 shared_dir # Octal notation
# or
$ chmod +t shared_dir # Symbolic notation
# Result: Users can create files but can't delete others' files
$ ls -ld shared_dir
drwxrwxrwt 2 user user 4096 Jan 15 shared_dir
# Challenge: What permissions would you set to:
# - Give owner rwx, group rwx, others just enter?
# - Make files created in it inherit the group?
# Answer: chmod 2770 dirname
3.5.5. Part 5: Real-World Project Setup Scenario#
3.5.5.1. Scenario: Setting Up a Secure Web Development Project#
Your team (user, alice, bob) is starting a PHP web project that needs:
Source code (developers should read/modify, web server reads)
Configuration files (secrets - developers only)
Uploads directory (web server writes, developers read)
Logs directory (web server writes, developers read)
3.5.5.2. Exercise 5.1: Create the Structure#
# Create project directory
$ cd ~/lab
$ mkdir -p webproject/{src,config,uploads,logs}
$ cd webproject
$ tree
webproject/
├── config/
├── logs/
├── src/
└── uploads/
# Create some sample files
$ echo "<?php echo 'Hello'; ?>" > src/index.php
$ echo "DB_USER=app\nDB_PASS=secret123" > config/db.conf
$ touch logs/access.log
$ chmod 775 uploads # Web server needs write access
3.5.5.3. Exercise 5.2: Set Secure Permissions#
# 1. Set directory permissions
$ chmod 755 . # Project root: rwxr-xr-x
$ chmod 755 src # Source: readable by all
$ chmod 750 config # Config: developers only (no read for web server)
$ chmod 755 logs # Logs: readable by all
$ chmod 755 uploads # Uploads: web server can write
# 2. Set file permissions
$ chmod 644 src/*.php # Source files: readable by all, writable by owner
$ chmod 640 config/* # Config: readable by group (developers), not by web
$ chmod 644 logs/*.log # Logs: readable by all
# Verify
$ ls -lR
3.5.5.4. Exercise 5.3: Set Up Group Ownership#
# Assume 'www-data' is the web server user and 'webteam' is the developer group
# Set group ownership
$ chgrp webteam config # Developers can read config
$ chgrp www-data logs # Web server owns logs
$ chgrp www-data uploads # Web server owns uploads
# Set group read/write where needed
$ chmod 750 config # webteam group can read
$ chmod 755 logs # Web server (www-data) can write via sticky bit
$ chmod 775 uploads # Web server can write
# For logs and uploads to work with setgid:
$ chmod 2755 logs # Files created inherit www-data group
$ chmod 2775 uploads # Files created inherit www-data group
3.5.5.5. Exercise 5.4: Security Verification Checklist#
# Run these commands to verify security:
# 1. Check no world-writable directories
$ find . -type d -perm -002
# Should show nothing or only expected temp directories
# 2. Verify config files aren't world-readable
$ ls -l config/
-rw-r----- 1 user webteam 35 Jan 15 db.conf
# Permission should be 640 or 600 (not 644)
# 3. Check source code permissions
$ ls -l src/
-rw-r--r-- 1 user user 25 Jan 15 index.php
# Should be readable (644) but not writable by group/others
# 4. Verify upload/log directories are writable by process
$ ls -ld uploads logs
drwxrwxr-x 2 user www-data 4096 Jan 15 logs
drwxrwxr-x 2 user www-data 4096 Jan 15 uploads
# Should be writable by the group that owns them
# 5. Test file creation with setgid
$ touch uploads/test.txt
$ ls -l uploads/test.txt
-rw-r--r-- 1 user www-data 0 Jan 15 uploads/test.txt
# Should show www-data as group (inherited from directory)
3.5.5.6. Reflection Questions#
Why did we make
config/less readable (750) thansrc/(755)?What would happen if you set
uploads/to 755 without setgid?Why is the sticky bit (t) useful on the
logs/directory?How would you allow only specific developers to modify config files?
What are the risks of making config files world-readable (644)?
3.5.5.7. Challenge: Enhanced Security#
Modify the setup so that:
Only the admin user (not all developers) can read/modify config
Developers can still read production logs
Web server can create both logs and uploads
No sensitive files are world-readable
Hint: Use umask, file-level permissions, and group membership strategically.
3.5.6. Summary: Key Takeaways#
3.5.6.1. Permissions Hierarchy#
Owner (u) > Group (g) > Others (o)
3.5.6.2. Quick Reference Table#
Task |
Command |
Notes |
|---|---|---|
View permissions |
|
Shows rwx permissions |
Change permissions (octal) |
|
u=7, g=5, o=5 |
Change permissions (symbolic) |
|
Add execute to owner |
Change ownership |
|
Changes both owner and group |
Change group |
|
Changes group only |
View umask |
|
Shows current umask |
Change umask |
|
Affects new file/directory creation |
Set setuid |
|
File runs as owner |
Set setgid |
|
New files inherit group |
Set sticky bit |
|
Only owner can delete their files |
3.5.6.3. Common Permission Patterns#
Pattern |
Octal |
Use Case |
|---|---|---|
Owner full, others none |
700 |
Private files/directories |
Owner rw, others r |
644 |
Source code, documentation |
Owner rwx, others rx |
755 |
Executable scripts, directories |
Owner/group rw, others none |
660 |
Shared team files |
Owner/group rwx, others none |
770 |
Shared team directory |
All full |
777 |
Temporary files (dangerous!) |
3.5.6.4. Umask Calculation#
For Files: Final permission = 666 - umask
umask 022 → files get 644 (rw-r–r–)
umask 077 → files get 600 (rw——-)
For Directories: Final permission = 777 - umask
umask 022 → dirs get 755 (rwxr-xr-x)
umask 077 → dirs get 700 (rwx——)
3.5.6.5. Security Principles#
Principle of Least Privilege: Users should have minimum permissions needed
Sensitive First: Config files, secrets → 600 or 640
Group Collaboration: Use groups and setgid for team projects
Audit Regularly: Check
ls -landfindfor permission issuesDocument Permissions: Explain why files have specific permissions
Test From User Perspective: Don’t just test as root/owner
3.5.6.6. Common Mistakes to Avoid#
❌ Making config files world-readable (644) when they contain secrets
❌ Using 777 for anything except temp directories
❌ Forgetting to set group ownership in team projects
❌ Not considering who needs to write (often requires group permissions)
❌ Setting setuid on user scripts (security risk)
❌ Changing permissions without understanding the impact