CVE-2023-1424
A memory corruption vulnerability exists in the MELSOFT Direct functionality of Mitsubishi Electric Corporation MELSEC iQ-F FX5U v1.240 and v1.260. A specially crafted network packet can lead to a buffer overflow. An attacker can send a malicious packet 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.
Mitsubishi Electric Corporation MELSEC iQ-F FX5U v1.240
Mitsubishi Electric Corporation MELSEC iQ-F FX5U v1.260
MELSEC iQ-F FX5U - https://www.mitsubishielectric.com/fa/products/cnt/plcf/items/index.html
10.0 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE-121 - Stack-based Buffer Overflow
The iQ-F FX5U is one of several members of the iQ-F series of Programmable Logic Controllers from Mitsubishi. The FX5U comes with built-in processor, power supply, Ethernet and 16 I/O points. The PLC can be configured to host several network services, such as an HTTP Server, FTP Server, FTP Client, MODBUS/TCP interface and several Mitsubishi-specific protocols.
The MELSOFT Direct protocol is used by the GXWorks Engineering software tool to interact with the PLC, enabling functionalities such as downloading and uploading files to the device, monitoring diagnostic information, updating device configurations and many others. The service responsible for implementing this protocol on the iQ-F is bound to UDP port 5560.
Each MELSOFT Direct request contains a field identifying the feature set being requested, as well as a second field identifying a subset of the specified feature. We have identified a stack-based buffer overflow in the feature set identified by the constant 0xC
, as well as the sub-features identified by the constants 0x10
and 0x11
.
For reference, MELSOFT Direct packets received on UDP port 5560 are initially dispatched from a function located at offset 0xffc4e24c
in version 1.260 of the iQ-FX5U firmware. The function responsible for parsing the 0xC
functionality is located at offset 0xffc4e508
, and this feature only implements handlers for command subset 0x10
(at offset 0xffce2602e
) and 0x11
(at offset 0xffe260a5
). Both the 0x10
and 0x11
implementations make use of a vulnerable function located at offset 0xffe260f4
, which is responsible for mapping the provided filepath to an internal reference identifier.
The vulnerable function expects four arguments:
* arg1
: must always be the value 0x0004
* filepath_length
: a value trusted to contain the length of the filepath
argument
* filepath
: a wchar filepath
* result
: a pointer to where the successful result of this function should be stored
Of these arguments, arg1
, filename_length
and filename
are all taken directly from the incoming MELSOFT Direct packet, and there are no sanitization or validation checks that occur on the supplied filename
or filename_length
parameters.
The callsite for the 0x10
feature is simply as follows:
0ffe26028 PUSHM r6-r8
0ffe2602a SUB #0x4, sp
0ffe2602c MOV.l r1, r8 # A reference to the MELSOFT Direct message structure, passed in `r1`, is copied to r8 to avoid clobbering
0ffe2602e MOV.w #0x0, #0x10[r8]
0ffe26032 MOV.l #0x8[r8], r7 # move a reference to the packet payload body into `r7`
0ffe26035 MOV.l #0xc[r8], r6
0ffe26038 MOVU.w #0xc[r7], r2 # `filepath_length` = *body->filepath_length
0ffe2603a MOVU.w #0xa[r7], r1 # `arg1` = *body->arg1
0ffe2603c ADD #0xe, r7, r3 # `filepath` = &body->filepath
0ffe2603f MOV.l sp, r4 # `result` = &result
0ffe26041 BSR.W #sub_ffe260f4 # sub_ffe260f4(*body->arg1, *body->filepath_length, &body->filepath, &result)
Below is an annotated decompilation of the vulnerable portion of function sub_ffe260f4
.
0ffe260f4 F_ERR sub_ffe260f4(int16_t arg1, uint16_t filepath_length, wchar16_t* filepath, uint8_t* result)
0ffe26100 uint16_t adjusted_length = filepath_length - 0x12 # Removing `wstrlen("$MELPRJ$")` from the provided length
0ffe26107 if (arg1 != 4)
0ffe26103 {
0ffe26108 return 0x40b0
0ffe26108 }
0ffe26111 else
0ffe26111 {
0ffe2611e wchar16 filename[0x42]
0ffe2611e memcpy(&filename, &filepath[9], adjusted_length) # Similarly, this memcpy is intended to remove `$MELPRJ$` directory from the start of the filepath
# Note the implicit trust in the attacker-controlled filepath and filepath_length fields
0ffe26128 ...
0ffe26132 }
The vulnerable memcpy
call at 0xFFE2611E
will attempt to move part of the attacker-controlled filepath
into a local stack variable, filename
, which is only 0x84 bytes long, but it will do so using the attacker-controlled filepath_length
parameter, such that up to 0xFFFF
bytes of data can be copied over top of the stack variable. An attacker who sends an 0xC
-> 0x10
or 0x11
MELSOFT Direct packet to a vulnerable device can provide arbitrary data that will be used to overflow an inadequately sized stack variable, leading to a denial-of-service within the RTOS task responsible for parsing the MELSOFT Direct protocol, and potentially remote code execution.
Vendor advisory: https://www.mitsubishielectric.com/en/psirt/vulnerability/pdf/2023-003_en.pdf
CISA advisory: https://www.cisa.gov/news-events/ics-advisories/icsa-23-143-03
2023-02-22 - Vendor Disclosure
2023-05-23 - Vendor Patch Release
2023-05-26 - Public Release
Discovered by Matt Wiseman of Cisco Talos.