Introduction
Past May, while working at the CICLAB laboratory of the University of Leon (Spain), I came across with a vulnerability on the PLC (Programmable Logic Controller) I was working with. For a research paper, which is currently under review, I had to deal with the configuration protocols used by the different PLCs I had in my testbed. The testbed consists of a number of PLCs from different vendors, among them Schneider-Electric.
Schneider-Electric PLCs configuration protocol is an evolution of the well-known modbus protocol, but using only the 0x5A Function Code. This protocol (or subprotocol), named internally "UMAS", has not been publicly specified, and therefore it had to be reverse-engineered.
After decoding this "UMAS" protocol (which I will explain in a future entry of this blog), I tried to send some invalid traffic to test the robustness of the PLCs.
From the Schneider Family of PLCs I had two different models in my testbed, a M580 PLC and a M340 PLC. After several tries, I was not able to compromise the Schneider-Electric M580 PLC, however when tried to send specially crafted UMAS packets to the M340 PLC, I found it stopped replying to ping commands.
This behaviour was tested using three different firmware versions. The M340 PLC seemed vulnerable, even when working with the latest firmware version (V2.70 at the moment).
Schneider Electric was contacted. I sent them an explanation of the problem together with a "pcap" file that showed the problem. Very quickly they let me know they had done their own tests and that it was a real vulnerability. It was finally published as the security notification SEVD-2017-048-02. The ICS-CERT has not released the public advisory yet, but they're on the way.
I must say they have been very very professional.
Explanation of the vulnerability
As mentioned earlier, this vulnerabilities is based on the modification of a series of legitimate "UMAS" packets sent in a specific order. "UMAS" is a configuration protocol that allows the software clients (Unity Pro and Vijeo Citect among others) to connect, configure and monitor Schneider-Electric PLCs. More than 20 different subfunction codes have been determined. These function codes allow the client to perform different tasks (Check keepalive, start/stop, upload/download strategies, read/write memory, etc).
One of these "subfunction codes" allow the client to "read" from the PLCs memory asking for a number of bytes to be read, starting from an offset of a "Memory block" (specified by a 16 bit number).
These memory blocks store different types of information (unlocated variables, system words, function blocks, etc). Every memory block has a different size (or top offset), depending on the data stored (sometimes it's 0x5B00, sometimes 0x3F00, sometimes 0xF500...). When trying to read memory over the "top offset" of a memory block, the PLC got locked. This happened with different "memory blocks", always that you sent a UMAS_read_memory request reading over the top offset of the block.
That's what, in other words Schneider-Electric explain with the following sentence:
The software does not properly restrict the size or amount of resources that are requested or influenced by an actor, which can be used to consume more resources than intended.
After sending this series of packets, the PLC got freezed and only could be recovered by approaching physically to the device and resetting it manually.
The following image show a wireshark capture at the moment where this packet (#133) is sent. Before the packet is sent the PLC (IP 10.1.0.102) replies to the different requests done by the client (10.8.0.101). It can be seen as well that a few seconds later some ping commands are sent and the PLC do not reply them:
The vulnerable UMAS packet is shown shadowed, but it can be seen that it requests the offset 0xF503 (while the top offset is 0xF500.
The following image shows the python script written for testing purposes. In the screen of the right the script is launched, in the screen of the right a ping command is running and suddenly it stops showing ping connection (when the exploit packet is finally sent).
Current Situation
Schneider-Electric bundled a number of fixes in a new firmware version (V2.90) which was released on December 21st. However, 2 months after the public release, very few from the currently available Schneider-Electric M340 PLCs are currently protected.
The Schneider-Electric public disclosure of this vulnerability was published a few days ago.
A simple search in shodan for on of the affected devices (looking for "BMX P34 2020") show that more than 700 devices (of this type) are currently accessible to internet and have not been upgraded to the firmware version V2.8 or V2.9.
This means that more than 700 potentially critical devices could be sent offline remotely in a question of seconds. I have an exploit script for metasploit ready, but clearly it will not be publicly released for a few months (or years!).
Acknowledges
The discovery of this vulnerability has been possible by the funding of INCIBE and thanks to the support of the colleagues of the CICLAB Laboratory at the University of León (Jacinto, Juanma and Borja) and the rest of the guys of the IAF.
No hay comentarios:
Publicar un comentario