CWE-282: Improper Ownership Management
Overview
Improper ownership management occurs when files, directories, or resources are created with incorrect ownership (world-writable, owned by wrong user, wrong group), allowing unauthorized modification, privilege escalation, or data tampering by unintended users.
OWASP Classification
A01:2025 - Broken Access Control
Risk
High: Incorrect ownership enables unauthorized file modification, privilege escalation (modifying config files, binaries), data tampering, credential theft, persistence mechanisms, and bypassing access controls through ownership exploitation.
Remediation Steps
Core principle: Ensure correct ownership and permissions on resources; never assume safe ownership - set and verify it explicitly.
See also CWE-732 for file permissions guidance.
Identify Incorrect File Ownership
When reviewing security scan results:
- Check file creation: Look for files created without explicit ownership setting
- Review service files: Find files owned by root that should be service-owned
- Check world-writable files: Identify chmod 777 or world-writable permissions
- Review sensitive configs: Find config files with wrong ownership
- Check deployment scripts: Look for missing chown commands
Vulnerable patterns:
# Creates file as root in shared directory
sudo touch /var/www/uploads/file.txt # Owned by root!
# World-writable
chmod 777 /tmp/app-config.conf # Anyone can modify!
Set Correct Ownership on File Creation (Primary Defense)
import os
import pwd
import grp
# VULNERABLE - creates file as root
def create_config_bad():
# Running as root, creates root-owned file
with open('/etc/myapp/config.conf', 'w') as f:
f.write('secret_key=12345')
# BUG: File owned by root
# Other processes running as 'myapp' cannot read it
# SECURE - set appropriate ownership
def create_config_safe():
config_file = '/etc/myapp/config.conf'
# Create file
with open(config_file, 'w') as f:
f.write('secret_key=12345')
# Set restrictive permissions
os.chmod(config_file, 0o600) # Owner read/write only
# Set ownership to service account
myapp_uid = pwd.getpwnam('myapp').pw_uid
myapp_gid = grp.getgrnam('myapp').gr_gid
os.chown(config_file, myapp_uid, myapp_gid)
# Verify ownership
stat_info = os.stat(config_file)
assert stat_info.st_uid == myapp_uid
assert stat_info.st_gid == myapp_gid
print(f\"Config file owned by myapp user (UID {myapp_uid})\")
Bash script:
#!/bin/bash
# VULNERABLE - root ownership in multi-user directory
touch /var/www/uploads/user_file.txt
chmod 644 /var/www/uploads/user_file.txt
# BUG: owned by root, www-data cannot modify
# SECURE - correct ownership
touch /var/www/uploads/user_file.txt
chown www-data:www-data /var/www/uploads/user_file.txt
chmod 644 /var/www/uploads/user_file.txt
# Verify
ls -l /var/www/uploads/user_file.txt
# -rw-r--r-- 1 www-data www-data ... user_file.txt
Use Appropriate Permissions and Ownership
# Application files
# /var/lib/myapp/ - application data directory
# VULNERABLE - wrong ownership and permissions
sudo mkdir /var/lib/myapp
sudo chmod 755 /var/lib/myapp # Anyone can read!
# Owned by root
# SECURE - service account ownership, restricted permissions
sudo mkdir /var/lib/myapp
sudo chown myapp:myapp /var/lib/myapp
sudo chmod 750 /var/lib/myapp # Owner + group only
# Configuration files
# VULNERABLE
sudo touch /etc/myapp/database.conf
echo \"db_password=secret123\" >> /etc/myapp/database.conf
sudo chmod 644 /etc/myapp/database.conf # World-readable!
# SECURE
sudo touch /etc/myapp/database.conf
echo \"db_password=secret123\" >> /etc/myapp/database.conf
sudo chown myapp:myapp /etc/myapp/database.conf
sudo chmod 600 /etc/myapp/database.conf # Owner only
# Log files
# VULNERABLE
sudo touch /var/log/myapp/app.log
sudo chmod 666 /var/log/myapp/app.log # World-writable!
# SECURE
sudo touch /var/log/myapp/app.log
sudo chown myapp:adm /var/log/myapp/app.log
sudo chmod 640 /var/log/myapp/app.log # Owner write, group read
# Executables
# VULNERABLE
sudo cp myapp /usr/bin/
sudo chown myapp:myapp /usr/bin/myapp # Service account owns executable!
sudo chmod 777 /usr/bin/myapp # World-writable!
# SECURE
sudo cp myapp /usr/bin/
sudo chown root:root /usr/bin/myapp # Root owns executables
sudo chmod 755 /usr/bin/myapp # Not writable by others
Recommended permissions: | File Type | Owner | Group | Permissions | Example | |-----------|-------|-------|-------------|---------| | Executable | root | root | 755 (r-xr-xr-x) | /usr/bin/myapp | | Config (sensitive) | service | service | 600 (rw-------) | /etc/myapp/secrets.conf | | Config (public) | service | service | 644 (rw-r--r--) | /etc/myapp/app.conf | | Data directory | service | service | 750 (rwxr-x---) | /var/lib/myapp | | Log file | service | adm | 640 (rw-r-----) | /var/log/myapp/app.log | | Upload directory | service | service | 750 (rwxr-x---) | /var/www/uploads |
Fix Ownership in Deployment
#!/bin/bash
# Deployment script with ownership management
APP_USER=\"myapp\"
APP_GROUP=\"myapp\"
# Create service user if doesn't exist
if ! id \"$APP_USER\" &>/dev/null; then
sudo useradd -r -s /bin/false \"$APP_USER\"
fi
# Create directories with correct ownership
sudo mkdir -p /var/lib/myapp
sudo mkdir -p /var/log/myapp
sudo mkdir -p /etc/myapp
# Set ownership
sudo chown -R \"$APP_USER:$APP_GROUP\" /var/lib/myapp
sudo chown -R \"$APP_USER:$APP_GROUP\" /var/log/myapp
sudo chown -R \"$APP_USER:$APP_GROUP\" /etc/myapp
# Set permissions
sudo chmod 750 /var/lib/myapp
sudo chmod 750 /var/log/myapp
sudo chmod 750 /etc/myapp
# Install application
sudo cp myapp /usr/bin/
sudo chown root:root /usr/bin/myapp
sudo chmod 755 /usr/bin/myapp
# Install configs
sudo cp config/*.conf /etc/myapp/
sudo chown \"$APP_USER:$APP_GROUP\" /etc/myapp/*.conf
sudo chmod 640 /etc/myapp/*.conf
# Verify
echo \"Checking ownership...\"
ls -la /var/lib/myapp
ls -la /var/log/myapp
ls -la /etc/myapp
ls -l /usr/bin/myapp
echo \"Deployment complete\"
Audit and Monitor File Ownership
#!/bin/bash
# Audit script to find ownership issues
echo \"Checking for world-writable files...\"
find /var/lib/myapp /etc/myapp -type f -perm /002 -ls
echo \"Checking for files owned by root in service directories...\"
find /var/lib/myapp -user root -ls
echo \"Checking for sensitive files with wrong permissions...\"
find /etc/myapp -type f -name '*.conf' ! -perm 600 -ls
echo \"Checking for executables not owned by root...\"
find /usr/bin /usr/local/bin -type f -executable ! -user root -ls
echo \"Audit complete\"
Monitoring with auditd (Linux):
# Monitor ownership changes
sudo auditctl -w /etc/myapp/ -p wa -k config_changes
sudo auditctl -w /var/lib/myapp/ -p wa -k app_data_changes
# View audit logs
sudo ausearch -k config_changes
Test Ownership Configuration
#!/bin/bash
echo \"Testing file ownership configuration...\"
# Test 1: Service can read config
sudo -u myapp cat /etc/myapp/app.conf
if [ $? -eq 0 ]; then
echo \"\u2713 Service can read config\"
else
echo \"\u2717 Service cannot read config!\"
exit 1
fi
# Test 2: Service cannot modify executable
sudo -u myapp touch /usr/bin/myapp.test 2>/dev/null
if [ $? -ne 0 ]; then
echo \"\u2713 Service cannot write to /usr/bin\"
else
echo \"\u2717 Service can write to /usr/bin!\"
rm /usr/bin/myapp.test
exit 1
fi
# Test 3: No world-writable files
world_writable=$(find /var/lib/myapp /etc/myapp -type f -perm /002 | wc -l)
if [ $world_writable -eq 0 ]; then
echo \"\u2713 No world-writable files found\"
else
echo \"\u2717 Found $world_writable world-writable files!\"
exit 1
fi
# Test 4: Sensitive configs not world-readable
readable=$(find /etc/myapp -name '*.conf' -type f -perm /004 | wc -l)
if [ $readable -eq 0 ]; then
echo \"\u2713 Config files not world-readable\"
else
echo \"\u2717 Found $readable world-readable configs!\"
exit 1
fi
echo \"All ownership tests passed!\"
Common Vulnerable Patterns
- Creating files as root in multi-user directories
- World-writable configuration files
- Sensitive files owned by wrong user
- Not setting ownership after file creation
- Using chmod 777 (world-writable)
Security Checklist
- Files owned by appropriate service account (not root)
- Executables owned by root, not service account
- Config files have 600 or 640 permissions
- No world-writable files (chmod 777)
- Data directories owned by service account
- Log files owned by service:adm with 640 permissions
- Deployment scripts set ownership explicitly
- Audit scripts check for ownership violations