Unsachgemäße Zertifikatsvalidierung

Beschreibung

Unsachgemäße Zertifikatsvalidierung tritt auf, wenn Software ein digitales Zertifikat nicht validiert oder falsch validiert. Zertifikate werden verwendet, um vertrauenswürdige Kommunikationskanale aufzubauen, Identitäten zu verifizieren und Datenintegrität sicherzustellen. Wenn Validierung fehlt oder fehlerhaft ist, können Angreifer Man-in-the-Middle (MitM)-Angriffe durchführen, indem sie betrügerische Zertifikate präsentieren, verschlüsselte Kommunikation abfangen, vertrauenswürdige Server imitieren oder bösartige Inhalte injizieren. Häufige Probleme umfassen deaktivierte Hostname-Verifikation, Akzeptanz von selbstsignierten Zertifikaten, Ignorieren von Zertifikatsablauf und Vertrauen in ungültige Zertifikatsketten.

Risiko

Zertifikatsvalidierungsfehler ermöglichen direkt Man-in-the-Middle-Angriffe gegen ansonsten verschlüsselte Kommunikation. Angreifer können HTTPS-Verkehr abfangen, Anmeldedaten stehlen, bösartige Payloads injizieren und legitime Dienste imitieren. Die standardmäßig deaktivierte Hostname-Verifikation im Netty-Framework hat zahlreiche Java-Anwendungen betroffen. Mobile Apps werden häufig mit deaktivierter Zertifikatsvalidierung für die Entwicklung ausgeliefert, die nie wieder aktiviert wird. Industrielle Steuerungssysteme wie Siemens Solid Edge waren anfällig, was Angriffe auf Engineering-Workstations ermöglichte. Finanz- und Gesundheitsdaten, die nur durch "TLS" geschützt sind, werden vollständig offengelegt, wenn Zertifikatsvalidierung fehlschlägt.

Lösung

Validieren Sie Zertifikate immer vollständig: Verifizieren Sie die Zertifikatskette bis zu einer vertrauenswürdigen Root-CA, prüfen Sie den Zertifikatsablauf, validieren Sie, dass der Hostname mit den Subject Alternative Names oder dem Common Name des Zertifikats übereinstimmt, und verifizieren Sie den Zertifikatswiderrufsstatus (CRL/OCSP). Verwenden Sie etablierte TLS-Bibliotheken mit sicheren Standardeinstellungen. Deaktivieren Sie nie die Zertifikatsvalidierung in Produktion. Implementieren Sie Certificate Pinning für hochsichere Anwendungen. Testen Sie Zertifikatsvalidierung explizit während Sicherheitsbewertungen. Konfigurieren Sie TLS ordnungsgemäß mit starken Cipher Suites.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Datenabfangen

Angreifer fangen alle "verschlüsselten" Kommunikationen ab und entschlüsseln sie, wenn sie gefälschte Zertifikate präsentieren können.
IntegritätBereich: Datenmanipulation

MitM-Angreifer können Daten während der Übertragung modifizieren, bösartige Inhalte injizieren oder Transaktionen ändern.
AuthentifizierungBereich: Identitätsfälschung

Angreifer imitieren legitime Server und leiten Benutzer zu bösartigen Diensten.

Beispielcode + Korrigierter Code

Anfälliger Code

// ANFÄLLIG: Deaktivierte Hostname-Verifikation
import javax.net.ssl.*;

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] {
    new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String auth) {}
        public void checkServerTrusted(X509Certificate[] chain, String auth) {}
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
    }
}, null);

// Akzeptiert JEDES Zertifikat!
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
# ANFÄLLIG: Deaktivierte Zertifikatsverifikation
import requests

# verify=False deaktiviert ALLE Zertifikatsvalidierung
response = requests.get('https://api.example.com', verify=False)

# ANFÄLLIG: Benutzerdefinierter SSL-Kontext ohne Verifikation
import ssl
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
// ANFÄLLIG: Node.js mit deaktivierter Verifikation
const https = require('https');

const agent = new https.Agent({
    rejectUnauthorized: false  // Akzeptiert ungültige Zertifikate!
});

https.get('https://api.example.com', { agent }, (res) => {
    // ...
});

// ANFÄLLIG: Umgebungsvariable
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';  // Nie tun!

Korrigierter Code

// SICHER: Ordnungsgemäße Zertifikatsvalidierung
import javax.net.ssl.*;
import java.security.KeyStore;

public class SecureHttpClient {
    public HttpsURLConnection createConnection(URL url) throws Exception {
        // Vertrauenswürdige Zertifikate laden
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(getClass().getResourceAsStream("/truststore.jks"),
                       "password".toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory.getInstance(
            TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);

        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, tmf.getTrustManagers(), null);

        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setSSLSocketFactory(ctx.getSocketFactory());
        // Standard-Hostname-Verifier validiert Hostname
        return conn;
    }
}

// SICHER: Certificate Pinning
public class PinningTrustManager implements X509TrustManager {
    private static final String EXPECTED_PIN = "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // Erst Zertifikatskette verifizieren
        defaultTrustManager.checkServerTrusted(chain, authType);

        // Dann Pin verifizieren
        String pin = getPin(chain[0]);
        if (!EXPECTED_PIN.equals(pin)) {
            throw new CertificateException("Zertifikats-Pin stimmt nicht überein");
        }
    }
}
# SICHER: Ordnungsgemäße Zertifikatsverifikation (Standard)
import requests

# verify=True ist der Standard - validiert Zertifikate
response = requests.get('https://api.example.com')  # Standardmäßig sicher

# SICHER: Benutzerdefiniertes CA-Bundle
response = requests.get('https://api.example.com',
                        verify='/path/to/ca-bundle.crt')

# SICHER: Certificate Pinning mit requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context

class PinningAdapter(HTTPAdapter):
    def __init__(self, expected_fingerprint):
        self.expected_fingerprint = expected_fingerprint
        super().__init__()

    def init_poolmanager(self, *args, **kwargs):
        ctx = create_urllib3_context()
        kwargs['ssl_context'] = ctx
        return super().init_poolmanager(*args, **kwargs)

    def cert_verify(self, conn, url, verify, cert):
        super().cert_verify(conn, url, verify, cert)
        # Zusätzliche Fingerprint-Verifikation
        actual = conn.sock.getpeercert(binary_form=True)
        if hashlib.sha256(actual).hexdigest() != self.expected_fingerprint:
            raise SSLError("Zertifikats-Fingerprint stimmt nicht überein")
// SICHER: Node.js mit ordnungsgemäßer Validierung (Standard)
const https = require('https');

// Standardverhalten validiert Zertifikate
https.get('https://api.example.com', (res) => {
    // Zertifikat wird automatisch validiert
});

// SICHER: Certificate Pinning
const tls = require('tls');
const https = require('https');

const EXPECTED_FINGERPRINT = '00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF';

const agent = new https.Agent({
    checkServerIdentity: (host, cert) => {
        const fingerprint = cert.fingerprint256;
        if (fingerprint !== EXPECTED_FINGERPRINT) {
            throw new Error('Zertifikats-Fingerprint stimmt nicht überein');
        }
        // Auch Standard-Hostname-Verifikation durchführen
        return tls.checkServerIdentity(host, cert);
    }
});

Ausgenutzt in der Praxis

Siemens Solid Edge (Siemens, 2025)

CVE-2025-40744 in Siemens Solid Edge SE2025 ermöglicht MitM-Angriffe aufgrund unsachgemäßer Client-Zertifikatsvalidierung beim Verbinden mit dem License Service, mit CVSS 7.5 hoher Schweregrad.

Fortinet FortiWeb WAF (Fortinet, 2024)

CVE-2024-33509 in FortiWeb ermöglicht MitM-Angreifern, WAF-Kommunikationen abzufangen und zu manipulieren, aufgrund unsachgemäßer Zertifikatsvalidierung beim Abrufen externer Daten.

Netty Framework (Netty, Mehrfach)

Standardmäßig deaktivierte Zertifikats-Hostname-Validierung in Netty 4.1.x betraf zahlreiche Java-Anwendungen einschließlich Keycloak und machte sie anfällig für MitM-Angriffe.


Tools zum Testen/Ausnutzen

  • SSLyze — TLS-Konfiguration und Zertifikatsvalidierung analysieren.

  • testssl.sh — TLS/SSL-Testtool.

  • mitmproxy — Zertifikatsvalidierung durch Versuch von MitM testen.


CVE-Beispiele


Referenzen

  1. MITRE. "CWE-295: Improper Certificate Validation." https://cwe.mitre.org/data/definitions/295.html

  2. OWASP. "Transport Layer Protection Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html