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

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Im Kommunikationskanal positionierte Angreifer können alle übertragenen Daten lesen und Zugangsdaten, Session-Tokens, personenbezogene Informationen und sensible Geschäftsdaten preisgeben.
Integrität, ZugriffskontrolleBereich: 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

  1. MITRE Corporation. "CWE-300: Channel Accessible by Non-Endpoint." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/300.html

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

  3. RFC 5246. "The Transport Layer Security (TLS) Protocol Version 1.2." https://tools.ietf.org/html/rfc5246