Improper Enforcement of Message Integrity During Transmission in a Communication Channel
Description
Improper Enforcement of Message Integrity During Transmission occurs when a product establishes a communication channel with an endpoint and receives messages from that endpoint, but does not sufficiently ensure that messages were not modified during transmission. Without proper integrity verification mechanisms, attackers who can access the network path between communicating parties can modify message contents without detection. This includes altering data values, injecting malicious content, replaying old messages, or completely substituting messages.
Risk
This vulnerability enables various man-in-the-middle attack scenarios. Attackers can modify financial transactions to change amounts or destinations. Command and control messages can be altered to execute different operations. Software update mechanisms can be compromised to deliver malicious payloads. Configuration data can be changed to weaken security settings. Authentication tokens or session data can be modified for privilege escalation. The risk is particularly severe in protocols that transmit sensitive or security-critical information, as modifications may go undetected until significant damage has occurred.
Solution
Implement cryptographic message integrity verification using HMACs (Hash-based Message Authentication Codes) or digital signatures. Use authenticated encryption modes (GCM, CCM) that provide both confidentiality and integrity. Employ TLS/HTTPS for transport security, which provides built-in integrity checks. Include sequence numbers or timestamps to prevent replay attacks. Verify message integrity before processing any message content. For signed messages, validate signatures using trusted public keys. Consider using established protocols (TLS, SSH) rather than implementing custom integrity mechanisms.
Common Consequences
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Modify Application Data - Attackers can modify message contents during transmission without detection. |
| Integrity, Confidentiality | Scope: Integrity, Confidentiality Gain Privileges or Assume Identity - If attackers can spoof endpoints or modify messages, they may gain privileges intended for legitimate parties. |
Example Code
Vulnerable Code
# Vulnerable: No message integrity verification
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):
# Vulnerable: No integrity protection
message = json.dumps({
'command': command,
'amount': amount
})
self.sock.send(message.encode())
def receive_response(self):
# Vulnerable: No verification that response wasn't modified
data = self.sock.recv(4096)
return json.loads(data.decode())
# Attacker on network can modify "transfer 100" to "transfer 100000"
// Vulnerable: Custom protocol without message authentication
public class VulnerableProtocol {
public void sendMessage(OutputStream out, String command, Map<String, String> params)
throws IOException {
// Vulnerable: No integrity check
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();
// Attacker can modify message content in transit
}
public Map<String, String> receiveMessage(InputStream in) throws IOException {
byte[] buffer = new byte[4096];
int bytesRead = in.read(buffer);
// Vulnerable: Trusting received data without verification
String message = new String(buffer, 0, bytesRead);
return parseMessage(message);
}
}
// Vulnerable: Configuration update without integrity check
typedef struct {
char server_address[256];
int port;
int security_level;
char admin_password[64];
} Config;
int vulnerable_update_config(int socket_fd) {
Config new_config;
// Vulnerable: Reading config directly from network without verification
ssize_t bytes_read = recv(socket_fd, &new_config, sizeof(Config), 0);
if (bytes_read == sizeof(Config)) {
// Apply config without checking integrity
apply_config(&new_config); // Attacker modified config accepted!
return 0;
}
return -1;
}
// Vulnerable: API without message signing
async function vulnerableApiCall(endpoint, data) {
// Vulnerable: No integrity verification of response
const response = await fetch(endpoint, {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' }
});
// Attacker could have modified the response
const result = await response.json();
return result; // Processing potentially modified data
}
# Vulnerable: Software update without verification
import urllib.request
class VulnerableUpdater:
def download_update(self, url):
# Vulnerable: No verification of update integrity
response = urllib.request.urlopen(url)
update_data = response.read()
# Attacker could serve malicious update
self.install_update(update_data)
def install_update(self, data):
# Installing potentially modified/malicious update
with open('/opt/myapp/update.bin', 'wb') as f:
f.write(data)
# Execute update...
Fixed Code
# Fixed: Message integrity with HMAC
import socket
import json
import hmac
import hashlib
import os
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()
})
# Fixed: Calculate HMAC for integrity
mac = hmac.new(self.secret, message.encode(), hashlib.sha256)
signature = mac.hexdigest()
# Send message with signature
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']
# Fixed: Verify HMAC before trusting data
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("Message integrity check failed!")
return json.loads(message)
// Fixed: Message authentication with digital signatures
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");
// Fixed: Sign the message
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(signingKey);
sig.update(messageBytes);
byte[] signature = sig.sign();
// Send length + message + signature
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);
// Fixed: Verify signature before trusting data
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(verifyKey);
sig.update(messageBytes);
if (!sig.verify(signature)) {
throw new SecurityException("Message signature verification failed!");
}
return parseMessage(new String(messageBytes, "UTF-8"));
}
}
// Fixed: Configuration update with integrity check
#include <openssl/evp.h>
#include <openssl/hmac.h>
typedef struct {
char server_address[256];
int port;
int security_level;
char admin_password[64];
unsigned char hmac[32]; // SHA-256 HMAC
} SecureConfig;
static const unsigned char shared_key[] = "..."; // Should be securely stored
int fixed_update_config(int socket_fd) {
SecureConfig new_config;
ssize_t bytes_read = recv(socket_fd, &new_config, sizeof(SecureConfig), 0);
if (bytes_read != sizeof(SecureConfig)) {
return -1;
}
// Fixed: Verify HMAC before trusting config
unsigned char expected_hmac[32];
unsigned int hmac_len;
// Calculate HMAC over config data (excluding the HMAC field itself)
HMAC(EVP_sha256(),
shared_key, sizeof(shared_key),
(unsigned char*)&new_config, sizeof(SecureConfig) - 32,
expected_hmac, &hmac_len);
// Fixed: Constant-time comparison
if (CRYPTO_memcmp(new_config.hmac, expected_hmac, 32) != 0) {
fprintf(stderr, "Config integrity check failed!\n");
return -1;
}
// Config verified, safe to apply
apply_config(&new_config);
return 0;
}
// Fixed: API with request/response signing
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
});
// Fixed: Sign the request
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');
// Fixed: Verify response signature
const expectedSignature = crypto
.createHmac('sha256', this.secretKey)
.update(responseBody)
.digest('hex');
if (responseSignature !== expectedSignature) {
throw new Error('Response integrity verification failed!');
}
return JSON.parse(responseBody);
}
}
# Fixed: Software update with cryptographic verification
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):
# Download update
response = urllib.request.urlopen(url)
update_data = response.read()
# Fixed: Verify hash
actual_hash = hashlib.sha256(update_data).hexdigest()
if actual_hash != expected_hash:
raise SecurityError("Update hash mismatch!")
# Download signature
sig_response = urllib.request.urlopen(signature_url)
signature = sig_response.read()
# Fixed: Verify digital signature
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 signature verification failed: {e}")
# Signature valid, safe to install
self.install_update(update_data)
def install_update(self, data):
with open('/opt/myapp/update.bin', 'wb') as f:
f.write(data)
# Execute update...
Related CWEs
- CWE-345: Insufficient Verification of Data Authenticity (parent)
- CWE-354: Improper Validation of Integrity Check Value (related)
- CWE-494: Download of Code Without Integrity Check (related)
- CWE-353: Missing Support for Integrity Check (related)
References
- 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."