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:
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:
- Gain access to a valid authentication structure.
- Search the filesystem for evidence of an SSH server.
- Store an SSH key in the running OAS configuration.
- 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.
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.