Fehlende Unterstützung für Integritätsprüfung

Beschreibung

Fehlende Unterstützung für Integritätsprüfung ist eine Schwachstelle, die auftritt, wenn ein Produkt ein Übertragungsprotokoll oder Datenspeichermechanismus verwendet, dem ein eingebauter Mechanismus zur Verifizierung der Datenintegrität fehlt, wie eine Prüfsumme, ein Hash oder ein Message Authentication Code. Ohne Integritätsverifizierung gibt es keine Möglichkeit festzustellen, ob Daten während der Übertragung oder Speicherung korrumpiert wurden, sei es versehentlich durch Hardware-Ausfälle und Netzwerkfehler, oder böswillig durch Man-in-the-Middle-Angriffe und Datenmanipulation. Das Fehlen von Integritätsprüfung entfernt die erste Schicht der Anwendungsebenen-Verifizierung, gemäß dem End-to-End-Prinzip, dass Integrität auf der niedrigstmöglichen Ebene verifiziert werden sollte, auf der die vollständige Nachricht untersucht werden kann. Diese Schwäche ist besonders kritisch für Protokolle, die sensible Daten, Konfigurationsdateien, Firmware-Updates oder beliebige Daten verarbeiten, bei denen unentdeckte Änderungen Sicherheitsimplikationen haben könnten.

Risiko

Fehlende Integritätsprüfungen ermöglichen sowohl versehentliche Korruption als auch absichtliche Manipulation unentdeckt zu bleiben. Bei Netzwerkkommunikation können Angreifer, die Man-in-the-Middle-Angriffe durchführen, Daten im Transit ohne Erkennung modifizieren - Finanztransaktionsbeträge ändern, heruntergeladene Software modifizieren um Malware einzuschließen, oder Konfigurationsbefehle ändern. Firmware- und Software-Updates ohne Integritätsverifizierung sind Hauptziele für Supply-Chain-Angriffe. Gespeicherte Daten ohne Integritätsschutz können stillschweigend korrumpiert werden, was zu Datenverlust, Systeminstabilität oder Sicherheits-Bypasses führt. Netzwerkprotokolle ohne Prüfsummen verarbeiten möglicherweise korrumpierte Pakete, was Anwendungsabstürze oder falsches Verhalten verursacht. Das Fehlen von Integritätsverifizierung bedeutet auch, dass es keine Nicht-Abstreitbarkeit gibt - es ist unmöglich festzustellen, ob Daten nach der Übertragung modifiziert wurden. Kritische Systeme, die auf Datenintegrität für Sicherheits- oder Sicherheitsentscheidungen angewiesen sind, werden unzuverlässig, wenn Integrität nicht verifiziert werden kann.

Lösung

Implementieren Sie Integritätsprüfung auf der entsprechenden Protokollebene. Für Netzwerkübertragungen verwenden Sie Protokolle mit eingebauter Integritätsverifizierung wie TLS (das HMAC-basierte Integrität bereitstellt) oder implementieren Sie Anwendungsebenen-Message Authentication Codes (MACs). Für Datenspeicherung berechnen und speichern Sie kryptografische Hashes (SHA-256 oder starker) zusammen mit Daten und verifizieren Sie vor der Verwendung. Für Firmware- und Software-Updates erfordern Sie kryptografische Signaturen, die sowohl Integrität als auch Authentizität bereitstellen. Verwenden Sie authentifizierte Verschlüsselungsmodi wie AES-GCM, die Vertraulichkeit mit Integrität kombinieren. Implementieren Sie Prüfsummen auf Paketebene für Protokolle, die Fehlererkennung ohne kryptografischen Overhead benötigen. Entwerfen Sie Protokolle gemäß dem End-to-End-Prinzip mit Integritätsverifizierung auf Anwendungsebene. Gehen Sie niemals davon aus, dass Integrität auf niedrigerer Ebene (IP-Prüfsummen, Ethernet CRC) ausreichenden Schutz für Anwendungsdaten bietet.

Häufige Auswirkungen

AuswirkungDetails
IntegritätUmfang: Integrität

Daten können während der Übertragung oder Speicherung ohne Erkennung korrumpiert werden. Anwendungen, die korrumpierte Daten verarbeiten, verhalten sich möglicherweise falsch, stürzen ab oder produzieren falsche Ergebnisse.
Nicht-AbstreitbarkeitUmfang: Nicht-Abstreitbarkeit

Ohne Integritätsverifizierung ist es unmöglich festzustellen, ob Daten nach der Erstellung modifiziert wurden, was Audit-Trails und Rechenschaftspflicht untergräbt.
VerfügbarkeitUmfang: Verfügbarkeit

Korrumpierte Daten, die ohne Erkennung verarbeitet werden, können Anwendungsabstürze, Systeminstabilität oder Denial of Service durch fehlerhafte Eingaben verursachen.

Beispielcode

Anfälliger Code (Mehrere Sprachen)

Die folgenden Beispiele demonstrieren fehlende Integritätsprüfungen:

# Anfällig: Netzwerkübertragung ohne Integritätsprüfung
import socket
import pickle

# Anfällig: UDP-Kommunikation ohne Prüfsumme
def vulnerable_send_command(host, port, command):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # Anfällig: Keine Integritätsprüfung auf übertragenen Daten
    # Angreifer kann Paket im Transit modifizieren
    data = pickle.dumps(command)
    sock.sendto(data, (host, port))

# Anfällig: TCP ohne Anwendungsebenen-Integrität
def vulnerable_receive_data(sock):
    # Anfällig: Nur auf TCP-Prüfsumme verlassen
    # TCP-Prüfsumme ist schwach und nicht kryptografisch
    data = sock.recv(4096)

    # Daten ohne Integritätsverifizierung verarbeiten
    return pickle.loads(data)  # Gefährlich ohne Integritätsprüfung

# Anfällig: Dateispeicherung ohne Integrität
def vulnerable_save_config(config, filepath):
    with open(filepath, 'wb') as f:
        # Anfällig: Kein Hash mit Daten gespeichert
        pickle.dump(config, f)

def vulnerable_load_config(filepath):
    with open(filepath, 'rb') as f:
        # Anfällig: Keine Integritätsverifizierung
        # Datei könnte korrumpiert oder manipuliert sein
        return pickle.load(f)

# Anfällig: Firmware-Download ohne Integrität
import urllib.request

def vulnerable_download_firmware(url, output_path):
    # Anfällig: Download ohne Integritätsverifizierung
    urllib.request.urlretrieve(url, output_path)

    # Anfällig: Heruntergeladene Datei ohne Prüfsumme verwenden
    apply_firmware(output_path)

# Anfällig: Datenbank-Backup ohne Integrität
def vulnerable_backup_database(db_path, backup_path):
    import shutil
    # Anfällig: Keine Prüfsumme berechnet oder gespeichert
    shutil.copy2(db_path, backup_path)

def vulnerable_restore_database(backup_path, db_path):
    import shutil
    # Anfällig: Wiederherstellung ohne Integritätsprüfung
    # Backup könnte korrumpiert sein
    shutil.copy2(backup_path, db_path)
// Anfällig: Fehlende Integritätsprüfungen in Java
import java.net.*;
import java.io.*;

public class VulnerableIntegrity {

    // Anfällig: UDP ohne Integrität
    public void vulnerableSendUDP(String host, int port, byte[] data)
            throws Exception {
        DatagramSocket socket = new DatagramSocket();
        InetAddress address = InetAddress.getByName(host);

        // Anfällig: Keine Prüfsumme oder MAC zum Paket hinzugefügt
        DatagramPacket packet = new DatagramPacket(data, data.length,
                                                     address, port);
        socket.send(packet);
        socket.close();
    }

    public byte[] vulnerableReceiveUDP(int port) throws Exception {
        DatagramSocket socket = new DatagramSocket(port);
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        socket.receive(packet);
        socket.close();

        // Anfällig: Keine Integritätsverifizierung auf empfangenen Daten
        return Arrays.copyOf(packet.getData(), packet.getLength());
    }

    // Anfällig: Dateioperationen ohne Integrität
    public void vulnerableSaveData(Object data, String path) throws Exception {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(path))) {
            // Anfällig: Kein Hash gespeichert
            oos.writeObject(data);
        }
    }

    public Object vulnerableLoadData(String path) throws Exception {
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(path))) {
            // Anfällig: Keine Integritätsprüfung vor Deserialisierung
            return ois.readObject();
        }
    }

    // Anfällig: HTTP-Download ohne Integrität
    public void vulnerableDownloadFile(String url, String outputPath)
            throws Exception {
        URL fileUrl = new URL(url);
        try (InputStream in = fileUrl.openStream();
             FileOutputStream out = new FileOutputStream(outputPath)) {

            // Anfällig: Keine Prüfsummenverifizierung
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        // Anfällig: Datei ohne Integritätsprüfung verwenden
        processDownloadedFile(outputPath);
    }
}

Korrigierter Code (Mehrere Sprachen)

# Korrigiert: Netzwerkübertragung mit Integritätsprüfungen
import socket
import pickle
import hashlib
import hmac
import struct

# Korrigiert: UDP mit HMAC-Integrität
def secure_send_command(host, port, command, secret_key):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    data = pickle.dumps(command)

    # Korrigiert: HMAC für Integrität berechnen
    mac = hmac.new(secret_key, data, hashlib.sha256).digest()

    # Korrigiert: Daten mit MAC senden
    packet = struct.pack('>I', len(data)) + mac + data
    sock.sendto(packet, (host, port))

def secure_receive_command(sock, secret_key):
    packet, addr = sock.recvfrom(65535)

    # Korrigiert: Länge, MAC und Daten parsen
    length = struct.unpack('>I', packet[:4])[0]
    received_mac = packet[4:36]  # 32 Bytes für SHA256
    data = packet[36:36+length]

    # Korrigiert: MAC vor Verarbeitung verifizieren
    expected_mac = hmac.new(secret_key, data, hashlib.sha256).digest()
    if not hmac.compare_digest(received_mac, expected_mac):
        raise ValueError("Integritätsprüfung fehlgeschlagen")

    return pickle.loads(data)

# Korrigiert: Dateispeicherung mit Hash
def secure_save_config(config, filepath):
    data = pickle.dumps(config)

    # Korrigiert: Hash berechnen und speichern
    hash_value = hashlib.sha256(data).digest()

    with open(filepath, 'wb') as f:
        f.write(hash_value)  # Erste 32 Bytes sind Hash
        f.write(data)

def secure_load_config(filepath):
    with open(filepath, 'rb') as f:
        stored_hash = f.read(32)
        data = f.read()

    # Korrigiert: Hash vor Laden verifizieren
    computed_hash = hashlib.sha256(data).digest()
    if not hmac.compare_digest(stored_hash, computed_hash):
        raise ValueError("Konfigurationsdatei-Integritätsprüfung fehlgeschlagen")

    return pickle.loads(data)

# Korrigiert: Firmware-Download mit Prüfsummenverifizierung
import urllib.request

def secure_download_firmware(url, checksum_url, output_path):
    # Korrigiert: Erwartete Prüfsumme herunterladen
    with urllib.request.urlopen(checksum_url) as response:
        expected_checksum = response.read().decode().strip()

    # Firmware herunterladen
    urllib.request.urlretrieve(url, output_path)

    # Korrigiert: Prüfsumme verifizieren
    sha256_hash = hashlib.sha256()
    with open(output_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            sha256_hash.update(chunk)

    actual_checksum = sha256_hash.hexdigest()

    if actual_checksum != expected_checksum:
        os.remove(output_path)
        raise ValueError("Firmware-Integritätsprüfung fehlgeschlagen")

    apply_firmware(output_path)

# Korrigiert: TLS für Transport-Integrität verwenden
import ssl

def secure_tcp_connection(host, port):
    context = ssl.create_default_context()

    # Korrigiert: TLS bietet Integrität über HMAC
    with socket.create_connection((host, port)) as sock:
        with context.wrap_socket(sock, server_hostname=host) as ssock:
            return ssock

# Korrigiert: Datenbank-Backup mit Integrität
def secure_backup_database(db_path, backup_path, metadata_path):
    import shutil

    # Datenbank kopieren
    shutil.copy2(db_path, backup_path)

    # Korrigiert: Hash berechnen und speichern
    sha256_hash = hashlib.sha256()
    with open(backup_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            sha256_hash.update(chunk)

    with open(metadata_path, 'w') as f:
        f.write(sha256_hash.hexdigest())

def secure_restore_database(backup_path, metadata_path, db_path):
    # Korrigiert: Integrität vor Wiederherstellung verifizieren
    with open(metadata_path, 'r') as f:
        expected_hash = f.read().strip()

    sha256_hash = hashlib.sha256()
    with open(backup_path, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            sha256_hash.update(chunk)

    if sha256_hash.hexdigest() != expected_hash:
        raise ValueError("Backup-Integritätsprüfung fehlgeschlagen")

    import shutil
    shutil.copy2(backup_path, db_path)
// Korrigiert: Integritätsprüfungen in Java
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class SecureIntegrity {

    // Korrigiert: UDP mit HMAC
    public void secureSendUDP(String host, int port, byte[] data,
                               SecretKey macKey) throws Exception {
        DatagramSocket socket = new DatagramSocket();
        InetAddress address = InetAddress.getByName(host);

        // Korrigiert: HMAC berechnen
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(macKey);
        byte[] macValue = mac.doFinal(data);

        // Korrigiert: MAC und Daten kombinieren
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeInt(data.length);
        dos.write(macValue);
        dos.write(data);

        byte[] packet = baos.toByteArray();
        socket.send(new DatagramPacket(packet, packet.length, address, port));
        socket.close();
    }

    public byte[] secureReceiveUDP(int port, SecretKey macKey) throws Exception {
        DatagramSocket socket = new DatagramSocket(port);
        byte[] buffer = new byte[65535];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        socket.receive(packet);
        socket.close();

        ByteArrayInputStream bais = new ByteArrayInputStream(
            packet.getData(), 0, packet.getLength());
        DataInputStream dis = new DataInputStream(bais);

        int dataLength = dis.readInt();
        byte[] receivedMac = new byte[32];  // SHA256 = 32 Bytes
        dis.readFully(receivedMac);
        byte[] data = new byte[dataLength];
        dis.readFully(data);

        // Korrigiert: HMAC verifizieren
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(macKey);
        byte[] expectedMac = mac.doFinal(data);

        if (!MessageDigest.isEqual(receivedMac, expectedMac)) {
            throw new SecurityException("Integritätsprüfung fehlgeschlagen");
        }

        return data;
    }

    // Korrigiert: Datei mit Hash
    public void secureSaveData(Object data, String path) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(data);
        }

        byte[] objectData = baos.toByteArray();

        // Korrigiert: SHA-256 Hash berechnen
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(objectData);

        // Korrigiert: Hash dann Daten schreiben
        try (FileOutputStream fos = new FileOutputStream(path)) {
            fos.write(hash);
            fos.write(objectData);
        }
    }

    public Object secureLoadData(String path) throws Exception {
        byte[] fileContent;
        try (FileInputStream fis = new FileInputStream(path)) {
            fileContent = fis.readAllBytes();
        }

        // Korrigiert: Hash und Daten extrahieren
        byte[] storedHash = Arrays.copyOfRange(fileContent, 0, 32);
        byte[] objectData = Arrays.copyOfRange(fileContent, 32, fileContent.length);

        // Korrigiert: Hash verifizieren
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] computedHash = digest.digest(objectData);

        if (!MessageDigest.isEqual(storedHash, computedHash)) {
            throw new SecurityException("Datei-Integritätsprüfung fehlgeschlagen");
        }

        try (ObjectInputStream ois = new ObjectInputStream(
                new ByteArrayInputStream(objectData))) {
            return ois.readObject();
        }
    }

    // Korrigiert: Download mit Prüfsummenverifizierung
    public void secureDownloadFile(String url, String checksumUrl, String outputPath)
            throws Exception {

        // Korrigiert: Erwartete Prüfsumme holen
        String expectedChecksum;
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new URL(checksumUrl).openStream()))) {
            expectedChecksum = reader.readLine().trim();
        }

        // Datei herunterladen
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        try (InputStream in = new URL(url).openStream();
             FileOutputStream out = new FileOutputStream(outputPath)) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
                digest.update(buffer, 0, bytesRead);
            }
        }

        // Korrigiert: Prüfsumme verifizieren
        String actualChecksum = bytesToHex(digest.digest());
        if (!actualChecksum.equalsIgnoreCase(expectedChecksum)) {
            new File(outputPath).delete();
            throw new SecurityException("Download-Integritätsprüfung fehlgeschlagen");
        }

        processDownloadedFile(outputPath);
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

Die Korrektur fügt kryptografische Integritätsverifizierung (HMAC, SHA-256, digitale Signaturen) vor dem Verarbeiten oder Verwenden von Daten hinzu.


Ausgenutzt in der Praxis

Protokoll-Integritätsangriffe

Verschiedene Protokolle ohne Integritätsprüfungen wurden ausgenutzt, um Daten im Transit zu modifizieren, einschließlich ungeschütztem HTTP-Verkehr und UDP-basierten Protokollen.

Firmware-Manipulation

Systeme, die Firmware-Updates ohne Integritätsverifizierung herunterladen, wurden kompromittiert, um bösartige Firmware zu installieren.


Tools zum Testen/Ausnutzen

  • Wireshark — Netzwerkverkehr auf Integritätsschutz analysieren.

  • mitmproxy — Ungeschützten Verkehr abfangen und modifizieren.

  • Burp Suite — Webanwendungs-Integritätsprüfungen testen.


CVE-Beispiele

Keine spezifischen CVEs referenzieren dieses CWE direkt, aber das Muster erscheint in vielen Schwachstellen, die ungeschützte Datenübertragung und -speicherung beinhalten.


Referenzen

  1. MITRE Corporation. "CWE-353: Missing Support for Integrity Check." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/353.html

  2. OWASP Foundation. "Cryptographic Failures." https://owasp.org/Top10/A02_2021-Cryptographic_Failures/

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