Fehlerhafte Eigentümerzuweisung

Beschreibung

Fehlerhafte Eigentümerzuweisung ist eine Schwachstelle, bei der Software einen Eigentümer einer Ressource zuweist, der außerhalb des beabsichtigten Kontrollbereichs liegt. Wenn der Ressourceneigentümer falsch einem anderen Benutzer, einer anderen Gruppe oder Entität zugewiesen wird, entstehen Wege für nicht autorisierte Akteure, auf Ressourcen zuzugreifen, sie zu modifizieren oder zu löschen, über die sie keine Kontrolle haben sollten. Dies tritt häufig bei Dateieigentümerschaft während der Installation, Prozesseigentümerschaft nach Privilegienänderungen oder Datenbankobjekt-Eigentümerschaft bei der Erstellung auf. Die falsch konfigurierte Eigentümerschaft untergräbt das Sicherheitsmodell, das die Ressource schützt.

Risiko

Fehlerhafte Eigentümerzuweisung schafft Privilegieneskalations- und unbefugte Zugriffs-Schwachstellen. Dateien, die unprivilegierten Benutzern gehören, können modifiziert werden, um bösartigen Code einzuschleusen, der mit erhöhten Privilegien ausgeführt wird, wenn die Dateien später von Systemprozessen verwendet werden. Ressourcen mit falscher Gruppeneigentümerschaft können für unbeabsichtigte Benutzer in dieser Gruppe zugänglich sein. Symbolische Link-Eigentümer-Probleme können es Angreifern ermöglichen, Link-Ziele zu manipulieren. Beim Abmelden oder Sitzungswechsel kann das Versäumnis, die ordnungsgemäße Eigentümerschaft wiederherzustellen, Ressourcen für nachfolgende Benutzer zugänglich machen. Das Risiko erstreckt sich auf Konfigurationsdateien, ausführbare Dateien, Datendateien und jede Ressource, bei der die Eigentümerschaft die Zugriffsrechte bestimmt.

Lösung

Setzen Sie die korrekte Eigentümerschaft sofort bei der Ressourcenerstellung. Überprüfen Sie die Eigentümerschaftseinstellungen während der Installation und Bereitstellung. Verwenden Sie das Prinzip der geringsten Privilegien - weisen Sie die Eigentümerschaft der am stärksten eingeschränkten Entität zu, die noch den ordnungsgemäßen Betrieb ermöglicht. Prüfen Sie regelmäßig die Ressourceneigentümerschaft und -berechtigungen. Seien Sie beim Umgang mit symbolischen Links explizit, ob Operationen den Link oder das Ziel betreffen. Stellen Sie die ordnungsgemäße Eigentümerschaft nach Abschluss von Privilegienoperationen wieder her. Verwenden Sie Konfigurationsmanagement-Tools, um die korrekte Eigentümerschaft systemübergreifend durchzusetzen. Testen Sie Eigentümerschaftseinstellungen als Teil der Sicherheitsverifikation.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Anwendungsdaten lesen - Ressourcen mit falscher Eigentümerschaft können von nicht autorisierten Benutzern lesbar sein.
IntegritätBereich: Integrität

Anwendungsdaten modifizieren - Falsch zugewiesene Ressourcen können von nicht autorisierten Benutzern modifiziert werden.
ZugriffskontrolleBereich: Zugriffskontrolle

Privilegien erlangen oder Identität annehmen - Eigentümerschaftsfehler können Privilegieneskalation ermöglichen.

Beispielcode

Verwundbarer Code

// Verwundbar: Datei mit falscher Eigentümerschaft erstellt
#include <stdio.h>
#include <sys/stat.h>
#include <pwd.h>
#include <unistd.h>

void vulnerable_create_config() {
    // Konfigurationsdatei erstellen
    FILE* f = fopen("/etc/myapp/config.conf", "w");
    if (f) {
        fprintf(f, "setting=value\n");
        fclose(f);
    }

    // Verwundbar: Datei gehört dem, der diesen Code ausführt
    // Wenn als root ausgeführt, gehört sie root
    // Wenn Installer als anderer Benutzer ausgeführt wird, ist Eigentümerschaft falsch

    // Noch schlimmer: Explizit falsche Eigentümerschaft setzen
    struct passwd* nobody = getpwnam("nobody");
    if (nobody) {
        // Verwundbar: Kritische Konfiguration gehört 'nobody'
        // Jeder Prozess, der als 'nobody' läuft, kann sie modifizieren
        chown("/etc/myapp/config.conf", nobody->pw_uid, nobody->pw_gid);
    }
}

// Verwundbar: Symbolischer Link Eigentümerschaftsverwirrung
void vulnerable_symlink_chown(const char* path, uid_t uid, gid_t gid) {
    // Verwundbar: chown folgt Symlinks!
    // Wenn path ein Symlink ist, ändert dies die Eigentümerschaft des ZIELS
    chown(path, uid, gid);
    // Angreifer erstellt Symlink zu /etc/passwd, wir ändern dessen Eigentümerschaft
}
# Verwundbar: Installationsskript mit falscher Eigentümerschaft
import os
import shutil

def vulnerable_install():
    # Anwendungsverzeichnis erstellen
    app_dir = "/opt/myapp"
    os.makedirs(app_dir, exist_ok=True)

    # Binary kopieren
    shutil.copy("myapp", os.path.join(app_dir, "myapp"))

    # Verwundbar: Eigentümerschaft auf unprivilegierten Benutzer für Schreibbarkeit setzen
    # Aber diese Binary könnte von root ausgeführt werden!
    os.chown(os.path.join(app_dir, "myapp"), 1000, 1000)  # uid 1000

    # Angreifer (uid 1000) kann jetzt die Binary ersetzen
    # Wenn root sie ausführt, wird Angreifers Code als root ausgeführt

# Verwundbar: Datenbank-Eigentümerschaft (CVE-2003-0265 Muster)
def vulnerable_create_db():
    import sqlite3

    # Datenbank mit Standardberechtigungen erstellen
    db_path = "/var/lib/myapp/data.db"
    conn = sqlite3.connect(db_path)

    # Verwundbar: Datenbankdatei wird mit Eigentümerschaft des aktuellen Benutzers erstellt
    # Wenn als root ausgeführt, ist Datei weltweit lesbar
    # Wenn als Web-Benutzer ausgeführt, könnte sie für andere Web-Apps zugänglich sein

    conn.execute("CREATE TABLE secrets (key TEXT, value TEXT)")
    conn.close()
#!/bin/bash
# Verwundbar: Installationsskript mit Eigentümerschaftsproblemen

# Verwundbar: Verzeichnisse mit falscher Eigentümerschaft erstellen
mkdir -p /opt/myapp/bin
mkdir -p /opt/myapp/logs

# Verwundbar: bin-Verzeichnis gehört normalem Benutzer
# CVE-2007-4238 Muster - Binary kann ersetzt werden
chown -R myuser:mygroup /opt/myapp/bin

# Verwundbar: Log-Verzeichnis weltweit beschreibbar
chmod 777 /opt/myapp/logs
# Jeder Benutzer kann Logs schreiben oder löschen, potentiell Angriffe verbergend

# Verwundbar: Konfigurationsdatei mit falscher Gruppe
chown root:users /etc/myapp.conf
chmod 660 /etc/myapp.conf
# Alle Benutzer in 'users'-Gruppe können Konfiguration modifizieren
// Verwundbar: Java-Dateierstellung mit falscher Eigentümerschaft
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class VulnerableOwnership {

    public void vulnerableCreateFile() throws IOException {
        Path path = Paths.get("/tmp/myapp/sensitive.dat");

        // Datei erstellen - Eigentümerschaft durch Prozessbenutzer bestimmt
        Files.createFile(path);

        // Verwundbar: Eigentümerschaft ohne Validierung auf bestimmten Benutzer setzen
        UserPrincipal user = path.getFileSystem()
            .getUserPrincipalLookupService()
            .lookupPrincipalByName("daemon");

        // Änderung zu 'daemon' Benutzer - aber warum?
        // Dieses Dienstkonto könnte von mehreren Anwendungen geteilt werden
        Files.setOwner(path, user);
    }
}

Lösungscode

// Behoben: Ordnungsgemäße Eigentümerzuweisung
#include <stdio.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <fcntl.h>

void secure_create_config() {
    // Behoben: Privilegien vor Erstellung abgeben wenn als root ausgeführt
    // Oder mit expliziter Eigentümerschaft erstellen

    // Beabsichtigten Eigentümer holen
    struct passwd* app_user = getpwnam("myapp");
    struct group* app_group = getgrnam("myapp");

    if (!app_user || !app_group) {
        return;  // Anwendungsbenutzer/-gruppe muss existieren
    }

    // Datei mit restriktiven Berechtigungen erstellen
    int fd = open("/etc/myapp/config.conf",
                  O_CREAT | O_WRONLY | O_TRUNC,
                  S_IRUSR | S_IWUSR);  // 600 - nur Eigentümer

    if (fd < 0) return;

    // Behoben: Korrekte Eigentümerschaft für Anwendung setzen
    fchown(fd, app_user->pw_uid, app_group->gr_gid);

    write(fd, "setting=value\n", 14);
    close(fd);
}

// Behoben: lchown für Symlink-sichere Eigentümerschaftsänderung verwenden
void secure_symlink_chown(const char* path, uid_t uid, gid_t gid) {
    struct stat st;

    // Behoben: Zuerst prüfen ob es ein Symlink ist
    if (lstat(path, &st) == 0) {
        if (S_ISLNK(st.st_mode)) {
            // Behoben: lchown verwenden um Link-Eigentümerschaft zu ändern, nicht Ziel
            lchown(path, uid, gid);
        } else {
            // Reguläre Datei - chown sicher verwendbar
            chown(path, uid, gid);
        }
    }
}

// Alternative: Operationen auf Symlinks ablehnen
void secure_chown_no_symlinks(const char* path, uid_t uid, gid_t gid) {
    struct stat st;

    if (lstat(path, &st) != 0) return;

    if (S_ISLNK(st.st_mode)) {
        // Behoben: Eigentümerschaft durch Symlinks nicht ändern
        fprintf(stderr, "Ablehnung: chown auf Symlink: %s\n", path);
        return;
    }

    chown(path, uid, gid);
}
# Behoben: Ordnungsgemäße Installation mit korrekter Eigentümerschaft
import os
import shutil
import pwd
import grp
import stat

def secure_install():
    app_dir = "/opt/myapp"

    # Korrekten Benutzer/Gruppe holen
    app_user = pwd.getpwnam("myapp")
    app_group = grp.getgrnam("myapp")

    # Verzeichnis mit korrekter Eigentümerschaft erstellen
    os.makedirs(app_dir, exist_ok=True)
    os.chown(app_dir, app_user.pw_uid, app_group.gr_gid)
    os.chmod(app_dir, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP)  # 750

    # Binary kopieren
    bin_path = os.path.join(app_dir, "myapp")
    shutil.copy("myapp", bin_path)

    # Behoben: Binary gehört root, nicht modifizierbar durch App-Benutzer
    os.chown(bin_path, 0, 0)  # root:root
    os.chmod(bin_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP |
                       stat.S_IROTH | stat.S_IXOTH)  # 755

    # Datenverzeichnis erstellen, das App-Benutzer gehört
    data_dir = os.path.join(app_dir, "data")
    os.makedirs(data_dir, exist_ok=True)
    os.chown(data_dir, app_user.pw_uid, app_group.gr_gid)
    os.chmod(data_dir, stat.S_IRWXU)  # 700 - nur App-Benutzer

# Behoben: Sichere Datenbankerstellung
def secure_create_db():
    import sqlite3
    import tempfile

    db_path = "/var/lib/myapp/data.db"
    db_dir = os.path.dirname(db_path)

    # Sicherstellen, dass Verzeichnis mit korrekten Berechtigungen existiert
    os.makedirs(db_dir, mode=0o700, exist_ok=True)

    # Anwendungsbenutzer holen
    app_user = pwd.getpwnam("myapp")
    os.chown(db_dir, app_user.pw_uid, app_user.pw_gid)

    # Datenbank erstellen
    conn = sqlite3.connect(db_path)
    conn.execute("CREATE TABLE IF NOT EXISTS secrets (key TEXT, value TEXT)")
    conn.close()

    # Behoben: Korrekte Eigentümerschaft und Berechtigungen setzen
    os.chown(db_path, app_user.pw_uid, app_user.pw_gid)
    os.chmod(db_path, stat.S_IRUSR | stat.S_IWUSR)  # 600
#!/bin/bash
# Behoben: Sicheres Installationsskript

# Verzeichnisse mit korrekter Eigentümerschaft erstellen
mkdir -p /opt/myapp/bin
mkdir -p /opt/myapp/logs
mkdir -p /opt/myapp/data

# Behoben: Binaries gehören root, nicht modifizierbar
chown root:root /opt/myapp/bin
chmod 755 /opt/myapp/bin

# Behoben: Logs gehören Anwendungsbenutzer, eingeschränkte Berechtigungen
chown myapp:myapp /opt/myapp/logs
chmod 750 /opt/myapp/logs  # Nur Eigentümer und Gruppe können zugreifen

# Behoben: Datenverzeichnis gehört Anwendungsbenutzer
chown myapp:myapp /opt/myapp/data
chmod 700 /opt/myapp/data  # Nur Anwendungsbenutzer

# Behoben: Konfiguration gehört root, lesbar durch App-Gruppe
chown root:myapp /etc/myapp.conf
chmod 640 /etc/myapp.conf  # root schreibt, myapp-Gruppe liest
// Behoben: Java mit ordnungsgemäßer Eigentümerschaftsberücksichtigung
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class SecureOwnership {

    public void secureCreateFile(String expectedOwner) throws IOException {
        Path path = Paths.get("/var/lib/myapp/data.dat");

        // Behoben: Zuerst mit restriktiven Berechtigungen erstellen
        Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");
        FileAttribute<Set<PosixFilePermission>> attr =
            PosixFilePermissions.asFileAttribute(perms);

        Files.createFile(path, attr);

        // Behoben: Verifizieren, dass Eigentümerschaft dem Erwarteten entspricht
        UserPrincipal currentOwner = Files.getOwner(path);

        if (!currentOwner.getName().equals(expectedOwner)) {
            // Nur ändern wenn nötig und Ziel validieren
            if (isValidApplicationUser(expectedOwner)) {
                UserPrincipal newOwner = path.getFileSystem()
                    .getUserPrincipalLookupService()
                    .lookupPrincipalByName(expectedOwner);
                Files.setOwner(path, newOwner);
            } else {
                throw new SecurityException("Ungültiger Eigentümer: " + expectedOwner);
            }
        }
    }

    private boolean isValidApplicationUser(String username) {
        // Nur bestimmte Anwendungsbenutzer erlauben
        return "myapp".equals(username) || "myapp-worker".equals(username);
    }
}

CVE-Beispiele

  • CVE-2024-43199: Binaries mit unsicherer Benutzer-/Gruppeneigentümerschaft installiert, die Modifikation ermöglicht.
  • CVE-2007-4238: Programm mit bin-Eigentümer installiert, ermöglicht Benutzern Modifikation der ausführbaren Datei.
  • CVE-2007-1716: Ressourceneigentümerschaft beim Abmelden nicht wiederhergestellt, ermöglicht Privilegieneskalation.
  • CVE-2005-3148: Symbolische Links mit falscher uid/gid wiederhergestellt.
  • CVE-2005-1064: Eigentümerschaft auf Symlink-Zielen statt Symlinks selbst geändert.

Referenzen

  1. MITRE Corporation. "CWE-708: Incorrect Ownership Assignment." https://cwe.mitre.org/data/definitions/708.html
  2. CWE-282: Improper Ownership Management.
  3. CERT C Coding Standard. "FIO01-C. Be careful using functions that use file names for identification."