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
| Auswirkung | Details |
|---|---|
| Integrität | Umfang: 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-Abstreitbarkeit | Umfang: 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ügbarkeit | Umfang: 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
-
MITRE Corporation. "CWE-353: Missing Support for Integrity Check." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/353.html
-
OWASP Foundation. "Cryptographic Failures." https://owasp.org/Top10/A02_2021-Cryptographic_Failures/
-
RFC 5246. "The Transport Layer Security (TLS) Protocol." https://tools.ietf.org/html/rfc5246