Unsichere beibehaltene vererbte Berechtigungen

Beschreibung

Unsichere beibehaltene vererbte Berechtigungen ist eine Schwachstelle, die auftritt, wenn ein Produkt einen Satz unsicherer Berechtigungen für ein Objekt erbt, beispielsweise beim Kopieren aus einer Archivdatei, ohne Benutzerbewusstsein oder Beteiligung. Anders als CWE-277, das sich mit vom erstellenden Prozess gesetzten Berechtigungen befasst, betrifft diese Schwäche Berechtigungen, die in Quellobjekte eingebettet sind (wie Dateien innerhalb von Archiven) und während Extraktions- oder Kopieroperationen beibehalten werden. Wenn Archive, Backups oder kopierte Dateien Objekte mit übermäßig permissiven Einstellungen enthalten, bleiben diese gefährlichen Berechtigungen in der Zielumgebung bestehen und erzeugen möglicherweise Sicherheitsschwachstellen.

Risiko

Beibehaltene unsichere Berechtigungen erzeugen Sicherheitsrisiken, wenn Dateien zwischen Systemen übertragen oder aus Backups wiederhergestellt werden. Archive, die auf einem System mit spezifischen Berechtigungsanforderungen erstellt wurden, können auf einem anderen System extrahiert werden, wo diese Berechtigungen unangemessen sind. Backup-Wiederherstellungen können Berechtigungsschwachstellen wieder einführen, die zuvor korrigiert wurden. Software-Distribution durch Archive kann Dateien mit den lokalen Berechtigungen des Entwicklers anstatt produktionsgerechten Einstellungen installieren. Das Risiko wird verstärkt, weil Benutzer oft annehmen, dass extrahierte Dateien sichere Standardberechtigungen haben werden, ohne zu wissen, dass Berechtigungen von der Quelle beibehalten werden. Angreifer, die Archivinhalte beeinflussen können, können Dateien mit gefährlichen Berechtigungen einbetten, die bestehen bleiben, wenn Opfer das Archiv extrahieren.

Lösung

Konfigurieren Sie Extraktions- und Kopiertools, um angemessene Berechtigungen anzuwenden, anstatt Quellberechtigungen blind beizubehalten. Verwenden Sie Archivformate und Extraktionsoptionen, die die Spezifikation von Zielberechtigungen ermöglichen. Implementieren Sie Post-Extraktions-Verifikation, um Dateiberechtigungen zu prüfen und zu korrigieren. Beim Erstellen von Archiven für Distribution setzen Sie explizit angemessene Berechtigungen innerhalb des Archivs, anstatt sich auf Quelldateiberechtigungen zu verlassen. Dokumentieren Sie Berechtigungsanforderungen für distribuierte Software und stellen Sie Installationsskripte bereit, die korrekte Berechtigungen setzen. Backup- und Wiederherstellungsverfahren sollten Berechtigungsvalidierung als Teil des Wiederherstellungsprozesses einschließen. Wenden Sie das Prinzip der geringsten Privilegien an, wenn Sie bestimmen, welche Berechtigungen während Dateioperationen beibehalten versus zurückgesetzt werden sollten.

Häufige Auswirkungen

AuswirkungDetails
Vertraulichkeit, IntegritätBereich: Vertraulichkeit, Integrität

Mit beibehaltenen unsicheren Berechtigungen extrahierte Dateien können unbefugtes Lesen sensibler Anwendungsdaten oder unbefugte Modifikation kritischer Dateien ermöglichen. Welt-lesbare Konfigurationsdateien können Anmeldedaten offenlegen, während welt-schreibbare ausführbare Dateien Code-Injection ermöglichen können.

Beispielcode

Anfälliger Code (Python)

Die folgenden Beispiele demonstrieren unsichere beibehaltene Berechtigungsschwachstellen:

# Anfällig: Behält Berechtigungen aus Archiv bei
import tarfile
import zipfile
import os

class VulnerableExtractor:

    def extract_tarball(self, archive_path, dest_dir):
        # Anfällig: extractall behält Berechtigungen aus Archiv bei
        with tarfile.open(archive_path, 'r:gz') as tar:
            tar.extractall(dest_dir)
        # Wenn Archiv welt-schreibbare Dateien enthält, bleiben sie welt-schreibbar
        # Wenn Archiv setuid-Binaries enthält, bleiben sie setuid!

    def extract_zip(self, archive_path, dest_dir):
        # Anfällig: extractall behält Unix-Berechtigungen aus zip bei
        with zipfile.ZipFile(archive_path, 'r') as zf:
            zf.extractall(dest_dir)
        # Externe Attribute mit Berechtigungen werden beibehalten

    def copy_from_backup(self, backup_path, restore_path):
        # Anfällig: shutil.copy2 behält Berechtigungen bei
        import shutil
        shutil.copy2(backup_path, restore_path)
        # Backup hatte möglicherweise unsichere Berechtigungen
# Anfällig: Shell-Skript, das Archivberechtigungen beibehält
#!/bin/bash

# Anfällig: tar behält Berechtigungen standardmäßig bei
tar -xzf software_package.tar.gz -C /opt/

# Anfällig: cp -p behält Berechtigungen bei
cp -p /backup/config.conf /etc/myapp/config.conf

# Anfällig: rsync -p behält Berechtigungen bei
rsync -ap /backup/data/ /var/lib/myapp/data/
// Anfällig: Java-Extraktion behält Berechtigungen bei
import java.io.*;
import java.util.zip.*;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class VulnerableArchiveHandler {

    public void extractZip(String archivePath, String destDir) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(
                new FileInputStream(archivePath))) {

            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                Path destPath = Paths.get(destDir, entry.getName());

                if (entry.isDirectory()) {
                    Files.createDirectories(destPath);
                } else {
                    Files.copy(zis, destPath, StandardCopyOption.REPLACE_EXISTING);

                    // Anfällig: Behält externe Attribute als Berechtigungen bei
                    int unixMode = (int) ((entry.getExtra() != null)
                        ? extractUnixMode(entry) : 0644);

                    // Wendet beliebige Berechtigungen aus Archiv an
                    setUnixPermissions(destPath, unixMode);
                }
            }
        }
    }
}

Korrigierter Code (Python)

# Korrigiert: Wendet angemessene Berechtigungen während Extraktion an
import tarfile
import zipfile
import os
import stat

class SecureExtractor:

    # Sichere Berechtigungslimits definieren
    MAX_FILE_PERMS = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH  # 0644
    MAX_DIR_PERMS = stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH  # 0755
    MAX_EXEC_PERMS = stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH  # 0755

    # Explizit zu verweigernde Berechtigungen
    DENIED_PERMS = stat.S_ISUID | stat.S_ISGID  # Kein setuid/setgid

    def extract_tarball_safely(self, archive_path, dest_dir):
        with tarfile.open(archive_path, 'r:gz') as tar:
            for member in tar.getmembers():
                # Berechtigungen bereinigen
                self._sanitize_tar_member(member)

                # Auch Path Traversal verhindern
                if member.name.startswith('/') or '..' in member.name:
                    raise SecurityError(f"Unsicherer Pfad im Archiv: {member.name}")

                tar.extract(member, dest_dir)

    def _sanitize_tar_member(self, member):
        # Setuid/setgid-Bits entfernen
        member.mode &= ~self.DENIED_PERMS

        if member.isdir():
            # Verzeichnisberechtigungen limitieren
            member.mode = member.mode & self.MAX_DIR_PERMS
        elif member.mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
            # Ausführbare Datei - auf maximale ausführbare Berechtigungen limitieren
            member.mode = member.mode & self.MAX_EXEC_PERMS
        else:
            # Reguläre Datei - auf maximale Dateiberechtigungen limitieren
            member.mode = member.mode & self.MAX_FILE_PERMS

    def extract_zip_safely(self, archive_path, dest_dir, default_mode=0o644):
        with zipfile.ZipFile(archive_path, 'r') as zf:
            for info in zf.infolist():
                # Path Traversal verhindern
                if info.filename.startswith('/') or '..' in info.filename:
                    raise SecurityError(f"Unsicherer Pfad: {info.filename}")

                # Datei extrahieren
                extracted = zf.extract(info, dest_dir)

                # Sichere Berechtigungen anwenden unabhängig von Archivinhalten
                if info.is_dir():
                    os.chmod(extracted, 0o755)
                else:
                    os.chmod(extracted, default_mode)

    def copy_from_backup_safely(self, backup_path, restore_path, mode=0o640):
        """Dateiinhalt kopieren ohne Quellberechtigungen beizubehalten"""
        import shutil

        # Nur Inhalt kopieren, nicht Berechtigungen
        shutil.copy(backup_path, restore_path)  # copy, nicht copy2

        # Explizit sichere Berechtigungen anwenden
        os.chmod(restore_path, mode)

        # Angemessenes Eigentum setzen
        import pwd
        app_user = pwd.getpwnam('myapp')
        os.chown(restore_path, app_user.pw_uid, app_user.pw_gid)
# Korrigiert: Shell-Skript mit Berechtigungsbereinigung
#!/bin/bash

# Extrahieren ohne Berechtigungen beizubehalten
tar --no-same-permissions --no-same-owner -xzf software_package.tar.gz -C /opt/

# Angemessene Berechtigungen nach Extraktion setzen
find /opt/extracted -type f -exec chmod 644 {} \;
find /opt/extracted -type d -exec chmod 755 {} \;
find /opt/extracted -name "*.sh" -exec chmod 755 {} \;

# Inhalt kopieren ohne Berechtigungen beizubehalten
cp /backup/config.conf /etc/myapp/config.conf
chmod 640 /etc/myapp/config.conf
chown root:myapp /etc/myapp/config.conf

# rsync ohne Berechtigungsbeibehaltung
rsync -a --no-perms /backup/data/ /var/lib/myapp/data/
# Oder explizit Berechtigungen setzen
rsync -a --chmod=D755,F644 /backup/data/ /var/lib/myapp/data/
// Korrigiert: Java-Extraktion mit Berechtigungsdurchsetzung
import java.io.*;
import java.util.zip.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.*;

public class SecureArchiveHandler {

    private static final Set<PosixFilePermission> SAFE_FILE_PERMS =
        PosixFilePermissions.fromString("rw-r--r--");
    private static final Set<PosixFilePermission> SAFE_DIR_PERMS =
        PosixFilePermissions.fromString("rwxr-xr-x");
    private static final Set<PosixFilePermission> SAFE_EXEC_PERMS =
        PosixFilePermissions.fromString("rwxr-xr-x");

    public void extractZipSecurely(String archivePath, String destDir) throws IOException {
        Path destPath = Paths.get(destDir).toRealPath();

        try (ZipInputStream zis = new ZipInputStream(
                new FileInputStream(archivePath))) {

            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                // Path Traversal verhindern
                Path entryPath = destPath.resolve(entry.getName()).normalize();
                if (!entryPath.startsWith(destPath)) {
                    throw new SecurityException("Path Traversal erkannt: " + entry.getName());
                }

                if (entry.isDirectory()) {
                    Files.createDirectories(entryPath,
                        PosixFilePermissions.asFileAttribute(SAFE_DIR_PERMS));
                } else {
                    // Sicherstellen, dass übergeordnetes Verzeichnis existiert
                    Files.createDirectories(entryPath.getParent());

                    // Inhalt extrahieren
                    Files.copy(zis, entryPath, StandardCopyOption.REPLACE_EXISTING);

                    // Sichere Berechtigungen anwenden - Archivberechtigungen ignorieren
                    Set<PosixFilePermission> perms = isExecutable(entry.getName())
                        ? SAFE_EXEC_PERMS : SAFE_FILE_PERMS;
                    Files.setPosixFilePermissions(entryPath, perms);
                }
            }
        }
    }

    private boolean isExecutable(String filename) {
        return filename.endsWith(".sh") || filename.endsWith(".py")
            || filename.equals("bin") || filename.contains("/bin/");
    }
}

Die Korrektur wendet sichere Berechtigungen während der Extraktion an, anstatt potenziell gefährliche Berechtigungen aus der Archivquelle beizubehalten.


Ausgenutzt in der Praxis

Archivbasierte Berechtigungsangriffe (Software-Distribution, Fortlaufend)

Bösartige Archive, die über kompromittierte Repositories oder MITM-Angriffe distribuiert wurden, enthielten Dateien mit setuid-Bits oder welt-schreibbaren Berechtigungen. Wenn Opfer diese Archive extrahierten, blieben die gefährlichen Berechtigungen bestehen, was Privilegieneskalation oder Backdoor-Installation ermöglichte.

Backup-Wiederherstellungsschwachstellen (Unternehmensumgebungen, Fortlaufend)

Backup-Wiederherstellungen, die Berechtigungen aus älteren Backups beibehielten, haben Berechtigungsschwachstellen wieder eingeführt, die zuvor behoben worden waren. Organisationen stellten aus Backups wieder her, die vor Sicherheitshärtung erstellt wurden, und brachten Systeme in anfällige Zustände zurück.

Export/Import-Berechtigungsleck (Anwendungsmigration, Historisch)

CVE-2005-1724 dokumentierte Software, die spezifizierte Berechtigungen während Exportoperationen nicht beachtete, was dazu führte, dass unsichere Berechtigungen beibehalten wurden, wenn Daten in neue Systeme importiert wurden.


Tools zum Testen/Ausnutzen

  • tar-Inspektionstools — Befehle wie tar -tvf zum Inspizieren von Berechtigungen innerhalb von Archiven vor Extraktion.

  • bsdtar — Archivtool mit Optionen zur Steuerung der Berechtigungsbeibehaltung.

  • Archiv-Berechtigungsanalysatoren — Tools zum Analysieren und Modifizieren von Archivinhalten.


CVE-Beispiele

  • CVE-2005-1724 — Software beachtete spezifizierte Berechtigungen während Exportoperationen nicht, unsichere Berechtigungen beibehaltend.

Referenzen

  1. MITRE Corporation. "CWE-278: Insecure Preserved Inherited Permissions." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/278.html

  2. GNU tar manual. "Handling File Permissions." https://www.gnu.org/software/tar/manual/

  3. OWASP. "Zip Slip Vulnerability." https://snyk.io/research/zip-slip-vulnerability