Backdooring CODESYS Applications via Vulnerability Chaining

Backdooring CODESYS Applications via Vulnerability Chaining

Figure 1. CODESYS Ecosystem

CODESYS is a manufacturer-independent development environment for programming industrial controllers, widely adopted across the automation industry. Hundreds of device manufacturers integrate the CODESYS runtime into their hardware, making it one of the most common Soft PLC platforms in the world. A Soft PLC is a software-based programmable logic controller that runs on general-purpose hardware instead of dedicated industrial modules, offering flexibility and lower costs while providing the same IEC 61131-3 programming environment that engineers expect.

The CODESYS ecosystem is comprised of two main components: the CODESYS Development System, a Windows-based IDE where engineers write, compile, and deploy control applications, and the CODESYS Control runtime, which executes those applications on the target device, as shown in Figure 1. The runtime handles real-time I/O processing, communication with field devices, and network services such as OPC UA and the proprietary CODESYS gateway protocol.

Security researchers at Nozomi Networks Labs identified three vulnerabilities affecting the CODESYS Control runtime and promptly notified CODESYS Group, providing technical details so the vendor could reproduce and remediate the issues. All reported vulnerabilities are fixed in CODESYS Control Runtime version 4.21.0.0 and CODESYS Runtime Toolkit version 3.5.22.0.

Taken together, these issues can let an authenticated attacker with valid Service-level credentials replace a legitimate control application with a backdoored one and eventually escalate to full control of the device.

We thank the CODESYS security team for the close collaboration throughout the disclosure process. They addressed all reported vulnerabilities in a timely manner and published three advisories to inform their user base. Operators should follow the vendor's guidance and apply the recommended updates immediately.

Vendor advisories:

Research Scope

Figure 2. CODESYS Control for Raspberry Pi

This research targeted the CODESYS Control runtime, specifically the CODESYS Control for Raspberry Pi SL variant. This version runs on low-cost ARM hardware and provides the full CODESYS Control feature set, making it an accessible and representative target for security analysis.

CODESYS Control for Raspberry Pi SL is a commercial product, but CODESYS offers an evaluation mode that allows unrestricted use for two hours per session. After that window, the runtime stops and must be restarted. Aside from this time limit, the evaluation mode imposes no functional restrictions, meaning every code path and network service is available for testing.

Although our testing was conducted on the Raspberry Pi variant, all the vulnerabilities we discovered affect a much broader set of CODESYS Control runtimes. Refer to the vendor advisories linked above for the complete list of affected products.

Attack Scenario

CODESYS-powered PLCs are deployed in a wide range of industrial environments: from manufacturing lines and energy systems to water treatment plants and building automation. In each case, the PLC executes a control application that governs physical processes, adjusting valve positions, regulating motor speeds, or sequencing robotic operations. A compromised control application can therefore cause real-world damage, from halted production to unsafe operating conditions.

This section describes how the vulnerabilities discovered by Nozomi Networks Labs could allow an authenticated attacker with limited privileges to take full control of a device running the CODESYS Control runtime.

The attack requires the attacker to hold valid Service-level credentials for the CODESYS runtime. Standard operational controls should normally prevent unauthorized access, but an attacker can obtain such credentials in several ways: by exploiting weak or default passwords, compromising an engineering workstation where credentials are stored, or, if they already have local access to the Soft PLC, leveraging CVE-2025-41658 to read the file containing CODESYS password hashes.

In other words, the core attack path is an authenticated abuse of overly broad Service privileges. Local operating-system access is not required to tamper with and restore a project once the attacker has those credentials, but it can be one way to obtain them.

Figure 3. CODESYS Attack Scenario

Figure 3 illustrates the attack flow. Once authenticated as a Service user, the attacker proceeds through the following steps:

  1. Download the boot application. The attacker uses the CODESYS Development System to download the boot application through the backup functionality.
  2. Access cryptographic material. The attacker exploits CVE-2025-41659 to access cryptographic material stored on the Soft PLC, including the ability to retrieve it and, where relevant, upload trusted certificate-authority material.
  3. Bypass optional cryptographic protections. CODESYS supports optional protections such as code encryption and code signing for applications. With access to the relevant cryptographic material, the attacker can decrypt and re-encrypt the boot application and, where signing is enforced, re-sign modified code using attacker-controlled trusted material.
  4. Tamper with the boot application. The attacker modifies the compiled application binary to inject attacker-controlled machine code. If encryption and/or signing protections are enabled, these can be bypassed using the previously obtained cryptographic material.
  5. Restore the tampered boot application. The attacker exploits CVE-2025-41660 to restore the tampered boot application to the device using the backup functionality, overwriting the legitimate application.
  6. Wait for a restart. The Service user cannot restart the application directly. The attacker must wait for an operator to restart the application or for the system to reboot. Once the application runs, the injected code executes as root, the same privilege level as the CODESYS Control runtime.
  7. Escalate to Administrator. With root access on the underlying operating system, the attacker can modify the CODESYS runtime's user database and grant themselves Administrator privileges, achieving full control of the device.

This attack chain demonstrates that Service-level access is sufficient to escalate privileges to full administrative control of the device and the host operating system. The sections that follow explain the relevant runtime internals, project format, and trust boundaries that make the chain possible.

Vulnerability Listing and Affected Versions

The following table lists all the vulnerabilities Nozomi Networks Labs found in the CODESYS Control runtime during this research:

CVE ID CWE CVSS v3.1 Base Score CVSS v3.1 Vector
CVE-2025-41658 Incorrect Default Permissions 5.5 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
CVE-2025-41659 Incorrect Permission Assignment for Critical Resource 8.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L
CVE-2025-41660 Incorrect Resource Transfer Between Spheres 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Potential Impact of the Vulnerabilities

The vulnerabilities we discovered in CODESYS Control runtimes align with several techniques in the MITRE ATT&CK for ICS framework. Three particularly relevant examples are summarized below.

T0839: Module Firmware

By combining CVE-2025-41659 and CVE-2025-41660, an adversary with low-privilege access can replace the legitimate control application with a backdoored version. Access to cryptographic material can also undermine optional protections such as encryption or signing, allowing the modified application to appear legitimate to the deployment workflow.

T0831: Manipulation of Control

Once arbitrary code has been injected into the control application, the attacker can manipulate the physical process governed by the PLC. This includes changing setpoints, overriding safety interlocks, altering actuator behavior, or falsifying sensor readings. On equipment such as conveyors, pumps, robotic arms, or HVAC systems, these actions can produce unsafe or damaging behavior.

T0882: Theft of Operational Information

CVE-2025-41659 allows a low-privilege user to access cryptographic material on the device, enabling extraction of compiled control logic, configuration data, and embedded credentials or operational parameters. More broadly, access to that material can also weaken optional trust mechanisms used to protect deployed code. Additionally, CVE-2025-41658 exposes the file containing CODESYS password hashes to any local user on the Soft PLC, enabling offline credential extraction. This information can reveal the layout of the control process and support further compromise.

Understanding the Attack Chain

The next sections explain how an attacker can abuse Service-level access to move from backup and project handling features to full device compromise. To do that, we first examine how the CODESYS runtime protects its code, how deployed applications are stored and restored, and why those mechanisms still allow a Service user to tamper with a project in practice.

Because the affected issues have now been remediated, we focus on the security implications and the reverse-engineering observations needed to understand the attack chain, while intentionally avoiding some low-level vulnerability details that would make reproduction easier for attackers.

The CODESYS Control executable includes protections against reverse engineering and debugging. Analyzing the application therefore requires addressing these mechanisms, but we omit their detailed discussion to avoid disclosing proprietary implementation details.

Project Format: What Happens When a Project Is Uploaded

With the analysis environment prepared, the next step was to examine how the CODESYS Development System creates a project and uploads it to the device.

The CODESYS Development System allows programming the device using IEC 61131-3 languages such as Ladder Diagram. Uploading a simple program to the device shows how that deployment process works in practice.

In this case, the Ladder Diagram application is compiled into a file named ApplicationName.app, which is transferred to the directory /var/opt/codesys/PlcLogic/ together with a checksum file ApplicationName.crc. The latter contains a CRC of the main application.

For an application named Application, the resulting files on the device are:

root@codesysrasp:/var/opt/codesys/PlcLogic/Application # ls –lah
total 208K

drwxr-xr-x 2 root root 4.0K Mar 16 18:22 .
drwxr-xr-x 8 root root 4.0K Mar 16 18:22 ..
-rw-r--r-- 1 root root 195K Mar 16 18:22 Application.app
-rw-r--r-- 1 root root 20   Mar 16 18:22 Application.crc

We do not cover the .app file format in detail here; it is sufficient to note that it contains executable machine code. The CODESYS Development System compiles IEC 61131-3 code directly to machine code, which is then loaded and executed at runtime by the codesyscontrol process analyzed previously. No new process is spawned; codesyscontrol loads the code and executes it in its own process.

This observation has an important security implication: deploying IEC 61131-3 code on a machine running the codesyscontrol runtime means executing code as root on the device.

This is expected for administrators. The CODESYS runtime even allows raw C modules, callable from IEC 61131-3 code, to execute on the device. The more relevant question is whether non-administrative users can abuse the same execution model.

Privilege Levels

Figure 4. CODESYS Filesystem Privileges

The CODESYS runtime supports four (default) privilege levels:

  • Administrator
  • Developer
  • Service
  • Watch

Each level has different access rights for various objects in the system. For each object, a level can have (when applicable):

  • Add/Remove
  • Modify
  • View
  • Execute

Administrators can customize every access right, but there are default values.

Figure 5 shows the default rights for file-system objects. These are the root file-system privileges for the /var/opt/codesys folder, which every subfolder and file inherits by default, although each can be customized separately.

A key question follows: what prevents a Service user from downloading, modifying, and re-uploading an application?

Service users have write access to application folders because they can create and restore backups. This write access is the key enabler for the attack, so the next step is to examine how the backup mechanism works and how it can be abused.

Backups

Figure 5. CODESYS Control Backup Functionality

Applications can be backed up from the CODESYS Development System, as shown in Figure 6. The resulting backup is a file with a .tbf extension. This file is simply a zip archive containing a metadata file along with the Application.app and Application.crc files:

user@/home/user $ file mybackup.tbf
mybackup.tbf: Zip archive data, made by v2.0, extract using at least v2.0, last modified Mar 18 2026 11:45:38, uncompressed size 193, method=deflate

user@/home/user $ unzip mybackup.tbf
Archive: mybackup.tbf
inflating: meta.info
warning: mybackup.tbf appears to use backslashes as path separators
inflating: $PlcLogic$/Application/Application.app
inflating: $PlcLogic$/Application/Application.crc

user@/home/user $ tree .
.
\-- $PlcLogic$
| \-- Application
| \-- Application.app
| \-- Application.crc
\-- meta.info
\-- mybackup.tbf

3 directories, 4 files

Since the backup is simply a zip archive, the attack path should be clear. Note that the .crc file contains a simple CRC32 checksum with no cryptographic signature, making it trivial to recompute after modification.

If optional cryptographic protections such as encryption or signing are in use, CVE-2025-41659 can still provide the attacker with access to the material needed to work around those protections.

Root Code Execution: Privilege Escalation from Service to Admin

At a high level, a Service user can abuse the backup and restore workflow as follows:

  1. Download a backup from the device.
  2. Unzip it and inspect the application binary.
  3. Inject a shellcode that spawns a reverse root shell.
  4. Recompute the .crc file to match the modified application.
  5. Restore the tampered backup on the device.

For our proof of concept, we placed the shellcode at the entry point of the application, overwriting the first instructions. A real attacker could choose a less conspicuous injection point, for example, hooking a rarely executed branch, so that the main functionality of the application remains intact and the tampering is harder to detect.

The one thing the attacker cannot do is restart the application, which is required for the backdoored code to run. The attacker must therefore wait for someone to restart the application (or reboot the system) before the backdoor triggers.

After completing these steps and waiting for a restart, the shellcode executes and the attacker obtains a root reverse shell:

user@/home/user $ nc -lvp 4369
listening on [any] 4369 ...
192.168.42.100: inverse host lookup failed: Unknown host
connect to [192.168.42.2] from (UNKNOWN) [192.168.42.100] 57558
whoami
root
pwd
/var/opt/codesys
ls
OPCUAServer
PlcLogic
SysFileMap.cfg
bacstac.ini
cert
cmact_licenses
codesyscontrol.log

At that point, the privilege escalation is complete: the attacker can tamper with the CODESYS runtime's local state and grant themselves Administrator privileges.

It is worth noting that optional cryptographic protections do not necessarily prevent this attack. As described in the Attack Scenario, CVE-2025-41659 can give the attacker access to the material needed to decrypt and re-encrypt the application and, where signing is enforced, to introduce trusted signing material and re-sign modified code before restoring it.

All the vulnerabilities exploited in this attack chain have been patched by CODESYS. As part of those fixes, CODESYS made code signing mandatory by default before PLC code can be deployed or executed. As a result, Service users, who still need the ability to create and restore backups, can no longer tamper with application code undetected.

Remediations

CODESYS has addressed these vulnerabilities through security patches for the CODESYS Development System and the CODESYS Control runtimes. Asset owners and operators are strongly urged to:

  • Update affected Soft PLCs with the latest version of the CODESYS Control runtime.
  • Implement network segmentation to limit system exposure.
  • Monitor network traffic for the presence of vulnerable assets.

To help organizations promptly identify whether devices running the vulnerable runtime are present in their environment, asset owners can rely on the advanced capabilities of Nozomi Networks OT/IoT Security Platform. The platform provides deep visibility into network traffic and host activities, enabling effective vulnerability and threat detection across OT networks.

Figure 6. Detection of vulnerable device in Nozomi Vantage

This proactive monitoring empowers security teams to respond to vulnerabilities and attacks swiftly and effectively, minimizing the impact of attacks targeting critical networks. To learn more about Nozomi Networks OT/IoT Security Platform and see it in action, request a demo today.