Skip to content

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

Additional Resources