Kanal zugänglich für Nicht-Endpunkte
Beschreibung
Kanal zugänglich für Nicht-Endpunkte ist eine Schwachstelle, die auftritt, wenn ein Produkt die Identitäten der Entitäten an beiden Enden eines Kommunikationskanals nicht ausreichend verifiziert oder die Integrität des Kanals nicht angemessen sicherstellt. Dies ermöglicht es Angreifern, sich zwischen legitime Endpunkte zu positionieren und Kommunikation abzufangen oder zu verändern. Das grundlegende Problem besteht darin, dass ein Kommunikationskanal für andere Parteien als die vorgesehenen Endpunkte ohne ordnungsgemäße Verifizierung oder Schutz zugänglich ist. Ohne ausreichende Identitätsprüfung an beiden Endpunkten können Angreifer die Kommunikation abhören, sich als legitime Parteien ausgeben oder Daten während der Übertragung verändern -- das klassische Man-in-the-Middle-Angriffsszenario.
Risiko
Das Versäumnis, Kommunikationskanal-Endpunkte zu sichern, stellt eine kritische Sicherheitsschwäche dar, die verheerende Man-in-the-Middle-Angriffe ermöglicht. Wenn Endpunkte nicht ordnungsgemäß verifiziert werden, können Angreifer sensible Daten einschließlich Zugangsdaten, personenbezogener Informationen, Finanzdaten und proprietärer Kommunikation abfangen. Das Risiko geht über passives Abhören hinaus zu aktiver Manipulation, bei der Angreifer Daten während der Übertragung ändern, potenziell Transaktionsdetails verändern, schädliche Inhalte einschleusen oder die Datenintegrität beschädigen. Aufsehenerregende Vorfälle wie Apples "goto fail"-Fehler (CVE-2014-1266) zeigen, wie Fehler bei der Endpunktverifizierung Millionen von Benutzern betreffen können. Die Auswirkungen werden in Umgebungen verstärkt, die sensible Daten verarbeiten, wie Finanzdienstleistungen, Gesundheitswesen und Regierungskommunikation.
Lösung
Verifizieren Sie immer die Identitäten beider Endpunkte in jedem Kommunikationskanal mit starken kryptographischen Mechanismen. Implementieren Sie Mutual TLS (mTLS), bei dem sowohl Client als auch Server Zertifikate zur Validierung vorlegen. Verwenden Sie X.509-Zertifikate, die Identitäten an kryptographische Schlüssel binden und durch eine vertrauenswürdige Zertifizierungsstelle verifiziert werden. Wenden Sie das Prinzip der vollständigen Vermittlung an -- nehmen Sie niemals an, dass ein Kanal ohne Verifizierung sicher ist. Implementieren Sie Certificate Pinning in Client-Anwendungen, um Zertifikatsaustausch-Angriffe zu verhindern. Verwenden Sie authentifizierte Verschlüsselungsmodi, die sowohl Vertraulichkeit als auch Integritätsschutz bieten. Validieren Sie Zertifikate vollständig einschließlich Vertrauenskette, Ablaufdatum, Widerrufsstatus und Hostname-Übereinstimmung. Erwägen Sie die Implementierung zusätzlicher Channel-Binding-Mechanismen, um die Authentifizierung an den spezifischen Kanal zu binden.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Vertraulichkeit | Bereich: Vertraulichkeit Im Kommunikationskanal positionierte Angreifer können alle übertragenen Daten lesen und Zugangsdaten, Session-Tokens, personenbezogene Informationen und sensible Geschäftsdaten preisgeben. |
| Integrität, Zugriffskontrolle | Bereich: Integrität, Zugriffskontrolle Angreifer können Kommunikation während der Übertragung ändern, sich als einer der Endpunkte ausgeben, schädliche Inhalte einschleusen und unautorisierten Zugang erlangen, indem sie die Identität einer legitimen Partei annehmen. |
Beispielcode und Lösung
Verwundbarer Code (Java)
Die folgenden Beispiele zeigen ungeschützte Kommunikationskanale:
// Verwundbar: Einfache Socket-Kommunikation ohne Verschlüsselung oder Authentifizierung
import java.net.*;
import java.io.*;
public class VulnerableClient {
public void sendSensitiveData(String data) throws Exception {
// Verwundbar: Keine Verschlüsselung, keine Endpunktverifizierung
Socket socket = new Socket("server.example.com", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// Verwundbar: Daten im Klartext gesendet
out.println("username:admin");
out.println("password:secretpassword");
out.println(data);
// Angreifer kann alles im Netzwerk mitlesen
String response = in.readLine();
socket.close();
}
}
# Verwundbar: HTTP ohne TLS oder Endpunktverifizierung
import http.client
import json
def vulnerable_api_call(endpoint, data):
# Verwundbar: Reines HTTP, keine Verschlüsselung
conn = http.client.HTTPConnection("api.example.com", 80)
# Verwundbar: Zugangsdaten ohne Verschlüsselung gesendet
headers = {
"Authorization": "Bearer secret_token_12345",
"Content-Type": "application/json"
}
# Angreifer kann all dies abfangen
conn.request("POST", endpoint, json.dumps(data), headers)
response = conn.getresponse()
return response.read()
# Verwundbar: SSL ohne ordnungsgemäße Verifizierung
import ssl
import socket
def vulnerable_ssl_connect(hostname, port):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Verwundbar: Zertifikatsprüfung deaktiviert
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(sock)
ssl_sock.connect((hostname, port))
# Angreifer mit beliebigem Zertifikat kann abfangen
return ssl_sock
// Verwundbar: C-Code ohne SSL-Verifizierungs-Callback
#include <openssl/ssl.h>
#include <openssl/err.h>
int vulnerable_connect(const char *host, int port) {
SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
// Verwundbar: Keine Zertifikatsverifizierung konfiguriert
// SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
SSL *ssl = SSL_new(ctx);
// Verbindung ohne Verifizierung der Server-Identität
int sock = create_socket(host, port);
SSL_set_fd(ssl, sock);
if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
return -1;
}
// Verwundbar: Zertifikat wird überhaupt nicht geprüft
// Jeder Endpunkt kann sich als Server ausgeben
return sock;
}
Sichere Lösung (Java)
// Behoben: Mutual TLS mit ordnungsgemäßer Endpunktverifizierung
import javax.net.ssl.*;
import java.security.*;
import java.io.*;
public class SecureClient {
public void sendSensitiveData(String data) throws Exception {
// Client-Zertifikat für gegenseitige Authentifizierung laden
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
clientKeyStore.load(
new FileInputStream("/path/to/client.p12"),
"keystorepassword".toCharArray()
);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(clientKeyStore, "keypassword".toCharArray());
// Vertrauenswürdige Server-Zertifikate laden
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(
new FileInputStream("/path/to/truststore.jks"),
"truststorepassword".toCharArray()
);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore);
// Behoben: SSL-Kontext mit Key- und Trust-Managern konfigurieren
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory factory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("server.example.com", 8443);
// Behoben: Hostname-Verifizierung aktivieren
SSLParameters params = socket.getSSLParameters();
params.setEndpointIdentificationAlgorithm("HTTPS");
socket.setSSLParameters(params);
// Behoben: Handshake-Abschluss prüfen (beide Endpunkte verifiziert)
socket.startHandshake();
// Kommunikation ist nun verschlüsselt und beide Endpunkte verifiziert
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
out.println(data);
String response = in.readLine();
socket.close();
}
}
# Behoben: Ordnungsgemäßes TLS mit Endpunktverifizierung
import ssl
import socket
import certifi
def secure_connect(hostname, port):
# Behoben: Kontext mit ordnungsgemäßer Verifizierung erstellen
context = ssl.create_default_context(cafile=certifi.where())
# Behoben: Hostname-Verifizierung aktivieren
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
# Behoben: Mindest-TLS-Version verlangen
context.minimum_version = ssl.TLSVersion.TLSv1_2
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Behoben: Hostname für SNI und Verifizierung angeben
ssl_sock = context.wrap_socket(sock, server_hostname=hostname)
ssl_sock.connect((hostname, port))
# Behoben: Zertifikat nach Verbindungsaufbau prüfen
cert = ssl_sock.getpeercert()
if not cert:
raise ssl.SSLError("No certificate received")
return ssl_sock
# Behoben: Mutual-TLS-Client
def secure_mtls_connect(hostname, port, client_cert, client_key, ca_bundle):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# Client-Zertifikat für gegenseitige Authentifizierung laden
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
# CA-Zertifikate für Server-Verifizierung laden
context.load_verify_locations(cafile=ca_bundle)
context.check_hostname = True
context.verify_mode = ssl.CERT_REQUIRED
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(sock, server_hostname=hostname)
ssl_sock.connect((hostname, port))
return ssl_sock
Die Behebung implementiert Mutual-TLS-Authentifizierung, die sicherstellt, dass beide Endpunkte die Identität des jeweils anderen mittels Zertifikaten verifizieren.
Ausgenutzt in der Praxis
Apple SSL "goto fail"-Fehler (iOS/macOS, 2014)
CVE-2014-1266 dokumentierte eine kritische Schwachstelle in Apples SSL/TLS-Implementierung, bei der ein Programmierfehler (doppelte "goto fail"-Anweisung) dazu führte, dass die Zertifikatsvalidierung umgangen wurde, was Man-in-the-Middle-Angriffe auf die gesamte iOS- und macOS-Kommunikation ermöglichte.
Banking-App MitM-Angriffe (Mobile Anwendungen, 2016)
Sicherheitsforscher entdeckten, dass mehrere Banking-Anwendungen aufgrund unsachgemäßer Zertifikatsvalidierung anfällig für Man-in-the-Middle-Angriffe waren, wodurch Angreifer Zugangsdaten und Finanztransaktionen abfangen könnten.
Tools zum Testen und Ausnutzen
-
mitmproxy -- Interaktiver HTTPS-Proxy zum Testen von Man-in-the-Middle-Angriffsszenarien.
-
Wireshark -- Netzwerkprotokoll-Analysator zur Untersuchung unverschlüsselter oder unzureichend gesicherter Kommunikation.
-
sslstrip -- Tool zur Demonstration von SSL-Stripping-Angriffen gegen unsachgemäß konfigurierte Endpunkte.
CVE-Beispiele
-
CVE-2014-1266 -- Apple SSL "goto fail"-Fehler umgeht Zertifikatsvalidierung.
-
CVE-2012-5810 -- Mobile Banking-App akzeptiert beliebige Zertifikate.
-
CVE-2014-0224 -- OpenSSL CCS Injection ermöglicht MitM-Angriffe.
Referenzen
-
MITRE Corporation. "CWE-300: Channel Accessible by Non-Endpoint." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/300.html
-
OWASP Foundation. "Transport Layer Protection Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html
-
RFC 5246. "The Transport Layer Security (TLS) Protocol Version 1.2." https://tools.ietf.org/html/rfc5246