CVE-2025-26858
A buffer overflow vulnerability exists in the Modbus TCP functionality of Socomec DIRIS Digiware M-70 1.6.9. A specially crafted set of network packets can lead to denial of service. An attacker can send a sequence of unauthenticated packets to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Socomec DIRIS Digiware M-70 1.6.9
DIRIS Digiware M-70 - https://www.socomec.us/en-us/reference/48290222
8.6 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H
CWE-20 - Improper Input Validation
The DIRIS Digiware M-50/M-70 gateway functions as the access point for industrial power monitoring systems, providing power supply and communication connection to devices in the electrical installation. It also includes a webserver WEBVIEW-M for the remote visualisation and analysis of measurements and consumption.
The issue arises when processing packet data sent to the Modbus TCP server on port 502. Below is a snippet of the decompilation of the vulnerable function. The function modbusServerProcessData extracts a length field from the Modbus Application Protocol header at [1]. This length field is checked at [2] to ensure it is less than the total size of the received data. However, the packet length is then incremented by 6 and stored in a structure [4], which is used as the size argument for the Mem_Copy function at [5]. The check at line [2] is inadequate to prevent a buffer overflow due to this increment at [4]. For instance, a received length of 261 (0x105) is the maximum size for the buffer pointed to by rx_buf, while a packet length of 260 (0x104) passes the check at [2]. This results in a size of 266 (0x10a) used at [5], causing a buffer overread of 5 bytes from rx_buf at [5]. Additionally, the destination buffer target_object->rx_buf is 256 (0x100) bytes in length, which is smaller than the source buffer rx_buf, which is 261 (0x105) bytes in length. This leads to a buffer overwrite of 10 (0xa) bytes in the destination buffer target_object->rx_buf at [5].
080fede0 uint32_t modbusServerProcessData(int32_t connNbr, int32_t sock_id, int32_t rx_buf, int32_t rx_len)
...
080fee10 uint32_t r0_6 = (uint32_t)*(uint16_t*)(rx_len - (uint32_t)i + rx_buf + 4); /* [1] */
080fee16 packet_length = byte_swap(r0_6);
...
080fee1e if (packet_length < rx_len) /* [2] */
080fee1e {
...
080fee38 target_object = getNextItemInList(&data_2001242c[connNbr].head, sock_id); /* [3] */
...
080fee3c
080fee42 if (target_object)
080fee42 {
080fee48 target_object->len = packet_length + 6; /* [4] */
...
080fee5e Mem_Copy(&*(uint32_t*)((char*)target_object->rx_buf + 0), rx_len - (uint32_t)i + rx_buf, (uint32_t)target_object->len); /* [5] */
To grasp the impact of the buffer overflow, it’s crucial to understand the structure of target_object, used as a destination buffer. A series of these objects are sequentially located in memory. Below is an example of this structure before the buffer overflow.
struct target_object [2]
{
[0]
{
void* nextPtr = 0xd0b20fd8;
void* prevPtr = 0x2001243c;
uint8_t rx_buf [0x100];
uint16_t len;
uint16_t field_10a;
};
[1]
{
void* nextPtr = 0xd0b210e4;
void* prevPtr = 0x2001243c;
uint8_t rx_buf [0x100];
uint16_t len;
uint16_t field_10a;
};
}
For illustration, below is how the structure appears in memory after the buffer overflow. Here, the ASCII character A (0x41) represents attacker-controlled data. At [7], the least significant byte of target_object[1].nextPtr is controlled by the attacker. When the buffer at [6] overflows, 10 additional bytes are overwritten past the end of target_object[0].rx_buf. However, only the first 5 bytes contain attacker-controlled packet data. These 5 bytes attacker-controlled bytes will overwrite target_object[0].len, target_object[0].field_10a and one byte of target_object[1].nextPtr at [7]. The 5 remaining bytes of the overflow are from the memory adjacent in memory to rx_buf the argument passed to modbusServerProcessData which happen to be NULL. Of these 5 NULL bytes, 3 of them overwrite target_object[1].nextPtr at [7] and 2 of them overwrite target_object[1].nextPtr at [8].
struct target_object [2]
{
[0]
{
void* nextPtr = 0xd0b20fd8;
void* prevPtr = 0x2001243c;
uint8_t rx_buf [0x100]; /* [6] */
uint16_t len;
uint16_t field_10a;
};
[1]
{
void* nextPtr = 0x00000041; /* [7] */
void* prevPtr = 0x20010000; /* [8] */
uint8_t rx_buf [0x100];
uint16_t len;
uint16_t field_10a;
};
}
This attack involves three packets within the same TCP session. The first packet overflows target_object[0].rx_buf and overwrites target_object[1].nextPtr and part of target_object[1].prevPtr. The second packet retrieves a pointer to target_object[1] using getNextItemInList at [3] and writes its data to target_object[1].rx_buf. The third packet obtains the partially attacker-controlled address stored at target_object[1].nextPtr using getNextItemInList at [3] and tries to write packet data there. This attempt fails, causing the device to crash and reboot.
Using the Cyber Security user profile in WEBVIEW-M, disable Modbus over Ethernet. This change will disable Modbus TCP (port 502).
Vendor advisory: https://www.socomec.fr/sites/default/files/2025-10/CVE-2025-26858—Diris-Digiware-Mxx-Dxx-_VULNERABILITIES_2025-10-01-16-38-44_English_0.pdf
2025-03-03 - Vendor Disclosure
2025-10-01 - Vendor Patch Release
2025-12-01 - Public Release
Discovered by Kelly Patterson of Cisco Talos.