CoDeSys has several components: a graphical Integrated Development Environment (IDE) for writing ladder logic on a PC and transferring the resultant logic to a PLC, a web server for PCs for retrieving and visualizing data from PLCs, and a ladder logic runtime engine for receiving the ladder logic from a PC and executing it.
We focused on the ladder logic runtime engine specifically as seen on the WAGO IPC 758-870 model PLC, although all makes and models of CoDeSys PLCs appear to be affected. The ladder logic runtime is provided by 3S-Software and can be run on many operating systems including Nucleus RTOS, embedded Linux, Windows CE, etc. The WAGO happens to run embedded Linux on an x86 CPU, and also allows Telnet and FTP access, making it a nice target for evaluation. The WAGO linux kernel includes a complete filesystem and many programs allowing for a good exercising of CoDeSys’ capabilities.
The CoDeSys runtime does a lot of things. Obviously its main purpose is to run ladder logic. Ladder logic is executed in the form of a wrapped binary, compiled for the operating system and CPU of the PLC. The ladder logic file contains a header followed by binary executable code. The CoDeSys ladder logic engine loads the file into memory, and then jumps into that memory and begins executing instructions contained in the file. This is important when we consider the privileges that CoDeSys often runs with, and its lack of authentication for file transfer.
The CoDeSys runtime has ancillary functions as well. It offers a TCP listener service, often running on TCP/1200 (although TCP/1201 and TCP/2455 are observed on other controller types). The TCP listener service allows for file transfer as well as a command-line interface.
Neither the command-line interface nor the file transfer functionality requires authentication. The CoDeSys runtime engine needs to access /dev devices on embedded Linux and writes to an output bus (K-Bus, which is connected over a PCI interface in the WAGO). As a consequence, manufacturers often run the ladder logic runtime as ‘root’ (on linux systems), ‘administrator’ (on embedded windows), or run it on an operating system which does not provide deprivileged users.
The result of all of this is that a user with the right know-how can connect to the command-line of CoDeSys and execute commands, as well as transfer files. Commands include the ability to stop and start the running ladder logic, wipe PLC memory, and list files and directories. Transferring files include the ability to send and receive. Sending and receiving files also suffers from directory traversal — we can read and write files outside of the CoDeSys directory on the controller using “../” notation. On most operating systems this includes the ability to overwrite critical configuration files such as /etc/passwd and /etc/shadow on linux, or the windows registry on Windows CE.
The ladder logic runtime file is transferred in conjunction with a 32-bit checksum. The 32-bit checksum is computed by adding the bytes of the runtime file together, and treating the result as a 32-bit integer. The ladder logic runtime transfer is mostly implemented in this release; a missing command is required to make the new ladder logic upload active on the PLC.
We have produced three tools for interacting with PLCs that run CoDeSys. The first tool is a command-shell utility. This allows an unauthenticated user the ability to perform privileged operations, sans password. It is the equivalent of running the “PLC – Browser” function from the CoDeSys desktop software, but does not assert vendor checks normally performed by the CoDeSys software — CoDeSys will normally fail to connect to a PLC and offer this option without properly licensed plugins.
The commands available vary by PLC, so type “?” to get a list of options.
The second tool is a file transfer tool which allows for reading and writing files on controllers with a filesystem. Again, this tool bypasses the only protections that CoDeSys provides — vendor-specific checks that ensure we’re communicating with the right kind of PLC.
These tools come in the form of Python scripts. The hastily-written code isn’t terribly legible (blame Reid) but works quite well on a wide variety of controllers. They can easily be ported to be Metasploit modules, and could be made to run the Meterpreter shell on supported operating systems.
The final tool is an Nmap NSE script that will detect if your PLC or controller is running a vulnerable version of the CoDeSys ladder logic runtime. It has both big endian and little endian probes, while the python scripts only support little endian implementations. So if the python scripts fail, try the nmap NSE script.
Download the tools: