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
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Datenabfangen Angreifer fangen alle "verschlüsselten" Kommunikationen ab und entschlüsseln sie, wenn sie gefälschte Zertifikate präsentieren können. |
| Integrität | Bereich: Datenmanipulation MitM-Angreifer können Daten während der Übertragung modifizieren, bösartige Inhalte injizieren oder Transaktionen ändern. |
| Authentifizierung | Bereich: 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
-
CVE-2025-40744 — Siemens Solid Edge Zertifikatsvalidierungsumgehung.
-
CVE-2024-33509 — FortiWeb unsachgemäße Zertifikatsvalidierung.
-
CVE-2022-32748 — Schneider Electric CAE Credential-Leak.
Referenzen
-
MITRE. "CWE-295: Improper Certificate Validation." https://cwe.mitre.org/data/definitions/295.html
-
OWASP. "Transport Layer Protection Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html