Fehlende Prüfung auf Zertifikatswiderruf nach initialer Prüfung
Beschreibung
Fehlende Prüfung auf Zertifikatswiderruf nach initialer Prüfung ist eine Schwachstelle, die auftritt, wenn ein Produkt den Zertifikatswiderrufsstatus nicht vor jeder privilegierten Aktion verifiziert und nur bei der initialen Verbindung oder Authentifizierung prüft. Ein Zertifikat kann zwischen der initialen Prüfung und nachfolgenden Operationen widerrufen werden aufgrund von Schlüsselkompromittierung, Richtlinienänderungen oder Mitarbeiterbeendigung. Dies schafft ein Zeitfenster, in dem widerrufene Anmeldedaten ihre Privilegien behalten, was fortgesetzten Zugang ermöglicht, der hätte beendet werden sollen. Die Schwachstelle ist im Wesentlichen eine TOCTOU (Time-of-Check Time-of-Use) Race Condition angewendet auf Zertifikatsvalidierung.
Risiko
Diese Schwachstelle ermöglicht Angreifern mit widerrufenen Zertifikaten, weiterhin auf geschützte Ressourcen zuzugreifen, bis die Sitzung endet oder eine periodische Neuprüfung stattfindet. Wenn ein privater Schlüssel kompromittiert und das Zertifikat widerrufen wird, können Angreifer den kompromittierten Schlüssel immer noch für den Rest aktiver Sitzungen verwenden. Bei langlebigen Verbindungen oder Sitzungen mit seltener Neuauthentifizierung kann das Zeitfenster der Exposition erheblich sein. Gekündigte Mitarbeiter, deren Zertifikate widerrufen werden, behalten möglicherweise Zugang. Das Risiko ist besonders schwerwiegend für hochsichere Anwendungen, bei denen sofortiger Widerruf kritisch ist, wie Finanzsysteme, Gesundheitsanwendungen oder Zugangskon trollsysteme.
Lösung
Stellen Sie sicher, dass Zertifikate vor jeder Nutzung einer geschützten Ressource auf Widerrufsstatus geprüft werden, nicht nur bei der initialen Authentifizierung. Implementieren Sie kurze Sitzungs-Timeouts, die Neuauthentifizierung erfordern. Verwenden Sie OCSP-Stapling, um den Widerrufsstatus effizient zu prüfen. Cachen Sie den Widerrufsstatus für kurze Zeiträume (Minuten, nicht Stunden), um Leistung und Sicherheit auszubalancieren. Erwägen Sie die Verwendung von Certificate-Transparency-Logs für zusätzliche Verifizierung. Implementieren Sie Echtzeit-Widerrufsprüfung für hochsichere Operationen. Entwerfen Sie Systeme, um die Zeit zwischen Widerruf und Durchsetzung zu minimieren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Vertrauen kann einer Entität zugewiesen werden, die nicht die ist, die sie vorgibt zu sein, da widerrufene Anmeldedaten weiter funktionieren. |
| Integrität | Umfang: Integrität Daten aus einer nicht vertrauenswürdigen Quelle können integriert werden, wenn widerrufene Zertifikate noch akzeptiert werden. |
| Vertraulichkeit | Umfang: Vertraulichkeit Daten können einer Entität offengelegt werden, die sich mit widerrufenen Anmeldedaten als vertrauenswürdige Entität ausgibt. |
Beispielcode
Anfälliger Code
// Anfällig: Prüft Zertifikat nur bei Verbindungszeit
public class VulnerableSSLServer {
public void handleConnection(SSLSocket socket) throws Exception {
// Zertifikat nur beim Handshake geprüft
SSLSession session = socket.getSession();
X509Certificate[] certs = (X509Certificate[])
session.getPeerCertificates();
// Initiale Verifizierung
verifyCertificate(certs[0]);
// Anfällig: Keine Widerrufsprüfung für nachfolgende Operationen
while (true) {
String command = readCommand(socket);
// Zertifikat könnte seit Verbindung widerrufen worden sein
executePrivilegedCommand(command); // Gefährlich!
}
}
private void verifyCertificate(X509Certificate cert) {
// Prüft nur Gültigkeit, nicht Widerruf für jede Operation
}
}
# Anfällig: Sitzung verwendet initiale Zertifikatsvalidierung wieder
class VulnerableAuthenticator:
def __init__(self):
self.authenticated_sessions = {}
def authenticate(self, cert, session_id):
# Anfällig: Prüft Widerruf nur beim Login
if self.verify_certificate(cert) and not self.is_revoked(cert):
self.authenticated_sessions[session_id] = {
'cert': cert,
'authenticated_at': time.time()
}
return True
return False
def perform_action(self, session_id, action):
# Anfällig: Keine erneute Widerrufsprüfung
if session_id in self.authenticated_sessions:
# Zertifikat könnte jetzt widerrufen sein!
execute_action(action)
Korrigierter Code
// Korrigiert: Widerruf vor jeder privilegierten Operation prüfen
public class SecureSSLServer {
private OCSPChecker ocspChecker;
private int maxOperationsBeforeRecheck = 10;
private int operationCount = 0;
public void handleConnection(SSLSocket socket) throws Exception {
SSLSession session = socket.getSession();
X509Certificate[] certs = (X509Certificate[])
session.getPeerCertificates();
X509Certificate clientCert = certs[0];
// Initiale Verifizierung
verifyAndCheckRevocation(clientCert);
while (true) {
String command = readCommand(socket);
// Korrigiert: Widerruf periodisch erneut prüfen
operationCount++;
if (operationCount >= maxOperationsBeforeRecheck) {
verifyAndCheckRevocation(clientCert);
operationCount = 0;
}
executePrivilegedCommand(command);
}
}
private void verifyAndCheckRevocation(X509Certificate cert) throws Exception {
// Zertifikatskette verifizieren
verifyCertificateChain(cert);
// Korrigiert: OCSP/CRL auf Widerruf prüfen
if (ocspChecker.isRevoked(cert)) {
throw new CertificateRevokedException("Zertifikat wurde widerrufen");
}
}
}
// Korrigiert: Widerruf vor jeder sensiblen Operation prüfen
public class SecureOperationHandler {
public void performSensitiveOperation(X509Certificate cert, Operation op)
throws Exception {
// Korrigiert: Widerruf vor JEDER sensiblen Operation prüfen
checkRevocationStatus(cert);
// Nur fortfahren wenn Zertifikat noch gültig ist
executeOperation(op);
}
private void checkRevocationStatus(X509Certificate cert) throws Exception {
// OCSP für Echtzeit-Widerrufsprüfung verwenden
OCSPResponse response = queryOCSP(cert);
if (response.getStatus() == OCSPResponseStatus.REVOKED) {
throw new CertificateRevokedException("Zertifikat widerrufen");
}
}
}
# Korrigiert: Zertifikatsstatus regelmäßig erneut prüfen
import time
from functools import wraps
class SecureAuthenticator:
RECHECK_INTERVAL = 300 # 5 Minuten
def __init__(self):
self.authenticated_sessions = {}
def authenticate(self, cert, session_id):
if self.verify_certificate(cert) and not self.is_revoked(cert):
self.authenticated_sessions[session_id] = {
'cert': cert,
'authenticated_at': time.time(),
'last_revocation_check': time.time()
}
return True
return False
def _check_session_validity(self, session_id):
"""Korrigiert: Widerrufsstatus periodisch erneut prüfen."""
session = self.authenticated_sessions.get(session_id)
if not session:
return False
cert = session['cert']
last_check = session['last_revocation_check']
# Korrigiert: Erneut prüfen wenn Intervall überschritten
if time.time() - last_check > self.RECHECK_INTERVAL:
if self.is_revoked(cert):
del self.authenticated_sessions[session_id]
return False
session['last_revocation_check'] = time.time()
return True
def perform_action(self, session_id, action):
# Korrigiert: Sitzung vor jeder Aktion validieren
if not self._check_session_validity(session_id):
raise PermissionError("Sitzung ungültig oder Zertifikat widerrufen")
execute_action(action)
# Korrigiert: Decorator für sensible Operationen
def require_valid_cert(self, func):
@wraps(func)
def wrapper(session_id, *args, **kwargs):
session = self.authenticated_sessions.get(session_id)
if not session:
raise PermissionError("Nicht authentifiziert")
# Korrigiert: Widerruf für sensible Ops immer prüfen
if self.is_revoked(session['cert']):
del self.authenticated_sessions[session_id]
raise PermissionError("Zertifikat widerrufen")
return func(session_id, *args, **kwargs)
return wrapper
CVE-Beispiele
Keine spezifischen CVEs sind für diese CWE gelistet, aber das Schwachstellenmuster erscheint in:
- Langlebigen TLS-Sitzungen ohne Widerrufs-Neuprüfung
- Webanwendungen, die Client-Zertifikate verwenden
- VPN-Systemen mit Zertifikatsauthentifizierung
Referenzen
- MITRE Corporation. "CWE-370: Missing Check for Certificate Revocation after Initial Check." https://cwe.mitre.org/data/definitions/370.html
- RFC 6960. "Online Certificate Status Protocol - OCSP." https://tools.ietf.org/html/rfc6960