Unsachgemäße Durchsetzung der Nachrichtenintegrität während der Übertragung in einem Kommunikationskanal
Beschreibung
Unsachgemäße Durchsetzung der Nachrichtenintegrität während der Übertragung tritt auf, wenn ein Produkt einen Kommunikationskanal mit einem Endpunkt aufbaut und Nachrichten von diesem Endpunkt empfängt, aber nicht ausreichend sicherstellt, dass Nachrichten während der Übertragung nicht modifiziert wurden. Ohne ordnungsgemäße Integritätsprüfmechanismen können Angreifer, die auf den Netzwerkpfad zwischen kommunizierenden Parteien zugreifen können, Nachrichteninhalte ohne Erkennung modifizieren. Dies umfasst das Ändern von Datenwerten, das Einschleusen bösartiger Inhalte, das Wiedereinspielen alter Nachrichten oder das vollständige Ersetzen von Nachrichten.
Risiko
Diese Schwachstelle ermöglicht verschiedene Man-in-the-Middle-Angriffsszenarien. Angreifer können Finanztransaktionen modifizieren, um Beträge oder Ziele zu ändern. Befehls- und Kontrollnachrichten können verändert werden, um andere Operationen auszuführen. Software-Update-Mechanismen können kompromittiert werden, um bösartige Payloads zu liefern. Konfigurationsdaten können geändert werden, um Sicherheitseinstellungen zu schwächen. Authentifizierungs-Tokens oder Session-Daten können für Privilegieneskalation modifiziert werden. Das Risiko ist besonders schwerwiegend bei Protokollen, die sensible oder sicherheitskritische Informationen übertragen, da Modifikationen unbemerkt bleiben können, bis erheblicher Schäden entstanden ist.
Lösung
Implementieren Sie kryptographische Nachrichtenintegritätsprüfung mit HMACs (Hash-based Message Authentication Codes) oder digitalen Signaturen. Verwenden Sie authentifizierte Verschlüsselungsmodi (GCM, CCM), die sowohl Vertraulichkeit als auch Integrität bieten. Setzen Sie TLS/HTTPS für Transportsicherheit ein, das eingebaute Integritätsprüfungen bietet. Fügen Sie Sequenznummern oder Zeitstempel hinzu, um Replay-Angriffe zu verhindern. Überprüfen Sie die Nachrichtenintegrität, bevor Sie Nachrichteninhalte verarbeiten. Für signierte Nachrichten validieren Sie Signaturen mit vertrauenswürdigen öffentlichen Schlüsseln. Erwägen Sie die Verwendung etablierter Protokolle (TLS, SSH) anstelle der Implementierung benutzerdefinierter Integritätsmechanismen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Integrität Anwendungsdaten modifizieren - Angreifer können Nachrichteninhalte während der Übertragung ohne Erkennung modifizieren. |
| Integrität, Vertraulichkeit | Bereich: Integrität, Vertraulichkeit Privilegien erlangen oder Identität annehmen - Wenn Angreifer Endpunkte fälschen oder Nachrichten modifizieren können, können sie Privilegien erlangen, die für legitime Parteien bestimmt sind. |
Beispielcode
Anfälliger Code
# Anfällig: Keine Nachrichtenintegritätsprüfung
import socket
import json
class VulnerableClient:
def __init__(self, host, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
def send_command(self, command, amount):
# Anfällig: Kein Integritätsschutz
message = json.dumps({
'command': command,
'amount': amount
})
self.sock.send(message.encode())
def receive_response(self):
# Anfällig: Keine Verifizierung, dass Antwort nicht modifiziert wurde
data = self.sock.recv(4096)
return json.loads(data.decode())
# Angreifer im Netzwerk kann "transfer 100" zu "transfer 100000" ändern
// Anfällig: Benutzerdefiniertes Protokoll ohne Nachrichtenauthentifizierung
public class VulnerableProtocol {
public void sendMessage(OutputStream out, String command, Map<String, String> params)
throws IOException {
// Anfällig: Keine Integritätsprüfung
StringBuilder message = new StringBuilder();
message.append(command).append("|");
for (Map.Entry<String, String> entry : params.entrySet()) {
message.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
out.write(message.toString().getBytes());
out.flush();
// Angreifer kann Nachrichteninhalt während der Übertragung modifizieren
}
public Map<String, String> receiveMessage(InputStream in) throws IOException {
byte[] buffer = new byte[4096];
int bytesRead = in.read(buffer);
// Anfällig: Empfangenen Daten ohne Verifizierung vertrauen
String message = new String(buffer, 0, bytesRead);
return parseMessage(message);
}
}
# Anfällig: Software-Update ohne Verifizierung
import urllib.request
class VulnerableUpdater:
def download_update(self, url):
# Anfällig: Keine Verifizierung der Update-Integrität
response = urllib.request.urlopen(url)
update_data = response.read()
# Angreifer könnte bösartiges Update liefern
self.install_update(update_data)
def install_update(self, data):
# Potenziell modifiziertes/bösartiges Update installieren
with open('/opt/myapp/update.bin', 'wb') as f:
f.write(data)
# Update ausführen...
Korrigierter Code
# Korrigiert: Nachrichtenintegrität mit HMAC
import socket
import json
import hmac
import hashlib
import os
import time
class FixedClient:
def __init__(self, host, port, shared_secret):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
self.secret = shared_secret.encode()
self.sequence = 0
def send_command(self, command, amount):
self.sequence += 1
message = json.dumps({
'command': command,
'amount': amount,
'sequence': self.sequence,
'timestamp': time.time()
})
# Korrigiert: HMAC für Integrität berechnen
mac = hmac.new(self.secret, message.encode(), hashlib.sha256)
signature = mac.hexdigest()
# Nachricht mit Signatur senden
packet = json.dumps({
'message': message,
'signature': signature
})
self.sock.send(packet.encode())
def receive_response(self):
data = self.sock.recv(4096)
packet = json.loads(data.decode())
message = packet['message']
received_signature = packet['signature']
# Korrigiert: HMAC überprüfen, bevor Daten vertraut werden
expected_mac = hmac.new(self.secret, message.encode(), hashlib.sha256)
expected_signature = expected_mac.hexdigest()
if not hmac.compare_digest(received_signature, expected_signature):
raise SecurityError("Nachrichtenintegritätsprüfung fehlgeschlagen!")
return json.loads(message)
// Korrigiert: Nachrichtenauthentifizierung mit digitalen Signaturen
import java.security.*;
import javax.crypto.*;
public class FixedProtocol {
private PrivateKey signingKey;
private PublicKey verifyKey;
public FixedProtocol(PrivateKey signingKey, PublicKey verifyKey) {
this.signingKey = signingKey;
this.verifyKey = verifyKey;
}
public void sendMessage(OutputStream out, String command, Map<String, String> params)
throws Exception {
StringBuilder message = new StringBuilder();
message.append(command).append("|");
message.append(System.currentTimeMillis()).append("|");
for (Map.Entry<String, String> entry : params.entrySet()) {
message.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
byte[] messageBytes = message.toString().getBytes("UTF-8");
// Korrigiert: Nachricht signieren
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(signingKey);
sig.update(messageBytes);
byte[] signature = sig.sign();
// Länge + Nachricht + Signatur senden
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(messageBytes.length);
dos.write(messageBytes);
dos.writeInt(signature.length);
dos.write(signature);
dos.flush();
}
public Map<String, String> receiveMessage(InputStream in) throws Exception {
DataInputStream dis = new DataInputStream(in);
int msgLength = dis.readInt();
byte[] messageBytes = new byte[msgLength];
dis.readFully(messageBytes);
int sigLength = dis.readInt();
byte[] signature = new byte[sigLength];
dis.readFully(signature);
// Korrigiert: Signatur verifizieren, bevor Daten vertraut werden
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(verifyKey);
sig.update(messageBytes);
if (!sig.verify(signature)) {
throw new SecurityException("Nachrichtensignaturverifizierung fehlgeschlagen!");
}
return parseMessage(new String(messageBytes, "UTF-8"));
}
}
# Korrigiert: Software-Update mit kryptographischer Verifizierung
import urllib.request
import hashlib
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
class FixedUpdater:
def __init__(self, public_key_pem):
self.public_key = serialization.load_pem_public_key(public_key_pem)
def download_update(self, url, signature_url, expected_hash):
# Update herunterladen
response = urllib.request.urlopen(url)
update_data = response.read()
# Korrigiert: Hash verifizieren
actual_hash = hashlib.sha256(update_data).hexdigest()
if actual_hash != expected_hash:
raise SecurityError("Update-Hash stimmt nicht überein!")
# Signatur herunterladen
sig_response = urllib.request.urlopen(signature_url)
signature = sig_response.read()
# Korrigiert: Digitale Signatur verifizieren
try:
self.public_key.verify(
signature,
update_data,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
except Exception as e:
raise SecurityError(f"Update-Signaturverifizierung fehlgeschlagen: {e}")
# Signatur gültig, sicher zu installieren
self.install_update(update_data)
def install_update(self, data):
with open('/opt/myapp/update.bin', 'wb') as f:
f.write(data)
# Update ausführen...
// Korrigiert: API mit Request/Response-Signierung
const crypto = require('crypto');
class SecureApiClient {
constructor(apiKey, secretKey) {
this.apiKey = apiKey;
this.secretKey = secretKey;
}
async makeRequest(endpoint, data) {
const timestamp = Date.now().toString();
const nonce = crypto.randomBytes(16).toString('hex');
const payload = JSON.stringify({
data,
timestamp,
nonce
});
// Korrigiert: Request signieren
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(payload)
.digest('hex');
const response = await fetch(endpoint, {
method: 'POST',
body: payload,
headers: {
'Content-Type': 'application/json',
'X-Api-Key': this.apiKey,
'X-Signature': signature,
'X-Timestamp': timestamp,
'X-Nonce': nonce
}
});
const responseBody = await response.text();
const responseSignature = response.headers.get('X-Response-Signature');
// Korrigiert: Response-Signatur verifizieren
const expectedSignature = crypto
.createHmac('sha256', this.secretKey)
.update(responseBody)
.digest('hex');
if (responseSignature !== expectedSignature) {
throw new Error('Response-Integritätsverifizierung fehlgeschlagen!');
}
return JSON.parse(responseBody);
}
}
Verwandte CWEs
- CWE-345: Insufficient Verification of Data Authenticity (Eltern)
- CWE-354: Improper Validation of Integrity Check Value (verwandt)
- CWE-494: Download of Code Without Integrity Check (verwandt)
- CWE-353: Missing Support for Integrity Check (verwandt)
Referenzen
- MITRE Corporation. "CWE-924: Improper Enforcement of Message Integrity During Transmission in a Communication Channel." https://cwe.mitre.org/data/definitions/924.html
- OWASP. "Cryptographic Failures." OWASP Top Ten 2021.
- NIST. "Guidelines for the Selection and Use of Transport Layer Security (TLS) Implementations."