Missing Support for Integrity Check

Description

Missing Support for Integrity Check is a vulnerability that occurs when a product employs a transmission protocol or data storage mechanism that lacks a built-in mechanism for verifying data integrity, such as a checksum, hash, or message authentication code. Without integrity verification, there is no way to determine if data has been corrupted during transmission or storage, whether accidentally through hardware failures and network errors, or maliciously through man-in-the-middle attacks and data tampering. The absence of integrity checking removes the first layer of application-level verification, following the end-to-end principle that integrity should be verified at the lowest possible level where the complete message can be examined. This weakness is particularly critical for protocols handling sensitive data, configuration files, firmware updates, or any data where undetected modification could have security implications.

Risk

Missing integrity checks allow both accidental corruption and deliberate tampering to go undetected. In network communications, attackers performing man-in-the-middle attacks can modify data in transit without detection - changing financial transaction amounts, modifying downloaded software to include malware, or altering configuration commands. Firmware and software updates without integrity verification are prime targets for supply chain attacks. Stored data without integrity protection can be silently corrupted, leading to data loss, system instability, or security bypasses. Network protocols without checksums may process corrupted packets, causing application crashes or incorrect behavior. The lack of integrity verification also means there's no non-repudiation - it's impossible to determine whether data was modified after transmission. Critical systems relying on data integrity for safety or security decisions become unreliable when integrity cannot be verified.

Solution

Implement integrity checking at the appropriate protocol layer. For network transmissions, use protocols with built-in integrity verification like TLS (which provides HMAC-based integrity) or implement application-layer message authentication codes (MACs). For data storage, compute and store cryptographic hashes (SHA-256 or stronger) alongside data and verify before use. For firmware and software updates, require cryptographic signatures that provide both integrity and authenticity. Use authenticated encryption modes like AES-GCM that combine confidentiality with integrity. Implement checksums at the packet level for protocols that need error detection without cryptographic overhead. Design protocols following the end-to-end principle with integrity verification at the application layer. Never assume lower-layer integrity (IP checksums, Ethernet CRC) provides sufficient protection for application data.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Data may become corrupted during transmission or storage without detection. Applications processing corrupted data may behave incorrectly, crash, or produce wrong results.
Non-RepudiationScope: Non-Repudiation

Without integrity verification, it's impossible to determine whether data was modified after creation, undermining audit trails and accountability.
AvailabilityScope: Availability

Corrupted data processed without detection can cause application crashes, system instability, or denial of service through malformed input.

Example Code

Vulnerable Code (Multiple Languages)

The following examples demonstrate missing integrity checks:

# Vulnerable: Network transmission without integrity check
import socket
import pickle

# Vulnerable: UDP communication without checksum
def vulnerable_send_command(host, port, command):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # Vulnerable: No integrity check on transmitted data
    # Attacker can modify packet in transit
    data = pickle.dumps(command)
    sock.sendto(data, (host, port))

# Vulnerable: TCP without application-level integrity
def vulnerable_receive_data(sock):
    # Vulnerable: Relying only on TCP checksum
    # TCP checksum is weak and not cryptographic
    data = sock.recv(4096)

    # Processing data without integrity verification
    return pickle.loads(data)  # Dangerous without integrity check

# Vulnerable: File storage without integrity
def vulnerable_save_config(config, filepath):
    with open(filepath, 'wb') as f:
        # Vulnerable: No hash stored with data
        pickle.dump(config, f)

def vulnerable_load_config(filepath):
    with open(filepath, 'rb') as f:
        # Vulnerable: No integrity verification
        # File could be corrupted or tampered
        return pickle.load(f)

# Vulnerable: Firmware download without integrity
import urllib.request

def vulnerable_download_firmware(url, output_path):
    # Vulnerable: Downloading without integrity verification
    urllib.request.urlretrieve(url, output_path)

    # Vulnerable: Using downloaded file without checksum
    apply_firmware(output_path)

# Vulnerable: Database backup without integrity
def vulnerable_backup_database(db_path, backup_path):
    import shutil
    # Vulnerable: No checksum computed or stored
    shutil.copy2(db_path, backup_path)

def vulnerable_restore_database(backup_path, db_path):
    import shutil
    # Vulnerable: Restoring without integrity check
    # Backup could be corrupted
    shutil.copy2(backup_path, db_path)

# Vulnerable: IPC without integrity check
import multiprocessing

def vulnerable_ipc_send(queue, data):
    # Vulnerable: No integrity protection
    queue.put(data)

def vulnerable_ipc_receive(queue):
    # Vulnerable: Processing without verification
    return queue.get()
// Vulnerable: Missing integrity checks in Java
import java.net.*;
import java.io.*;

public class VulnerableIntegrity {

    // Vulnerable: UDP without integrity
    public void vulnerableSendUDP(String host, int port, byte[] data)
            throws Exception {
        DatagramSocket socket = new DatagramSocket();
        InetAddress address = InetAddress.getByName(host);

        // Vulnerable: No checksum or MAC added to packet
        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();

        // Vulnerable: No integrity verification on received data
        return Arrays.copyOf(packet.getData(), packet.getLength());
    }

    // Vulnerable: File operations without integrity
    public void vulnerableSaveData(Object data, String path) throws Exception {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(path))) {
            // Vulnerable: No hash stored
            oos.writeObject(data);
        }
    }

    public Object vulnerableLoadData(String path) throws Exception {
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(path))) {
            // Vulnerable: No integrity check before deserializing
            return ois.readObject();
        }
    }

    // Vulnerable: HTTP download without integrity
    public void vulnerableDownloadFile(String url, String outputPath)
            throws Exception {
        URL fileUrl = new URL(url);
        try (InputStream in = fileUrl.openStream();
             FileOutputStream out = new FileOutputStream(outputPath)) {

            // Vulnerable: No checksum verification
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }
        // Vulnerable: Using file without integrity check
        processDownloadedFile(outputPath);
    }

    // Vulnerable: Serialized object transmission
    public void vulnerableSendObject(Socket socket, Serializable obj)
            throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(
            socket.getOutputStream());

        // Vulnerable: No integrity protection
        oos.writeObject(obj);
        oos.flush();
    }

    // Vulnerable: Configuration update without integrity
    public void vulnerableApplyConfig(byte[] configData) {
        // Vulnerable: Applying config without verification
        // Config could be corrupted or malicious
        Config config = parseConfig(configData);
        applyConfig(config);
    }
}
// Vulnerable: Missing integrity checks in C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

// Vulnerable: UDP transmission without checksum
int vulnerable_send_udp(int sockfd, const char *data, size_t len,
                         struct sockaddr_in *dest) {
    // Vulnerable: No integrity check added to data
    return sendto(sockfd, data, len, 0,
                  (struct sockaddr *)dest, sizeof(*dest));
}

int vulnerable_recv_udp(int sockfd, char *buffer, size_t len) {
    struct sockaddr_in sender;
    socklen_t sender_len = sizeof(sender);

    int received = recvfrom(sockfd, buffer, len, 0,
                            (struct sockaddr *)&sender, &sender_len);

    // Vulnerable: Processing data without integrity check
    return received;
}

// Vulnerable: File write without checksum
int vulnerable_write_data(const char *path, const void *data, size_t len) {
    FILE *f = fopen(path, "wb");
    if (!f) return -1;

    // Vulnerable: No checksum written
    fwrite(data, 1, len, f);
    fclose(f);

    return 0;
}

int vulnerable_read_data(const char *path, void *buffer, size_t max_len) {
    FILE *f = fopen(path, "rb");
    if (!f) return -1;

    // Vulnerable: Reading without integrity verification
    size_t read = fread(buffer, 1, max_len, f);
    fclose(f);

    return read;
}

// Vulnerable: Firmware update without signature
int vulnerable_apply_firmware(const char *firmware_path) {
    FILE *f = fopen(firmware_path, "rb");
    if (!f) return -1;

    // Vulnerable: No integrity check on firmware
    fseek(f, 0, SEEK_END);
    size_t size = ftell(f);
    fseek(f, 0, SEEK_SET);

    unsigned char *firmware = malloc(size);
    fread(firmware, 1, size, f);
    fclose(f);

    // Vulnerable: Applying potentially corrupted/malicious firmware
    flash_firmware(firmware, size);
    free(firmware);

    return 0;
}

// Vulnerable: IPC without integrity
typedef struct {
    int command;
    char data[256];
    // No checksum field
} ipc_message;

int vulnerable_send_ipc(int fd, ipc_message *msg) {
    // Vulnerable: No integrity protection
    return write(fd, msg, sizeof(*msg));
}

int vulnerable_recv_ipc(int fd, ipc_message *msg) {
    // Vulnerable: No integrity verification
    return read(fd, msg, sizeof(*msg));
}

Fixed Code (Multiple Languages)

# Fixed: Network transmission with integrity checks
import socket
import pickle
import hashlib
import hmac
import struct

# Fixed: UDP with HMAC integrity
def secure_send_command(host, port, command, secret_key):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    data = pickle.dumps(command)

    # Fixed: Compute HMAC for integrity
    mac = hmac.new(secret_key, data, hashlib.sha256).digest()

    # Fixed: Send data with MAC
    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)

    # Fixed: Parse length, MAC, and data
    length = struct.unpack('>I', packet[:4])[0]
    received_mac = packet[4:36]  # 32 bytes for SHA256
    data = packet[36:36+length]

    # Fixed: Verify MAC before processing
    expected_mac = hmac.new(secret_key, data, hashlib.sha256).digest()
    if not hmac.compare_digest(received_mac, expected_mac):
        raise ValueError("Integrity check failed")

    return pickle.loads(data)

# Fixed: File storage with hash
def secure_save_config(config, filepath):
    data = pickle.dumps(config)

    # Fixed: Compute and store hash
    hash_value = hashlib.sha256(data).digest()

    with open(filepath, 'wb') as f:
        f.write(hash_value)  # First 32 bytes are hash
        f.write(data)

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

    # Fixed: Verify hash before loading
    computed_hash = hashlib.sha256(data).digest()
    if not hmac.compare_digest(stored_hash, computed_hash):
        raise ValueError("Config file integrity check failed")

    return pickle.loads(data)

# Fixed: Firmware download with checksum verification
import urllib.request

def secure_download_firmware(url, checksum_url, output_path):
    # Fixed: Download expected checksum
    with urllib.request.urlopen(checksum_url) as response:
        expected_checksum = response.read().decode().strip()

    # Download firmware
    urllib.request.urlretrieve(url, output_path)

    # Fixed: Verify checksum
    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 integrity check failed")

    apply_firmware(output_path)

# Fixed: Using TLS for transport integrity
import ssl

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

    # Fixed: TLS provides integrity via HMAC
    with socket.create_connection((host, port)) as sock:
        with context.wrap_socket(sock, server_hostname=host) as ssock:
            return ssock

# Fixed: Database backup with integrity
def secure_backup_database(db_path, backup_path, metadata_path):
    import shutil

    # Copy database
    shutil.copy2(db_path, backup_path)

    # Fixed: Compute and store hash
    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):
    # Fixed: Verify integrity before restore
    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 integrity check failed")

    import shutil
    shutil.copy2(backup_path, db_path)
// Fixed: Integrity checks in Java
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class SecureIntegrity {

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

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

        // Fixed: Combine MAC and data
        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);

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

        if (!MessageDigest.isEqual(receivedMac, expectedMac)) {
            throw new SecurityException("Integrity check failed");
        }

        return data;
    }

    // Fixed: File with 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();

        // Fixed: Compute SHA-256 hash
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(objectData);

        // Fixed: Write hash then data
        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();
        }

        // Fixed: Extract hash and data
        byte[] storedHash = Arrays.copyOfRange(fileContent, 0, 32);
        byte[] objectData = Arrays.copyOfRange(fileContent, 32, fileContent.length);

        // Fixed: Verify hash
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] computedHash = digest.digest(objectData);

        if (!MessageDigest.isEqual(storedHash, computedHash)) {
            throw new SecurityException("File integrity check failed");
        }

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

    // Fixed: Download with checksum verification
    public void secureDownloadFile(String url, String checksumUrl, String outputPath)
            throws Exception {

        // Fixed: Get expected checksum
        String expectedChecksum;
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new URL(checksumUrl).openStream()))) {
            expectedChecksum = reader.readLine().trim();
        }

        // Download file
        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);
            }
        }

        // Fixed: Verify checksum
        String actualChecksum = bytesToHex(digest.digest());
        if (!actualChecksum.equalsIgnoreCase(expectedChecksum)) {
            new File(outputPath).delete();
            throw new SecurityException("Download integrity check failed");
        }

        processDownloadedFile(outputPath);
    }

    // Fixed: TLS for transport
    public Socket secureConnect(String host, int port) throws Exception {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        SSLSocketFactory factory = context.getSocketFactory();

        // Fixed: TLS provides integrity
        return factory.createSocket(host, port);
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}
// Fixed: Integrity checks in C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>

// Fixed: UDP with HMAC
typedef struct {
    unsigned char mac[32];  // SHA256 HMAC
    uint32_t data_len;
    unsigned char data[];   // Flexible array
} secure_packet;

int secure_send_udp(int sockfd, const unsigned char *data, size_t len,
                     const unsigned char *key, size_t key_len,
                     struct sockaddr_in *dest) {

    // Allocate packet with MAC
    size_t packet_size = sizeof(secure_packet) + len;
    secure_packet *packet = malloc(packet_size);

    packet->data_len = htonl(len);
    memcpy(packet->data, data, len);

    // Fixed: Compute HMAC
    unsigned int mac_len;
    HMAC(EVP_sha256(), key, key_len, data, len, packet->mac, &mac_len);

    int result = sendto(sockfd, packet, packet_size, 0,
                        (struct sockaddr *)dest, sizeof(*dest));
    free(packet);
    return result;
}

int secure_recv_udp(int sockfd, unsigned char *buffer, size_t max_len,
                     const unsigned char *key, size_t key_len) {

    unsigned char recv_buffer[65535];
    struct sockaddr_in sender;
    socklen_t sender_len = sizeof(sender);

    int received = recvfrom(sockfd, recv_buffer, sizeof(recv_buffer), 0,
                            (struct sockaddr *)&sender, &sender_len);

    if (received < sizeof(secure_packet)) {
        return -1;
    }

    secure_packet *packet = (secure_packet *)recv_buffer;
    size_t data_len = ntohl(packet->data_len);

    // Fixed: Verify HMAC
    unsigned char expected_mac[32];
    unsigned int mac_len;
    HMAC(EVP_sha256(), key, key_len, packet->data, data_len,
         expected_mac, &mac_len);

    if (CRYPTO_memcmp(packet->mac, expected_mac, 32) != 0) {
        return -1;  // Integrity check failed
    }

    // Fixed: Data verified, safe to copy
    if (data_len > max_len) {
        return -1;
    }

    memcpy(buffer, packet->data, data_len);
    return data_len;
}

// Fixed: File with SHA256 hash
int secure_write_data(const char *path, const void *data, size_t len) {
    FILE *f = fopen(path, "wb");
    if (!f) return -1;

    // Fixed: Compute SHA256 hash
    unsigned char hash[32];
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(ctx, data, len);
    EVP_DigestFinal_ex(ctx, hash, NULL);
    EVP_MD_CTX_free(ctx);

    // Fixed: Write hash then data
    fwrite(hash, 1, 32, f);
    fwrite(data, 1, len, f);
    fclose(f);

    return 0;
}

int secure_read_data(const char *path, void *buffer, size_t max_len) {
    FILE *f = fopen(path, "rb");
    if (!f) return -1;

    unsigned char stored_hash[32];
    fread(stored_hash, 1, 32, f);

    fseek(f, 0, SEEK_END);
    size_t total_size = ftell(f);
    size_t data_len = total_size - 32;
    fseek(f, 32, SEEK_SET);

    if (data_len > max_len) {
        fclose(f);
        return -1;
    }

    fread(buffer, 1, data_len, f);
    fclose(f);

    // Fixed: Verify hash
    unsigned char computed_hash[32];
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(ctx, buffer, data_len);
    EVP_DigestFinal_ex(ctx, computed_hash, NULL);
    EVP_MD_CTX_free(ctx);

    if (CRYPTO_memcmp(stored_hash, computed_hash, 32) != 0) {
        return -1;  // Integrity check failed
    }

    return data_len;
}

// Fixed: Firmware with signature verification
int secure_apply_firmware(const char *firmware_path, const char *sig_path,
                           EVP_PKEY *public_key) {

    // Read firmware
    FILE *f = fopen(firmware_path, "rb");
    if (!f) return -1;

    fseek(f, 0, SEEK_END);
    size_t size = ftell(f);
    fseek(f, 0, SEEK_SET);

    unsigned char *firmware = malloc(size);
    fread(firmware, 1, size, f);
    fclose(f);

    // Read signature
    f = fopen(sig_path, "rb");
    if (!f) {
        free(firmware);
        return -1;
    }

    fseek(f, 0, SEEK_END);
    size_t sig_size = ftell(f);
    fseek(f, 0, SEEK_SET);

    unsigned char *signature = malloc(sig_size);
    fread(signature, 1, sig_size, f);
    fclose(f);

    // Fixed: Verify signature
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, public_key);
    EVP_DigestVerifyUpdate(ctx, firmware, size);

    int verified = EVP_DigestVerifyFinal(ctx, signature, sig_size);
    EVP_MD_CTX_free(ctx);
    free(signature);

    if (verified != 1) {
        free(firmware);
        return -1;  // Signature verification failed
    }

    // Fixed: Only apply after verification
    int result = flash_firmware(firmware, size);
    free(firmware);

    return result;
}

The fix adds cryptographic integrity verification (HMAC, SHA-256, digital signatures) before processing or using data.


Exploited in the Wild

Protocol Integrity Attacks

Various protocols without integrity checks have been exploited to modify data in transit, including unprotected HTTP traffic and UDP-based protocols.

Firmware Tampering

Systems downloading firmware updates without integrity verification have been compromised to install malicious firmware.


Tools to Test/Exploit

  • Wireshark — Analyze network traffic for integrity protection.

  • mitmproxy — Intercept and modify unprotected traffic.

  • Burp Suite — Test web application integrity checks.


CVE Examples

No specific CVEs directly reference this CWE, but the pattern appears in many vulnerabilities involving unprotected data transmission and storage.


References

  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