Verwendung von fest codierten Passwörtern

Beschreibung

Verwendung von fest codierten Passwörtern ist eine Schwachstelle, die auftritt, wenn ein Produkt ein Passwort enthält, das direkt im Quellcode, in Konfigurationsdateien oder Binärdateien eingebettet ist und entweder zur Authentifizierung eingehender Benutzer (eingehende Authentifizierung) oder zur Verbindung mit externen Komponenten und Diensten (ausgehende Kommunikation) verwendet wird. Fest codierte Passwörter erzeugen schwere Sicherheitsrisiken, da sie nicht geändert werden können, ohne die Software zu modifizieren und neu bereitzustellen, oft über alle Installationen des Produkts identisch sind und durch Reverse Engineering, Quellcode-Zugang oder Konfigurationsdatei-Analyse entdeckt werden können. Sobald ein fest codiertes Passwort entdeckt wird, werden alle Systeme, die diese Software verwenden, anfällig, bis eine gepatchte Version bereitgestellt wird.

Risiko

Fest codierte Passwörter stellen eine der schwerwiegendsten Authentifizierungsschwachstellen dar, da sie Angreifern zuverlässigen, dauerhaften Zugriff bieten. Einmal durch Reverse Engineering, geleakten Quellcode oder Sicherheitsforschung entdeckt, funktioniert das Passwort bei jeder Installation der betroffenen Software. Das Ändern des Passworts erfordert Software-Updates, deren Bereitstellung auf allen betroffenen Systemen Monate oder Jahre dauern kann. Viele IoT-Geräte und eingebettete Systeme mit fest codierten Anmeldedaten bleiben dauerhaft anfällig, weil ihnen Update-Mechanismen fehlen. Das Risiko wird durch die Tendenz verstärkt, fest codierte Passwörter über Produktlinien hinweg wiederzuverwenden, und durch die Verfügbarkeit von Standard-Anmeldedaten-Datenbanken, die Angreifer routinemäßig konsultieren. In industriellen Kontrollsystemen und kritischer Infrastruktur waren fest codierte Passwörter an bedeutenden Sicherheitsvorfällen beteiligt.

Lösung

Betten Sie niemals Passwörter direkt in Quellcode, Konfigurationsdateien oder kompilierte Binärdateien ein. Implementieren Sie anfängliche Setup-Prozeduren, die Administratoren erfordern, eindeutige Anmeldedaten während der Installation zu konfigurieren. Verwenden Sie sichere Anmeldedaten-Speichermechanismen wie Hardware-Sicherheitsmodule, verschlüsselte Keystores oder Betriebssystem-Anmeldedaten-Manager. Für Service-zu-Service-Authentifizierung verwenden Sie zertifikatsbasierte Authentifizierung oder OAuth-Tokens anstelle von Passwörtern. Wenn Legacy-Systeme gespeicherte Anmeldedaten erfordern, verschlüsseln Sie sie mit Schlüsseln, die aus installationsspezifischen Werten abgeleitet sind. Implementieren Sie Anmeldedaten-Rotationsmechanismen, die Passwortänderungen ohne Software-Updates ermöglichen. Führen Sie Code-Reviews durch und verwenden Sie statische Analysetools zur Erkennung fest codierter Anmeldedaten. Scannen Sie Binärdateien und Konfigurationsdateien vor der Veröffentlichung auf Anmeldedatenmuster.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleBereich: Zugriffskontrolle

Wenn fest codierte Passwörter verwendet werden, ist es fast sicher, dass böswillige Benutzer schließlich Zugang zu dem betreffenden Konto erhalten. Das Passwort kann nicht geändert werden, ohne das Produkt zu modifizieren und neu bereitzustellen.
AuthentifizierungBereich: Authentifizierung

Fest codierte Passwörter untergraben den gesamten Authentifizierungsmechanismus. Einmal entdeckt, können Angreifer legitime Benutzer oder Dienste imitieren, und die Behebung erfordert Software-Updates über alle betroffenen Installationen.

Beispielcode

Anfälliger Code (Java)

Der folgende Code demonstriert fest codierte Passwortmuster:

public class VulnerableAuthentication {

    // Anfällig: Fest codiertes Passwort für Admin-Konto
    private static final String ADMIN_PASSWORD = "admin123";

    // Anfällig: Fest codierte Datenbank-Anmeldedaten
    private static final String DB_USER = "app_user";
    private static final String DB_PASSWORD = "DbP@ssw0rd!2024";

    public boolean authenticateUser(String username, String password) {
        // Anfällig: Vergleich gegen fest codierte Anmeldedaten
        if (username.equals("admin") && password.equals(ADMIN_PASSWORD)) {
            return true;
        }

        // Gegen Datenbank prüfen...
        return checkDatabase(username, password);
    }

    public Connection getDatabaseConnection() throws SQLException {
        // Anfällig: Fest codierte Anmeldedaten für Datenbank
        String url = "jdbc:mysql://localhost:3306/myapp";
        return DriverManager.getConnection(url, DB_USER, DB_PASSWORD);
    }

    // Anfällig: Fest codierter API-Schlüssel
    public void callExternalService() {
        String apiKey = "sk-live-abc123secretkey456";
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.service.com/data"))
            .header("Authorization", "Bearer " + apiKey)
            .build();
        // Anfrage senden...
    }

    // Anfällig: Fest codierter Verschlüsselungsschlüssel
    public byte[] encryptData(byte[] data) {
        // Schlüssel im Code eingebettet
        byte[] key = "MySecretKey12345".getBytes();
        // ... Verschlüsselungslogik
        return encrypted;
    }
}
<!-- Anfällig: Fest codiertes Passwort in Konfiguration -->
<!-- config.xml -->
<configuration>
    <database>
        <username>dbadmin</username>
        <password>SuperSecretDB123!</password>  <!-- Offengelegt! -->
    </database>
    <admin>
        <backdoor-password>masterkey</backdoor-password>  <!-- Offengelegt! -->
    </admin>
</configuration>

Korrigierter Code (Java)

public class SecureAuthentication {

    private final CredentialStore credentialStore;
    private final SecretsManager secretsManager;

    public SecureAuthentication(CredentialStore credentialStore,
                                SecretsManager secretsManager) {
        this.credentialStore = credentialStore;
        this.secretsManager = secretsManager;
    }

    public boolean authenticateUser(String username, String password) {
        // Korrigiert: Gehashtes Passwort aus sicherem Speicher abrufen
        String storedHash = credentialStore.getPasswordHash(username);

        if (storedHash == null) {
            // Konstantzeit-Fake-Prüfung um Timing-Angriffe zu verhindern
            PasswordHasher.verify(password, DUMMY_HASH);
            return false;
        }

        // Passwort gegen sicher gespeicherten Hash verifizieren
        return PasswordHasher.verify(password, storedHash);
    }

    public Connection getDatabaseConnection() throws SQLException {
        // Korrigiert: Anmeldedaten aus Secrets-Manager abrufen
        DatabaseCredentials creds = secretsManager.getDatabaseCredentials("myapp-db");

        String url = "jdbc:mysql://localhost:3306/myapp";
        return DriverManager.getConnection(url, creds.getUsername(), creds.getPassword());
    }

    public void callExternalService() {
        // Korrigiert: API-Schlüssel aus sicherem Speicher abrufen
        String apiKey = secretsManager.getSecret("external-api-key");

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.service.com/data"))
            .header("Authorization", "Bearer " + apiKey)
            .build();
        // Anfrage senden...
    }

    public byte[] encryptData(byte[] data) {
        // Korrigiert: Schlüssel aus sicherem Schlüsselspeicher abrufen
        SecretKey key = keyStore.getKey("data-encryption-key");
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }
}

// Sichere Initialisierung während des Setups
public class SetupWizard {

    public void initialSetup() {
        // Admin muss eindeutiges Passwort während des Setups setzen
        String adminPassword = promptForPassword("Admin-Passwort eingeben: ");

        // Passwortstärke validieren
        if (!PasswordPolicy.isStrong(adminPassword)) {
            throw new SecurityException("Passwort erfüllt nicht die Anforderungen");
        }

        // Gehashtes Passwort speichern
        String hash = PasswordHasher.hash(adminPassword);
        credentialStore.storePasswordHash("admin", hash);

        // Passwort aus Speicher löschen
        Arrays.fill(adminPassword.toCharArray(), '\0');
    }
}
# Korrigiert: Konfiguration referenziert Secrets, enthält sie nicht
# config.yaml
database:
  credentials_secret: "db-credentials"  # Referenz zum Secrets-Manager
  host: localhost
  port: 3306

external_api:
  key_secret: "external-api-key"  # Referenz zum Secrets-Manager

Die Korrektur verwendet externe Secrets-Manager, fordert Anmeldedaten während des Setups an, speichert Passwort-Hashes anstelle von Klartext und bettet niemals Anmeldedaten in Code oder Konfiguration ein.


Ausgenutzt in der Praxis

Mirai-Botnet IoT-Ausnutzung (Global, 2016)

Das Mirai-Botnet nutzte fest codierte Standard-Anmeldedaten in IoT-Geräten einschließlich Kameras, Routern und DVRs aus, um ein massives Botnet aufzubauen. Die Malware enthielt eine Liste von 62 gängigen Benutzername/Passwort-Kombinationen, die in verschiedenen Geräten fest codiert waren. Mit Mirai infizierte Geräte starteten rekordverdächtige DDoS-Angriffe gegen wichtige Internetinfrastruktur und demonstrierten die katastrophalen Auswirkungen fest codierter Anmeldedaten in bereitgestellten Geräten.

Cisco fest codierte Anmeldedaten (Mehrere Produkte, 2018-2022)

Bei mehreren Cisco-Produkten einschließlich Netzwerkmanagementsystemen, Videoüberwachungssystemen und IoT-Gateways wurden fest codierte Anmeldedaten gefunden. CVE-2022-29964 betraf verteilte Kontrollsysteme mit fest codierten Passwörtern, die lokalen Shell-Zugang ermöglichten. Diese Schwachstellen betrafen kritische Infrastruktur und erforderten Notfall-Patches.

Zyxel Firewall Backdoor (Zyxel, 2020)

CVE-2020-29583 enthüllte eine Schwachstelle mit fest codierten Anmeldedaten in Zyxel-Firewalls und Access-Point-Controllern. Das undokumentierte Konto "zyfwp" hatte ein fest codiertes Passwort, das Administrator-Zugang über SSH ermöglichte. Über 100.000 Geräte waren potenziell betroffen, und die Schwachstelle wurde aktiv in der Wildnis ausgenutzt.


Tools zum Testen/Ausnutzen

  • Gitleaks — Erkennt fest codierte Secrets, Passwörter und API-Schlüssel in Git-Repositories.

  • TruffleHog — Durchsucht Git-Repositories nach versehentlich committeten Secrets und Anmeldedaten.

  • Credential Scanner — Microsoft-Tool zur Erkennung von Anmeldedaten in Quellcode und Konfigurationsdateien.


CVE-Beispiele

  • CVE-2022-29964 — Verteiltes Kontrollsystem enthielt fest codierte Passwörter, die lokalen Shell-Zugang ermöglichten.

  • CVE-2021-37555 — IoT-Haustierfutterautomat legte fest codierte Authentifizierungs-Anmeldedaten über Telnet-Dienst offen.

  • CVE-2021-35033 — WiFi-Router-Firmware enthielt fest codiertes BusyBox-Shell-Passwort.

  • CVE-2020-29583 — Zyxel-Firewall enthielt undokumentiertes fest codiertes Admin-Konto.


Referenzen

  1. MITRE Corporation. "CWE-259: Use of Hard-coded Password." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/259.html

  2. OWASP Foundation. "Credential Management Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Credential_Management_Cheat_Sheet.html

  3. CISA. "Alert on Default Credentials." https://www.cisa.gov/news-events/alerts

  4. NIST. "Digital Identity Guidelines." Special Publication 800-63B. https://pages.nist.gov/800-63-3/sp800-63b.html