Team82 Logo Claroty

Team82 Research

Exploiting Honeywell ControlEdge VirtualUOC

Uri Katz
/ May 20th, 2024

Executive Summary

Team82 has researched Honeywell ControlEdge Virtual Unit Operations Center (UOC) and found multiple vulnerabilities in the EpicMo protocol implementation within ControlEdge Virtual UOC instances. These vulnerabilities are exploitable and can lead to unauthenticated remote code execution.

The vulnerabilities we found reside in the EpicMo protocol (TCP port 55565)—a proprietary protocol designed by Honeywell that is used to communicate between Honeywell Experion servers and controllers. This protocol contained an undocumented and dangerous function that enabled us to write files on Virtual UOC controllers without sanitation, which exposed the devices to the execution of unauthorized code. An attacker already on an OT network would use a malicious network packet to exploit this vulnerability and compromise the virtual controller. This attack could be carried out remotely in order to modify files, resulting in full control of the controller and the execution of malicious code. 

Honeywell has updated Virtual UOC and users are urged to move to current versions. The Cybersecurity Infrastructure & Security Agency (CISA) has published an advisory for CVE-2023-5389 (CVSS v3 score: 9.1) and CVE-2023-5390 (5.3). Honeywell has also published an advisory.

What is Honeywell Virtual UOC?

Honeywell is a significant player in the industrial control system (ICS) market, offering an extensive array of controllers for industrial automation. One product is the Honeywell Control Edge Unit Operations Controller (UOC), a modular physical controller that extends the Experion control DCS environment. The ControlEdge UOC includes built-in fault tolerant Ethernet, ModbusTCP, and EtherNet/IP. UOC is also offered as a virtual controller. The Virtual UOC decreases an enterprise’s hardware footprint because it does not require a physical controller. This is essentially a Linux-based virtual machine that can be installed in a virtual environment.

The VirtualUOC location on Honeywell DCS systems.

Multiple Virtual UOC Communication Protocols

Honeywell controllers use multiple protocols for communications. A service called NameServer is responsible for routing and opening communications for all protocols. In order to start communication over a specific protocol, we first need to send a UDP message to the NameServer service (over UDP port 12321) specifying which protocol that will be used.

A UDP packet initiating EpicMo protocol communications.

After sending the UDP initialization message, one can start communicating over TCP. Each session starts with a TCP initialization message specifying the protocol again.

EpicMo Protocol

The EpicMo protocol (TCP port 55565) is used for debugging and diagnostics of Honeywell controllers. It includes function codes such as ReadMemory, WriteMemory, Reboot and ReadCrashBlock, which allow for error detection and debugging.

Protocol Structure

Sequence Number

Packet Length

Number of Packets

Number of Packets Sent

Function Code

2 bytes

2 bytes

2 bytes

2 bytes

1 byte

  • Sequence number: A sequential number for the packet.

  • Packet Length: Length of the packet.

  • Number Packets Received: Counter for the number of packets received.

  • Number Packet Sent: Counter for the number of packets sent.

  • Function Code: The function code the client desires to invoke.

An EpicMo protocol struct, written in Python.

While researching the EpicMo protocol we discovered that the Virtual UOC implements different EpicMo function codes than the C300 controller.

EpicMo Command Handlers

Two commands that caught our attention are LoadFileFromModule and LoadFileToModule. After researching these functions, we came to the conclusion that they enable arbitrary file-write and file-read to the virtual controller.


From File Write to preauth RCE via LoadFileToModule

(Command 0x51)

LoadFileToModule allows users to write files to the controller. One of the parameters this function receives is a Destination_Path, which is the path the given file will be written to. 

We discovered that this functionality allows users to supply an arbitrary path and data, and no validation or limitation exists on the given path. This means users can write files to all writeable locations on the controller, which is a security concern. By leveraging this functionality, attackers could achieve remote code execution on the controller, by writing executable files, for example.

In order to upload a file using the LoadFileToModule function code, we need to send at least three packets (start write, write data, finish write). Each packet starts with the regular EpicMo header.

LoadFileToModule start write command

File Type

Upload Packet Number


File Data Checksum

File Data Length

Destination Path

1 Byte

4 Bytes

2 Bytes

4 Bytes

4 Bytes


  • File Type: Firmware file or generic file. 0x05 is used for generic file

  • Upload Packet Number: Packet number in the upload sequence. The first packet is 0.

  • File Data Checksum: Checksum for the entire file data

  • File Data Length: Length of the entire data

  • Destination Path: The name of the file to save on the controller

LoadFileToModule data command 

The maximum length of the file data in a data command is 0x7F. If the data length is more than 0x7F it will be split into multiple packets where Upload Packet Number is updated accordingly.

File Type

Upload Packet Number

Data Length (0x7f max)


1 Byte

4 Bytes

2 Bytes


LoadFileToModule final command 

Final command is used to signal that the upload is finished.

File Type

Upload Packet Number

Data Length: Must Be 0

1 Byte

4 Bytes

2 Bytes

When the Upload Packet Number is not 0 and the Data length is 0, it is considered as the final upload packet.

In order to send a valid LoadFileToModule start command, we need to include a checksum of the file. In order to calculate a file’s checksum, we implemented the following function that returns the correct checksum for a given file, below.

In order to demonstrate how an attacker might leverage this vulnerability to achieve remote code execution, we searched for writeable locations on the virtual controller. However, a few limitations existed:

  1. Files uploaded using LoadFileToModule do not have the UNIX execute attribute

  2. All files that are mounted to /usr/honeywell are mounted as read-only and this directory is not writeable.

We eventually decided to overwrite a system .so file; .so files do not need to have the execute attribute, and we can create a shared object that will execute our code when it is loaded. We chose /lib/ as the shared object we overwrite since it is loaded at startup, but overwriting it does not affect the runtime in any major way and enables stable pre-auth RCE. 

Our code execution flow looks like this:

  1. Compile with our payload set to run at startup

  2. Use the LoadFilefromModule to write file to /lib/ on the controller

  3. Call the Reboot command in order to ensure a reload of

Finally, we were able to demonstrate a preauth RCE on a remote virtual UOC using CVE-2023-5389.


Proprietary protocols such as Honeywell’s EpicMo used for communication between Honeywell Experion servers and controllers often contain vulnerabilities that can put industrial processes at risk for manipulation or disruption. 

We found mechanisms with a function that enables possible remote code execution by writing files on Virtual UOC controllers without sanitization.

We found an undocumented and dangerous function that enabled us to write files on Virtual UOC controllers without sanitation. An attacker on the OT network could send malicious packets to the controller and write files without authenticating to the controller. 

Team82 privately disclosed these vulnerabilities, CVE-2023-5389 and CVE-2023-5390, to Honeywell, which has addressed them in an update.

Stay in the know

Get the Team82 Newsletter

Related Vulnerability Disclosures

LinkedIn Twitter YouTube Facebook