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
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Unbefugter Zugriff - Geisterkonten ermöglichen unbefugten Zugriff, der vor Administratoren verborgen ist. |
| Rechenschaftspflicht | Umfang: Rechenschaftspflicht Verborgene Aktivitäten - Aktionen von Geisterkonten entgehen normalen Rechenschaftsmechanismen. |
| Integrität | Umfang: 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
- MITRE Corporation. "CWE-1249: Application-Level Admin Tool with Inconsistent View of Underlying Operating System." https://cwe.mitre.org/data/definitions/1249.html
- Tony Martin's "Ghost in the Shell Weakness" (2020)