My first CVE, found in the embedded TCP/IP stack PicoTCP.

Affected Products#

TASS PicoTCP versions <= 1.7.

This is all versions, as the project is no longer maintained.

Vulnerability Description#

The vulnerability is an integer overflow that results in denial of service, present in the implementation of the ICMPv6 packet processing functionality of the library.

The library is only vulnerable when compiled with support for ethernet.

Vulnerability Severity#

6.1 CVSS 3.1 score denial of service.

Technical Breakdown#

The vulnerability can be seen in the following C code snippet for the ICMPv6 memory allocation function pico_ipv6_alloc() in the module file “pico_ipv6.c”.

static struct pico_frame *pico_ipv6_alloc(struct pico_protocol *self, struct pico_device *dev, uint16_t size)

{
	struct pico_frame *f = NULL;
	IGNORE_PARAMETER(self);
	
	if (0) {}
	
	// ... SNIP
	
	else {
	
	#ifdef PICO_SUPPORT_ETH
	
	// Function call is vulnerable to a integer overflow, resulting in an under-allocation of memory
	f = pico_proto_ethernet.alloc(&pico_proto_ethernet, dev, (uint16_t)(size + PICO_SIZE_IP6HDR));
	
	#else
	
	// ...SNIP

	if (!f) return NULL;
	
	// Alocated space for "f" is too small, and results in a large out-of-bounds write, leading to denial-of-service
	f->net_len = PICO_SIZE_IP6HDR;
	f->transport_hdr = f->net_hdr + PICO_SIZE_IP6HDR;
	f->transport_len = (uint16_t)size;
	
	/* Datalink size is accounted for in pico_datalink_send (link layer) */
	f->len = (uint32_t)(size + PICO_SIZE_IP6HDR);
	
	return f;
}

The size of the data contained within the ICMPv6 packet is stored in a u16 bit representation, and then has the size of the ICMPv6 header added to it (a constant 40 bytes) which is then cast to a u16 bit representation - (uint16_t)(size + PICO_SIZE_IP6HDR).

If the malicious ping packet has a size of 65496 or greater it results in an integer overflow in the memory allocation for the packet, resulting in an under-allocation of memory for the struct f.

The malicious packet is then processed and copied into the under-allocated struct f , resulting in an out-of-bounds write and subsequent denial of service.

Suggested Fix#

If you are not using ethernet functionality, do not compile the library with the functionality enabled.

There is no vendor provided fix available, you must patch the source code of the library to change the size of the casted variable to uint32_t as below to avoid the possibility of integer overflow.

f = pico_proto_ethernet.alloc(&pico_proto_ethernet, dev, (uint32_t)(size + PICO_SIZE_IP6HDR));