According to the Usenix paper, a libmodbus version had been used for OpenPLC that is vulnerable to a buffer overflow. The buffer overflow can be verified by issuing an according "Read Registers" command that results in a service crash (or SIGSEGV under gdb). As the paper further mentions, the lesser-known "Read Write Register" function (code 0x17) has to be used to gain actual Remote Code Execution.
Unfortuantely, the Modbus service on the PLC returns an "Illegal Function" error, when using that function code, as can be seen from the pymodbus.console output:
So, the code path for responding with an "Illegal Function" error should not be taken.
EDIT:
Taking another look at the PLC code base, I realized that the openplc gets linked against libmodbus, but actually uses its own Modbus implementation. The modbus.cppdoes not contain a definition for function code 0x17 and also does not have the code implemented for handling it. Thus the message handling function defaults to the "Illegal Function" response.
According to the Usenix paper, a libmodbus version had been used for OpenPLC that is vulnerable to a buffer overflow. The buffer overflow can be verified by issuing an according "Read Registers" command that results in a service crash (or
SIGSEGV
undergdb
). As the paper further mentions, the lesser-known "Read Write Register" function (code 0x17) has to be used to gain actual Remote Code Execution.Unfortuantely, the Modbus service on the PLC returns an "Illegal Function" error, when using that function code, as can be seen from the pymodbus.console output:
and also under Wireshark:
Looking at the libmodbus code inside this repo (and also on the pre-built PLC VM), one can see that this function code is defined: https://github.com/Fortiphyd/GRFICSv2/blob/master/plc_vm/OpenPLC_v2-master/libmodbus-3.0.4/src/modbus-private.h#L65
and that it should also be properly handled: https://github.com/Fortiphyd/GRFICSv2/blob/master/plc_vm/OpenPLC_v2-master/libmodbus-3.0.4/src/modbus.c#L870
So, the code path for responding with an "Illegal Function" error should not be taken.
EDIT: Taking another look at the PLC code base, I realized that the openplc gets linked against libmodbus, but actually uses its own Modbus implementation. The
modbus.cpp
does not contain a definition for function code 0x17 and also does not have the code implemented for handling it. Thus the message handling function defaults to the "Illegal Function" response.The overflow still triggers for read requests, due to the
modbus.cpp
having been modified, accordingly: https://github.com/Fortiphyd/GRFICSv2/blob/master/plc_vm/OpenPLC_v2-master/core/modbus.cpp#L292So, apparently, it would be required to also re-implement the "Read and Write Registers" function inside the
modbus.cpp
to gain code executioin.