Admin-Tool auf Anwendungsebene mit inkonsistenter Sicht auf das zugrunde liegende Betriebssystem

Beschreibung

Admin-Tool auf Anwendungsebene mit inkonsistenter Sicht auf das zugrunde liegende Betriebssystem tritt auf, wenn eine Verwaltungsanwendung den aktuellen Zustand des zugrunde liegenden Betriebssystems nicht korrekt darstellt, wodurch eine Diskrepanz zwischen der Anzeige des Tools und den tatsächlichen OS-Bedingungen entsteht. Webbasierte Verwaltungsoberflächen verfolgen Benutzerinformationen oft getrennt von der tatsächlichen OS-Benutzerdatenbank. Wenn diese Darstellungen auseinanderlaufen, können Angreifer die Lücke ausnutzen, indem sie "Geister"-Konten erstellen -- OS-Benutzerkonten, die für Administratoren unsichtbar sind, weil das Verwaltungstool sie nicht widerspiegelt.

Risiko

Inkonsistente Admin-Tool-Ansichten haben schwerwiegende Sicherheitsauswirkungen. Geisterkonten können erstellt werden, die Administratoren nicht sehen können. Persistente Hintertür-Konten können eingerichtet werden. Unbefugte Benutzer können Systemzugriff erlangen. Audit-Trails können unvollständig sein. Sicherheitsüberprüfungen können aktive Bedrohungen übersehen. Compliance-Verstöße können unentdeckt auftreten. Angreifer können ihre Präsenz verbergen. Die Systemintegrität kann stillschweigend kompromittiert werden.

Lösung

Aktualisieren Sie regelmäßig das OS-Modell des Admin-Tools und gleichen Sie es mit Konfigurationsdateien auf Inkonsistenzen ab. Implementieren Sie Echtzeit-Synchronisation zwischen Admin-Tools und OS-Zustand. Verwenden Sie direkte OS-Abfragen anstelle zwischengespeicherter Daten. Fügen Sie Integritätsprüfungen zwischen Tool-Zustand und OS-Zustand hinzu. Alarmieren Sie bei Inkonsistenzen zwischen Darstellungen. Protokollieren Sie alle Systemänderungen unabhängig von der Quelle. Implementieren Sie regelmäßige Abgleichprüfungen.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleUmfang: Zugriffskontrolle

Unbefugter Zugriff - Geisterkonten ermöglichen unbefugten Zugriff, der vor Administratoren verborgen ist.
RechenschaftspflichtUmfang: Rechenschaftspflicht

Verborgene Aktivitäten - Aktionen von Geisterkonten entgehen normalen Rechenschaftsmechanismen.
IntegritätUmfang: Integrität

Unerwarteter Zustand - Der Systemzustand weicht von dem ab, was Administratoren glauben.

Beispielcode und Lösung

Verwundbarer Code

# VERWUNDBAR: Admin-Oberfläche pflegt separate Benutzerdatenbank

import os

class VulnerableAdminPanel:
    def __init__(self):
        # Admin-Tool pflegt eigene Benutzerliste
        # VERWUNDBAR: Nicht mit OS synchronisiert
        self.managed_users = self.load_user_database()

    def load_user_database(self):
        # Lädt aus Datenbank des Admin-Tools, NICHT aus dem OS
        return database.query("SELECT username FROM admin_users")

    def list_users(self):
        # VERWUNDBAR: Zeigt nur Benutzer, die dem Admin-Tool bekannt sind
        # Geisterkonten in /etc/passwd werden nicht erscheinen
        return self.managed_users

    def create_user(self, username, password):
        # In Admin-Datenbank UND OS erstellen
        self.managed_users.append(username)
        database.insert("admin_users", username)
        os.system(f"useradd {username}")

    def delete_user(self, username):
        # Aus Admin-Datenbank UND OS löschen
        self.managed_users.remove(username)
        database.delete("admin_users", username)
        os.system(f"userdel {username}")

    # VERWUNDBAR: Keine Möglichkeit, Geisterkonten zu erkennen
    # Angreifer kann Benutzer direkt zu /etc/passwd hinzufügen
    # Admin-Tool zeigt ihn nicht an


# Angriff: Geisterkonto erstellen
def create_ghost_account():
    # Angreifer hat Befehlsausführung erlangt
    # Benutzer direkt im OS erstellen, Admin-Tool umgehen

    # Zu /etc/passwd hinzufügen
    os.system("echo 'ghostuser:x:1001:1001::/home/ghostuser:/bin/bash' >> /etc/passwd")

    # Zu /etc/shadow hinzufügen
    os.system("echo 'ghostuser:$6$salt$hashedpassword:18000:0:99999:7:::' >> /etc/shadow")

    # Home-Verzeichnis erstellen
    os.makedirs("/home/ghostuser", exist_ok=True)

    # Geisterkonto ist jetzt aktiv, aber für Admin-Panel unsichtbar
<!-- VERWUNDBAR: Web-Admin-Panel mit zwischengespeicherter Benutzerliste -->
<?php

class VulnerableUserManager {
    private $userCache = [];

    public function __construct() {
        // VERWUNDBAR: Benutzer beim Start in Cache laden
        $this->refreshCache();
    }

    private function refreshCache() {
        // Aus Admin-Datenbank laden
        $result = $this->db->query("SELECT * FROM users");
        while ($row = $result->fetch_assoc()) {
            $this->userCache[$row['username']] = $row;
        }
    }

    public function listUsers() {
        // VERWUNDBAR: Gibt zwischengespeicherte Daten zurück, nicht live OS-Zustand
        return array_keys($this->userCache);
    }

    public function userExists($username) {
        // VERWUNDBAR: Prüft nur Cache
        return isset($this->userCache[$username]);
    }

    // VERWUNDBAR: Keine Erkennung von OS-Änderungen
    // Geisterkonten erscheinen nicht im Cache
}

// Angriffsszenario
// 1. Angreifer nutzt Command Injection: `; useradd attacker`
// 2. Admin-Panel-Cache wird nicht aktualisiert
// 3. Benutzer attacker existiert im OS, ist aber für Admins unsichtbar
?>
// VERWUNDBAR: Admin-Service mit separatem Zustand

public class VulnerableAdminService {
    private Set<String> knownUsers = new HashSet<>();
    private Database adminDb;

    public VulnerableAdminService() {
        // VERWUNDBAR: Nur aus Admin-Datenbank initialisieren
        loadUsersFromDatabase();
    }

    private void loadUsersFromDatabase() {
        List<User> users = adminDb.getAllUsers();
        for (User u : users) {
            knownUsers.add(u.getUsername());
        }
    }

    public List<String> getAllUsers() {
        // VERWUNDBAR: Gibt Sicht des Admin-Tools zurück, nicht OS-Realität
        return new ArrayList<>(knownUsers);
    }

    public boolean deleteUser(String username) {
        // Aus Admin-DB löschen
        adminDb.deleteUser(username);
        knownUsers.remove(username);

        // Aus OS löschen
        Runtime.getRuntime().exec("userdel " + username);
        return true;
    }

    // VERWUNDBAR: Kein Abgleich mit tatsächlichen OS-Benutzern
    // Keine Erkennung unbefugter Konten
}

Sichere Lösung

# SICHER: Admin-Oberfläche mit OS-Synchronisation

import os
import pwd
import spwd
import hashlib

class SecureAdminPanel:
    def __init__(self):
        self.managed_users = set()

    def list_users(self):
        # SICHER: Immer direkt das OS abfragen
        os_users = self.get_os_users()
        admin_users = self.get_admin_database_users()

        # Auf Inkonsistenzen prüfen
        ghost_accounts = os_users - admin_users
        if ghost_accounts:
            self.alert_ghost_accounts(ghost_accounts)

        missing_from_os = admin_users - os_users
        if missing_from_os:
            self.alert_missing_users(missing_from_os)

        return os_users

    def get_os_users(self):
        # SICHER: Direkt aus dem OS lesen
        users = set()
        for user in pwd.getpwall():
            if user.pw_uid >= 1000 and user.pw_uid < 65534:  # Normale Benutzer
                users.add(user.pw_name)
        return users

    def get_admin_database_users(self):
        return set(database.query("SELECT username FROM admin_users"))

    def reconcile_users(self):
        # SICHER: Regelmäßiger Abgleich
        os_users = self.get_os_users()
        admin_users = self.get_admin_database_users()

        # Geisterkonten erkennen
        for username in os_users:
            if username not in admin_users:
                self.log_security_event(f"Geisterkonto erkannt: {username}")
                self.disable_account(username)

        # Entfernte Konten erkennen
        for username in admin_users:
            if username not in os_users:
                self.log_security_event(f"Benutzer fehlt im OS: {username}")

    def alert_ghost_accounts(self, accounts):
        for account in accounts:
            self.log_security_event(f"ALARM: Geisterkonto erkannt: {account}")
            # Geisterkonto deaktivieren
            self.disable_account(account)
            # Sicherheitsteam benachrichtigen
            self.send_security_alert(f"Unbefugtes Konto: {account}")

    def verify_system_integrity(self):
        # SICHER: Überprüfen, ob kritische Dateien manipuliert wurden
        passwd_hash = self.hash_file("/etc/passwd")
        shadow_hash = self.hash_file("/etc/shadow")

        if passwd_hash != self.known_passwd_hash:
            self.alert_file_modification("/etc/passwd")

        if shadow_hash != self.known_shadow_hash:
            self.alert_file_modification("/etc/shadow")

    def create_user(self, username, password):
        # Im OS erstellen
        result = os.system(f"useradd -m {username}")
        if result != 0:
            raise Exception("OS-Benutzer könnte nicht erstellt werden")

        # Erstellung überprüfen
        if not self.os_user_exists(username):
            raise Exception("Überprüfung der Benutzererstellung fehlgeschlagen")

        # In Admin-Datenbank erstellen
        database.insert("admin_users", username)

        # Konsistenz überprüfen
        self.reconcile_users()

    def os_user_exists(self, username):
        try:
            pwd.getpwnam(username)
            return True
        except KeyError:
            return False
<!-- SICHER: Web-Admin-Panel mit Live-OS-Abfragen -->
<?php

class SecureUserManager {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }

    public function listUsers() {
        // SICHER: Benutzer aus beiden Quellen holen und vergleichen
        $osUsers = $this->getOSUsers();
        $dbUsers = $this->getDBUsers();

        $ghostAccounts = array_diff($osUsers, $dbUsers);
        $missingAccounts = array_diff($dbUsers, $osUsers);

        if (!empty($ghostAccounts)) {
            $this->alertGhostAccounts($ghostAccounts);
        }

        if (!empty($missingAccounts)) {
            $this->alertMissingAccounts($missingAccounts);
        }

        // Vollständige Liste mit Status zurückgeben
        return [
            'users' => $osUsers,
            'ghost_accounts' => $ghostAccounts,
            'inconsistencies' => $missingAccounts
        ];
    }

    private function getOSUsers() {
        // SICHER: Direkt aus dem OS lesen
        $users = [];
        $passwd = file('/etc/passwd');
        foreach ($passwd as $line) {
            $parts = explode(':', $line);
            $uid = intval($parts[2]);
            if ($uid >= 1000 && $uid < 65534) {
                $users[] = $parts[0];
            }
        }
        return $users;
    }

    private function getDBUsers() {
        $users = [];
        $result = $this->db->query("SELECT username FROM users");
        while ($row = $result->fetch_assoc()) {
            $users[] = $row['username'];
        }
        return $users;
    }

    private function alertGhostAccounts($accounts) {
        foreach ($accounts as $account) {
            error_log("SICHERHEITSALARM: Geisterkonto erkannt: $account");
            $this->logSecurityEvent('ghost_account', $account);

            // Geisterkonto automatisch deaktivieren
            exec("usermod -L " . escapeshellarg($account));
        }
    }

    public function userExists($username) {
        // SICHER: OS direkt prüfen
        exec("id " . escapeshellarg($username), $output, $returnCode);
        return $returnCode === 0;
    }

    public function periodicReconciliation() {
        // SICHER: Per Cron für kontinuierliche Überwachung ausführen
        $this->listUsers();  // Erkennt und alarmiert bei Inkonsistenzen

        // Auch auf Dateiänderungen prüfen
        $this->checkCriticalFiles();
    }

    private function checkCriticalFiles() {
        $files = ['/etc/passwd', '/etc/shadow', '/etc/group'];
        foreach ($files as $file) {
            $currentHash = md5_file($file);
            $knownHash = $this->db->query("SELECT hash FROM file_hashes WHERE path='$file'")->fetch_assoc()['hash'];

            if ($currentHash !== $knownHash) {
                $this->logSecurityEvent('file_modified', $file);
            }
        }
    }
}
?>

CVE-Beispiele

Schwachstellen durch Geisterkonten wurden in verschiedenen webbasierten Verwaltungsoberflächen gefunden, bei denen Angreifer Systemkonten erstellen könnten, die für Administratoren unsichtbar blieben.


Verwandte CWEs

  • CWE-1250: Unsachgemäße Erhaltung der Konsistenz zwischen unabhängigen Darstellungen gemeinsamen Zustands (übergeordnet)

Referenzen

  1. MITRE Corporation. "CWE-1249: Application-Level Admin Tool with Inconsistent View of Underlying Operating System." https://cwe.mitre.org/data/definitions/1249.html
  2. Tony Martin's "Ghost in the Shell Weakness" (2020)