Open Automation Software recently released patches for multiple vulnerabilities in their OAS Engine

Cisco Talos publicly disclosed these issues after working with Open Automation Software to ensure that patches were available for users. Now that a fix has been released with Version 19, we want to take the time to dive into a few of these vulnerabilities and show how a handful of bugs that could be viewed as low-impact could be exploited as a series to carry out various malicious actions, even going as far to gaining access to the underlying system.

Background

The OAS Platform facilitates the simplified transfer of data between various proprietary devices and applications. It can connect products from multiple vendors, connect a product to a custom application, and more. Configuration of the platform is possible through TCP/58727 by default.

Vulnerabilities

During this research, we discovered eight vulnerabilities, five of which are covered here. Full technical details can be found in the respective vulnerability reports: 

TALOS-2023-1769

TALOS-2023-1770

TALOS-2023-1771

TALOS-2023-1772

TALOS-2023-1773

TALOS-2023-1774

TALOS-2023-1775

TALOS-2023-1776

Bypass authentication via default configuration

TALOS-2023-1769 (CVE-2023-31242)

By default, when the OAS Engine is installed, no admin application user is set. Without an admin application user, no authentication is required to access certain functionality that would otherwise require valid credentials, including creating new users. Additionally, if an admin user is created, but the configuration is not saved before the OAS Engine restarts, those changes will be lost and the system will revert to disregarding the authentication structure.

Bypass authentication via stolen U_EP

TALOS-2023-1770 (CVE-2023-34998)

When a privileged request is sent by a legitimate administrator to the OAS Engine, the traffic is sent unencrypted across the wire. As such, it is possible for a bad actor capable of sniffing traffic between the client and OAS Engine to capture a valid U_EP authentication structure. The attacker can then use the structure to craft their successful privileged request. Any captured U_EP remains valid until the associated user account has been deleted.

File overwrite

TALOS-2023-1771 (CVE-2023-32615)

The OAS configuration tool provides a feature to save the running configuration to disk on the OAS engine server. When this information gets saved, the user specifies the path and filename, restricted only by the permissions of the underlying OAS user system account. If the chosen file already exists, the contents of that file will be replaced with the configuration data.

Add user unsanitized input

TALOS-2023-1772 (CVE-2023-34317)

Access to the various features of the OAS Engine and associated data is controlled through the use of OAS engine application users. 

Application administrator users can add additional users to the application with varying levels of permissions. These users exist within the OAS Engine exclusively, not on the underlying system. When adding a user, no filtering is performed on the value entered for the username, allowing a wide variety of characters not appropriate for a username to be entered and subsequently stored in the running configuration.

List directory

TALOS-2023-1774 (CVE-2023-32271)

Through the OAS Configuration tool, the functionality to load a saved configuration from disk or save a running configuration to disk is exposed to authenticated application users. 

Accompanying the configuration management tools is a remote file browser that allows users to see what files exist on the remote system.

Attack walkthrough

By combining these vulnerabilities, it is possible to gain access to the underlying system as the user running the OAS Engine. 

In this scenario, an adversary could: 

  1. Gain access to a valid authentication structure.
  2. Search the filesystem for evidence of an SSH server.
  3. Store an SSH key in the running OAS configuration.
  4. Write the running configuration to disk.

Interacting with the OAS Engine

Before an adversary can make any of the requests needed to exploit the system, they’d need to understand the protocol used by the OAS Configuration utility. These requests consist of two related Protobuf structures — Client_Send and OASPacket — concatenated together and sent to the OAS Engine via TCP/58727 (by default). Responses to these requests will be delivered in a similar format, replacing the Client_Send Protobuf with a Server_Send.

The Server_Send Protobuf takes the following form, where the Handshake and Offset fields must be retained if a subsequent Client_Send is to be sent. 

message Server_Send {
  int32 Version = 1;
  int32 OASVersion = 2;
  int32 Handshake = 3;
  int32 Offset = 4;
  int32 Length = 5;
}

The Client_Send Protobuf takes the following form, where Version is 0x01, and Length is the size in bytes of the OASPacket Protobuf:

message Client_Send {
  int32 Version = 1;
  int32 ClientHandshake = 2;
  int32 Handshake = 3;
  int32 Length = 4;
}

The ClientHandshake and Handshake fields are used in a client/server handshake that is likely in place to prevent replay attacks. ClientHandshake is a randomly generated value less than or equal to 0x3FFFEC75 that will be used in a subsequent request's handshake process. Handshake is a value calculated by taking the Handshake field from the prior Server_Send response, adding it to the Offset field from that same response, subtracting by both 0x12CB and the value of the ClientHandshake field from the prior Client_Send request, and finally adding 0x888. This can be better visualized with the following formula:

handshake = server_send_handshake + server_send_offset - 0x12CB - previous_client_send_handshake + 0x888

The OASPacket Protobuf takes the following form, where LDCMode, LDCHost, and SendingGUID are not always necessary, Version is 0x01, CommandNumber defines the type of request being sent, and DataAsBytes is a set of serialized Protobufs describing the request data. 

message OASPacket {
  int32 Version = 1;
  int32 LDCMode = 2;
  int32 CommandNumber = 3;
  string LDCHost = 4;
  string SendingGUID = 5;
  bytes DataAsBytes = 6;
}

Many of the requests contain a field of the custom type U_EP. This field contains a serialized copy of credentials used to authenticate privileged requests. The U_EP Protobuf takes the following form, where Version is 0x01, and Seed is a random value used to encrypt the credentials:

message U_EP {
  int32 Version = 1;
  int32 Seed = 2;
  bytes DataAsBytes = 3;
}

The DataAsBytes field contains a serialized and encrypted User_EncryptedPassword Protobuf, which takes the following form:

message User_EncryptedPassword {
  string Username = 1;
  string EncyprtedPassword = 2;
}

By combining the generic structures discussed here with the request-specific structures discussed later, an adversary could replicate the desired communications with the OAS Engine. 

Bypass authentication

Many of the requests necessary to successfully interact with the OAS Engine require authentication. At this time, two options exist to bypass this authentication requirement: abusing the default configuration or reusing a valid authentication structure. 

Option 1: Abusing Default Configuration

As the requests needed to gain access require authentication, it is necessary first to acquire a valid U_EP structure. 

The easiest way to obtain valid credentials is to use the vulnerability disclosed in TALOS-2023-1769. This vulnerability is only exploitable in cases where the OAS Engine is still running its default configuration. To determine if the target in question is vulnerable, an OASPacket with Version set to 0x01 and CommandNumber set to 0x13F can be used. When correctly sent, the server will return a response with the following format:

message Version_Runtime_License {
  int32 Version = 1;
  bool Runtime = 2;
  string LicenseString = 3;
  string MtcExpirationString = 4;
  bool NetCore = 5;
  bool WinOS = 6;
  bool LinuxOS = 7;
  string AssemblyVersion = 8;
  string BaseDirectory = 9;
  bool EnableActiveDirectory = 10;
  string ActiveDirectoryEntry = 11;
  string ActiveDirectoryFilter = 12;
}

If the server is vulnerable to TALOS-2023-1769, the MtcExpirationString field will contain the string "Create an Admin User." In this state, the server does not perform any verification of the U_EP structure, allowing privileged requests by unauthenticated users as long as any value is provided in the U_EP field.

If an admin user has already been created, the OAS Engine will not be vulnerable to TALOS-2023-1769 and will require a different approach. The vulnerability disclosed in TALOS-2023-1770 provides an alternative way to obtain a valid U_EP

Option 2: Pass the U_EP

This vulnerability occurs when legitimate configuration requests, including privileged ones, are sent to the OAS Engine. Most of these messages are sent in cleartext, as disclosed in TALOS-2023-1770. The exception is a field within the U_EP authentication structure, referred to within the OAS Platform as the User_EncryptedPassword. The User_EncryptedPassword is a block of data containing the authenticating username and associated encrypted password that is supplied as a block of AES-encrypted, serialized data to the DataAsBytes field in a U_EP authentication structure, as shown below.

message U_EP {
  int32 Version = 1;
  int32 Seed = 2;
  bytes DataAsBytes = 3;
}

message User_EncryptedPassword {
  string Username = 1;
  string EncyprtedPassword = 2;
}

While it is possible to decrypt the User_EncryptedPassword and get access to the raw username and encrypted password (TALOS-2023-1776), it is not necessary for authentication. 

When a legitimate U_EP is built, a value is randomly generated and stored in the Seed field of the structure. This seed is subsequently used to build the AES key used to encrypt the User_EncryptedPassword data. This process generally results in a different U_EP value for each new configuration session when conducted through the official tool, but this process does not cause prior sessions to be terminated. 

If an attacker obtains access to legitimate configuration traffic by sniffing network traffic, obtaining an old traffic capture, or any other method, they can extract the U_EP structure and successfully authenticate for as long as the associated user exists within the OAS Engine. 

Explore the Filesystem

With the ability to successfully send authenticated messages, we can leverage the vulnerability disclosed in TALOS-2023-1774 to explore the filesystem. 

From here a variety of approaches could be taken, but for this deep dive, we are looking for the existence of the sshd_config file in /etc/ssh/ and the .ssh directory in the OAS user's home directory, indicating that an SSH server is likely enabled on the system. 

We can do this by using an OASPacket with Version set to 0x01 and CommandNumber set to 0x0F. Additionally, the DataAsBytes field will need to be filled with a serialized Browse_File Protobuf containing a valid U_EP, the GetDirectories and GetFiles flags set, a DirectoryPath set to the absolute path of the desired location, and a FileExtension field containing an asterisk to indicate any file type.

message Browse_File {
  int32 Version = 1;
  U_EP UEP = 2;
  bool GetDrives = 3;
  bool GetDirectories = 4;
  bool GetFiles = 5;
  string DirectoryPath = 6;
  string FileExtension = 7;
}

When successfully sent, the OAS Engine will respond with the results in a Browse_File_Result Protobuf, containing all of the data organized by type. 

message Browse_File_Result {
  bool Success = 1;
  optional string ErrorString = 2;
  repeated string Drives = 3;
  repeated string Directories = 4;
  repeated string ShortDirectories = 5;
  repeated string Files = 6;
  repeated string ShortFileNames = 7;
}

Upload new SSH key

After verifying with some certainty that an SSH server is running, it is possible to leverage TALOS-2023-1771 and TALOS-2023-1772 to upload a new SSH key and subsequently gain access to the underlying system.

Since there is not any dedicated file upload functionality exposed by the OAS Engine, it is necessary to get more creative. By combining the improper input validation vulnerability disclosed in TALOS-2023-1772 with the external control of the filename vulnerability disclosed in TALOS-2023-1771, it is possible to create a makeshift file upload process. 

💡
It is important to note that while functional for this scenario, this technique will result in a file that cannot be fully controlled. As such, it is likely to create a file that could be considered corrupt by most applications.

When adding a new application user to the OAS Engine, the user details are taken and written to the running OAS Engine configuration. During this process, no verification is performed to ensure that the value entered contains exclusively characters that make sense for a username. Additionally, there is no limit on the length of the username. 

By supplying the entirety of an SSH public key that we control as the username of a new entry, it is possible to abuse this lack of verification to get our desired file data stored in the running OAS configuration

We can do this through the use of an OASPacket with Version set to 0x01 and CommandNumber set to 0x88. Additionally, the DataAsBytes field will need to be filled with a serialized String Protobuf containing a Version number, a valid U_EP, and a String value containing the public key data. 

message String {
  int32 Version = 1;
  U_EP UEP = 2;
  string String = 3;
}

With our key stored in the running configuration, we can then trigger it to get written to a file of our choice, in this case, the OAS user's authorized_keys, file, by saving the configuration to disk. While the file will contain a large amount of OAS configuration information that is meaningless to the SSH server, the public key supplied via a username will still be interpreted successfully as long as it is surrounded by newline characters.

We can do this by using an OASPacket with Version set to 0x01 and CommandNumber set to 0x74. The DataAsBytes field must again be filled with a serialized String Protobuf containing a Version number, a valid U_EP, and a String value, this time containing the absolute path to the file where the configuration should be written. 

message String {
  int32 Version = 1;
  U_EP UEP = 2;
  string String = 3;
}

If everything works correctly and the target has its SSH server running, it will be possible to log in as the underlying OS user running the OAS engine via SSH.

Mitigations

Before the release of this walkthrough and the associated vulnerabilities, Cisco Talos worked with Open Automation Software to ensure that patches were made publicly available in Version 19. All users are recommended to upgrade to the latest version. 

For Snort coverage, (SIDs 61991 - 61994, 62003, and 62004) that can detect the exploitation of these vulnerabilities, download the latest rule sets from Snort.org, and our latest Vulnerability Advisories are always posted on Talos Intelligence’s website.