Nicht vertrauenswürdiger Suchpfad

Beschreibung

Nicht vertrauenswürdiger Suchpfad tritt auf, wenn ein Produkt kritische Ressourcen wie Bibliotheken oder ausführbare Dateien über einen extern bereitgestellten Suchpfad sucht, der auf Ressourcen zeigen kann, die nicht unter der direkten Kontrolle des Produkts stehen. Angreifer können den Suchpfad manipulieren oder bösartige Ressourcen an Orten platzieren, die vor den legitimen Ressourcen-Standorten durchsucht werden. Wenn das Produkt diese bösartigen Ressourcen lädt, führt es angreifergesteuerten Code mit den Privilegien der anfälligen Anwendung aus. Dies wird häufig durch DLL-Hijacking unter Windows ausgenutzt, wo Anwendungen bösartige DLLs aus dem aktuellen Verzeichnis oder anderen angreifergesteuerten Standorten laden.

Risiko

Schwachstellen durch nicht vertrauenswürdige Suchpfade ermöglichen Privilegieneskalation und beliebige Codeausführung. CVE-2025-12793 in ASUS ASCI ermöglicht lokalen Angreifern die Codeausführung durch Platzierung bösartiger DLLs in Pfaden, die von AsusSoftwareManagerAgent durchsucht werden. CVE-2024-6769 kombiniert Drive-Remapping mit Activation-Context-Poisoning für Windows DLL-Hijacking. CVE-2024-14012 in Revenera InstallShield ermöglicht Privilegieneskalation durch MPR.dll-Hijacking. Auch FortiClient Windows ist betroffen. Diese Angriffe sind besonders gefährlich, weil sie von niedrig-privilegiertem lokalem Zugriff auf SYSTEM-Level-Codeausführung eskalieren können und manchmal remote über SMB- oder WebDAV-Shares ausgelöst werden können.

Lösung

Verwenden Sie immer vollqualifizierte Pfade beim Laden von Bibliotheken, ausführbaren Dateien oder anderen Ressourcen. Entfernen Sie das aktuelle Verzeichnis aus dem DLL-Suchpfad mit SetDllDirectory("") unter Windows. Verwenden Sie sichere Bibliothekslade-Flags wie LOAD_LIBRARY_SEARCH_SYSTEM32. Hardcodieren Sie Suchpfade auf bekannte sichere Systemverzeichnisse. Validieren Sie, dass geladene Ressourcen von erwarteten Standorten stammen. Implementieren Sie ordnungsgemäße ACLs, um unbefugte Benutzer am Schreiben in Verzeichnisse im Suchpfad zu hindern. Verwenden Sie Anwendungsmanifeste, um exakte DLL-Versionen und -Standorte anzugeben.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleUmfang: Codeausführung

Angreifer führen beliebigen Code aus, wenn ihre bösartige Ressource von der anfälligen Anwendung geladen wird.
IntegritätUmfang: Privilegieneskalation

Code läuft mit den Privilegien der anfälligen Anwendung, oft SYSTEM- oder Administrator-Level.
VertraulichkeitUmfang: Systemkompromittierung

Erfolgreiche Ausnutzung bietet persistenten Zugriff und Möglichkeit, auf sensible Daten zuzugreifen.

Beispielcode

Anfälliger Code

// ANFÄLLIG: DLL ohne vollständigen Pfad laden
#include <windows.h>

void load_plugin() {
    // Windows sucht: App-Verzeichnis, aktuelles Verzeichnis, Systemverzeichnis, etc.
    // Angreifer kann bösartige helper.dll im aktuellen Verzeichnis platzieren
    HMODULE hLib = LoadLibrary("helper.dll");

    if (hLib) {
        // Jetzt läuft Angreifers Code mit App-Privilegien!
        typedef void (*InitFunc)();
        InitFunc init = (InitFunc)GetProcAddress(hLib, "Initialize");
        if (init) init();
    }
}
// ANFÄLLIG: Programm ohne vollständigen Pfad ausführen
#include <cstdlib>

void run_utility() {
    // system() verwendet PATH-Umgebungsvariable
    // Angreifer kann PATH modifizieren oder bösartige Utility in durchsuchtem Verzeichnis platzieren
    system("utility.exe --process");
}

// ANFÄLLIG: Python-Modulladen
// Wenn PYTHONPATH angreifergesteuert ist, können bösartige Module geladen werden
import helper  // Könnte Angreifers helper.py laden
// ANFÄLLIG: Native Bibliothek ohne vollständigen Pfad laden
public class NativeWrapper {
    static {
        // Java durchsucht java.library.path, der Angreiferpfade enthalten kann
        System.loadLibrary("nativehelper");  // Lädt nativehelper.dll
    }

    public native void processData(byte[] data);
}

Korrigierter Code

// SICHER: DLL mit vollständigem Pfad und sicheren Flags laden
#include <windows.h>
#include <libloaderapi.h>
#include <shlwapi.h>

HMODULE load_library_safely(const char* dllName) {
    // Aktuelles Verzeichnis aus DLL-Suchpfad entfernen
    SetDllDirectory("");

    // Vollständigen Pfad zum Systemverzeichnis bauen
    char systemPath[MAX_PATH];
    GetSystemDirectory(systemPath, MAX_PATH);
    PathAppend(systemPath, dllName);

    // Nur aus Systemverzeichnis laden
    HMODULE hLib = LoadLibraryEx(
        systemPath,
        NULL,
        LOAD_LIBRARY_SEARCH_SYSTEM32  // Nur system32 durchsuchen
    );

    return hLib;
}

// SICHER: Anwendungs-DLL mit explizitem Pfad laden
HMODULE load_app_library(const char* dllName) {
    char appPath[MAX_PATH];

    // Anwendungsverzeichnis abrufen
    GetModuleFileName(NULL, appPath, MAX_PATH);
    PathRemoveFileSpec(appPath);
    PathAppend(appPath, dllName);

    // Pfad ist im erwarteten Verzeichnis verifizieren (kein Traversal)
    if (!path_is_trusted(appPath)) {
        return NULL;
    }

    return LoadLibraryEx(appPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}

int path_is_trusted(const char* path) {
    // Pfad beginnt mit erwartetem Anwendungsverzeichnis verifizieren
    char expectedBase[MAX_PATH];
    GetModuleFileName(NULL, expectedBase, MAX_PATH);
    PathRemoveFileSpec(expectedBase);

    // Pfade normalisieren und vergleichen
    char normalizedPath[MAX_PATH];
    GetFullPathName(path, MAX_PATH, normalizedPath, NULL);

    return strncmp(normalizedPath, expectedBase, strlen(expectedBase)) == 0;
}
// SICHER: Programme mit vollständigen Pfaden ausführen
#include <windows.h>
#include <string>

void run_utility_safely() {
    // Vollständigen Pfad zur Utility bauen
    char systemPath[MAX_PATH];
    GetSystemDirectory(systemPath, MAX_PATH);

    std::string fullPath = std::string(systemPath) + "\\utility.exe";

    // CreateProcess statt system() für mehr Kontrolle verwenden
    STARTUPINFO si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    CreateProcess(
        fullPath.c_str(),
        NULL,  // Befehlszeile
        NULL,  // Prozess-Sicherheit
        NULL,  // Thread-Sicherheit
        FALSE, // Handles vererben
        0,     // Erstellungs-Flags
        NULL,  // Umgebung (vom Parent verwenden)
        NULL,  // Aktuelles Verzeichnis (vom Parent verwenden)
        &si,
        &pi
    );

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

// SICHER: Python mit expliziten Modulpfaden
// PYTHONPATH explizit im kontrollierten Startskript setzen
// importlib mit expliziten Pfaden verwenden
import importlib.util
import os

def load_trusted_module(module_name, expected_dir):
    module_path = os.path.join(expected_dir, f"{module_name}.py")

    # Modul ist am erwarteten Ort verifizieren
    real_path = os.path.realpath(module_path)
    if not real_path.startswith(os.path.realpath(expected_dir)):
        raise SecurityError(f"Modul-Pfad-Traversal erkannt: {module_path}")

    spec = importlib.util.spec_from_file_location(module_name, module_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module
// SICHER: Native Bibliothek mit vollständigem Pfad laden
public class SecureNativeWrapper {
    static {
        String libPath;

        // Plattformspezifischen Bibliotheksnamen und -ort bestimmen
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("win")) {
            libPath = System.getenv("ProgramFiles") +
                      "\\MyApp\\lib\\nativehelper.dll";
        } else {
            libPath = "/usr/lib/myapp/libnativehelper.so";
        }

        // Pfad ist im erwarteten Verzeichnis verifizieren
        File libFile = new File(libPath);
        try {
            String canonicalPath = libFile.getCanonicalPath();
            if (!canonicalPath.startsWith(getExpectedLibDir())) {
                throw new SecurityException("Bibliothekspfad außerhalb erwartetem Verzeichnis");
            }
        } catch (IOException e) {
            throw new RuntimeException("Bibliothekspfad kann nicht verifiziert werden", e);
        }

        // Mit explizitem vollständigem Pfad laden
        System.load(libPath);
    }

    private static String getExpectedLibDir() {
        // Erwartetes Basisverzeichnis für native Bibliotheken zurückgeben
        return System.getenv("ProgramFiles") + File.separator + "MyApp";
    }

    public native void processData(byte[] data);
}

Ausgenutzt in der Praxis

ASUS Software Manager Agent (ASUS, 2025)

CVE-2025-12793 in ASUS ASCI AsusSoftwareManagerAgent ermöglicht lokalen Angreifern die Ausführung beliebigen Codes durch Platzierung bösartiger DLLs in Pfaden, die von der anfälligen Komponente durchsucht werden, betrifft Versionen vor v3.1.49.0.

Windows Drive-Remapping-Angriff (Microsoft, 2024)

CVE-2024-6769 kombiniert Drive-Remapping mit Activation-Context-Poisoning, um DLL-Hijacking auf Windows-Systemen zu erreichen, demonstriert ausgeklügelte Ausnutzung nicht vertrauenswürdiger Suchpfade.

Revenera InstallShield (Revenera, 2024)

CVE-2024-14012 in InstallShield 2023 R1 ermöglicht Privilegieneskalation, wenn Setup.exe MPR.dll aus einem unsicheren Verzeichnis lädt, wodurch lokale Administratoren höhere Privilegien erlangen können.


Tools zum Testen/Ausnutzen

  • Procmon — Dateisystemaktivität überwachen, um DLL-Suchreihenfolge zu identifizieren.

  • DLL Hijack Auditor — DLL-Hijacking-Möglichkeiten identifizieren.

  • Robber — DLL-Hijacking-Schwachstellen-Scanner.


CVE-Beispiele


Referenzen

  1. MITRE. "CWE-426: Untrusted Search Path." https://cwe.mitre.org/data/definitions/426.html

  2. Microsoft. "Dynamic-Link Library Security." https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-security