Erstellung temporärer Datei in Verzeichnis mit unsicheren Berechtigungen

Beschreibung

Erstellung temporärer Datei in Verzeichnis mit unsicheren Berechtigungen ist eine Schwachstelle, die auftritt, wenn eine Anwendung temporäre Dateien in einem Verzeichnis erstellt, dessen Berechtigungen unbeabsichtigten Akteuren ermöglichen, die Existenz der Datei festzustellen oder anderweitig auf diese Datei zuzugreifen. Übliche gemeinsam genutzte Verzeichnisse wie /tmp auf Unix oder C:\Windows\Temp unter Windows sind für alle Benutzer zugänglich, wodurch alle dort erstellten Dateien potenziell für Angreifer sichtbar sind. Selbst wenn individuelle Dateiberechtigungen sicher sind, können die Verzeichnisberechtigungen Angreifern ermöglichen, Dateien aufzuzählen oder symbolische Link-Angriffe durchzuführen.

Risiko

Das Erstellen temporärer Dateien in für alle zugänglichen Verzeichnissen offenbart Informationen über das Anwendungsverhalten. Angreifer können feststellen, welche Anwendungen verwendet werden, indem sie das Verzeichnis auf neue Dateien überwachen. Durch Korrelation temporärer Dateien mit laufenden Prozessen können Gegner Benutzeraktivitäten ableiten und gezielte Angriffe planen. Selbst wenn Dateiinhalte geschützt sind, können Dateinamen und Zeitpunkt der Erstellung sensible Informationen preisgeben. Symbolische Link-Angriffe in gemeinsam genutzten Verzeichnissen können Dateioperationen zu angreiferkontrollierten Orten umleiten. Diese Aufklärungsfähigkeit hilft bei Privilegieneskalation und gezielter Ausnutzung.

Lösung

Speichern Sie sensible temporäre Dateien in nicht für alle lesbaren Verzeichnissen, vorzugsweise in Benutzer-spezifischen Verzeichnissen innerhalb des Home-Ordners des Benutzers. Erstellen Sie ein privates Verzeichnis mit restriktiven Berechtigungen (0700) für die temporären Dateien der Anwendung. Vermeiden Sie die Verwendung systemweiter temporärer Verzeichnisse für sensible Operationen. Verwenden Sie moderne Sprach-APIs, die die Angabe benutzerdefinierter Verzeichnisse für temporäre Dateien unterstützen. Stellen Sie sicher, dass das übergeordnete Verzeichnis angemessene Berechtigungen hat, bevor Sie temporäre Dateien erstellen. Erwägen Sie die Verwendung von speicherbasiertem temporärem Storage für hochsensible Daten.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitUmfang: Vertraulichkeit

Angreifer gewinnen Informationen darüber, was der Benutzer tut, durch Sichtbarkeit von temporären Anwendungsdateien.

Beispielcode

Anfälliger Code

// Anfällig: Erstellt Temp-Datei im für alle lesbaren /tmp
void vulnerable_shared_dir() {
    char template[] = "/tmp/myapp.XXXXXX";
    int fd = mkstemp(template);

    if (fd >= 0) {
        // Selbst mit 0600 Berechtigungen können Angreifer:
        // - Sehen dass die Datei in /tmp existiert
        // - Wissen dass die Anwendung läuft
        // - Timing-Angriffe versuchen
        write(fd, secret_data, strlen(secret_data));
        close(fd);
        unlink(template);
    }
}

// Anfällig: Vorhersagbares Unterverzeichnis in /tmp
void vulnerable_predictable_dir() {
    char dirname[] = "/tmp/myapp";
    mkdir(dirname, 0755);  // Für alle lesbares Verzeichnis!

    char filepath[256];
    snprintf(filepath, sizeof(filepath), "%s/data.tmp", dirname);

    int fd = open(filepath, O_CREAT | O_WRONLY, 0600);
    // Verzeichnis offenbart dass myapp läuft
}
// Anfällig: System-Temp-Verzeichnis verwenden
import java.io.*;
import java.nio.file.*;

public class VulnerableTempDir {
    public void processSecret(String data) throws IOException {
        // Anfällig: System-Temp-Verzeichnis ist für alle zugänglich
        Path temp = Files.createTempFile("sensitive", ".tmp");

        // Datei ist in /tmp oder C:\Windows\Temp
        // Andere Benutzer können sehen dass sie existiert
        Files.writeString(temp, data);
    }

    public void createWorkDir() throws IOException {
        // Anfällig: Erstellt Verzeichnis im gemeinsam genutzten /tmp
        Path workDir = Files.createTempDirectory("myapp");

        // Verzeichnislisting zeigt dass myapp läuft
        Path dataFile = workDir.resolve("data.txt");
        Files.writeString(dataFile, "secret");
    }
}
# Anfällig: Gemeinsames /tmp-Verzeichnis verwenden
import tempfile
import os

def vulnerable_default_temp():
    # Anfällig: tempfile.gettempdir() gibt /tmp zurück
    with tempfile.NamedTemporaryFile(delete=False) as f:
        f.write(b"sensible daten")
        # Datei in /tmp für alle Benutzer sichtbar
        return f.name

def vulnerable_tmp_socket():
    # Anfällig: Socket in für alle zugänglichem Verzeichnis
    import socket

    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.bind("/tmp/myapp.sock")  # Jeder Benutzer kann sehen dass dies existiert

Korrigierter Code

// Korrigiert: Temp-Datei in privatem Benutzerverzeichnis erstellen
#include <pwd.h>
#include <unistd.h>

void secure_private_dir() {
    struct passwd *pw = getpwuid(getuid());
    char dirpath[PATH_MAX];
    char filepath[PATH_MAX];

    // Korrigiert: Privates Verzeichnis im Home des Benutzers verwenden
    snprintf(dirpath, sizeof(dirpath), "%s/.myapp/tmp", pw->pw_dir);

    // Privates Verzeichnis erstellen
    mkdir(pw->pw_dir, 0700);  // Sicherstellen dass Home-Verzeichnis existiert
    snprintf(dirpath, sizeof(dirpath), "%s/.myapp", pw->pw_dir);
    mkdir(dirpath, 0700);
    snprintf(dirpath, sizeof(dirpath), "%s/.myapp/tmp", pw->pw_dir);
    mkdir(dirpath, 0700);

    // Temp-Datei in privatem Verzeichnis erstellen
    snprintf(filepath, sizeof(filepath), "%s/data.XXXXXX", dirpath);
    int fd = mkstemp(filepath);

    if (fd >= 0) {
        write(fd, secret_data, strlen(secret_data));
        close(fd);
        unlink(filepath);
    }
}

// Korrigiert: XDG-Runtime-Verzeichnis verwenden wenn verfügbar
void secure_runtime_dir() {
    const char *runtime_dir = getenv("XDG_RUNTIME_DIR");
    char template[PATH_MAX];

    if (runtime_dir && access(runtime_dir, W_OK) == 0) {
        // Korrigiert: XDG_RUNTIME_DIR ist benutzer-privat
        snprintf(template, sizeof(template), "%s/myapp.XXXXXX", runtime_dir);
    } else {
        // Fallback auf Home-Verzeichnis
        struct passwd *pw = getpwuid(getuid());
        snprintf(template, sizeof(template), "%s/.myapp.XXXXXX", pw->pw_dir);
    }

    int fd = mkstemp(template);
    // ...
}
// Korrigiert: Privates Verzeichnis für Temp-Dateien verwenden
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Set;

public class SecureTempDir {
    private Path privateTempDir;

    public SecureTempDir() throws IOException {
        // Korrigiert: Privates Temp-Verzeichnis im Benutzer-Home erstellen
        Path userHome = Paths.get(System.getProperty("user.home"));
        Path appDir = userHome.resolve(".myapp").resolve("tmp");

        if (!Files.exists(appDir)) {
            Set<PosixFilePermission> perms =
                PosixFilePermissions.fromString("rwx------");
            Files.createDirectories(appDir,
                PosixFilePermissions.asFileAttribute(perms));
        }

        this.privateTempDir = appDir;
    }

    public void processSecret(String data) throws IOException {
        // Korrigiert: Temp-Datei im privaten Verzeichnis erstellen
        Set<PosixFilePermission> perms =
            PosixFilePermissions.fromString("rw-------");

        Path temp = Files.createTempFile(privateTempDir, "sensitive", ".tmp",
            PosixFilePermissions.asFileAttribute(perms));

        try {
            Files.writeString(temp, data);
            processFile(temp);
        } finally {
            Files.deleteIfExists(temp);
        }
    }
}
# Korrigiert: Privates Verzeichnis für Temp-Dateien verwenden
import os
import tempfile
import stat

def get_private_temp_dir():
    """Privates Temp-Verzeichnis für diese App abrufen oder erstellen."""
    # Zuerst XDG_RUNTIME_DIR versuchen (benutzer-privat auf Linux)
    runtime_dir = os.environ.get('XDG_RUNTIME_DIR')
    if runtime_dir and os.access(runtime_dir, os.W_OK):
        private_dir = os.path.join(runtime_dir, 'myapp')
    else:
        # Fallback auf Home-Verzeichnis
        private_dir = os.path.expanduser('~/.myapp/tmp')

    # Mit restriktiven Berechtigungen erstellen
    os.makedirs(private_dir, mode=0o700, exist_ok=True)

    # Berechtigungen verifizieren
    mode = os.stat(private_dir).st_mode
    if mode & (stat.S_IRWXG | stat.S_IRWXO):
        raise SecurityError("Temp-Verzeichnis hat unsichere Berechtigungen")

    return private_dir

def secure_temp_file():
    # Korrigiert: Privates Verzeichnis verwenden
    private_dir = get_private_temp_dir()

    with tempfile.NamedTemporaryFile(dir=private_dir, delete=True) as f:
        f.write(b"sensible daten")
        process_file(f.name)

def secure_unix_socket():
    import socket

    # Korrigiert: Socket in privatem Verzeichnis
    private_dir = get_private_temp_dir()
    socket_path = os.path.join(private_dir, 'myapp.sock')

    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.bind(socket_path)
    os.chmod(socket_path, 0o600)

CVE-Beispiele

  • CVE-2022-27818 — Rust-Hotkey-Daemon erstellt Domain-Socket in /tmp, der für jeden Benutzer zugänglich ist.
  • CVE-2021-21290 — Java-Framework verwendet File.createTempFile() mit unsicheren Standardberechtigungen im gemeinsamen Verzeichnis.

Referenzen

  1. MITRE Corporation. "CWE-379: Creation of Temporary File in Directory with Insecure Permissions." https://cwe.mitre.org/data/definitions/379.html
  2. freedesktop.org. "XDG Base Directory Specification." https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html