Talos Vulnerability Report

TALOS-2024-1948

Open Automation Software OAS Platform OAS Engine File Data Source Configuration denial of service vulnerability

April 3, 2024
CVE Number

CVE-2024-24976

SUMMARY

A denial of service vulnerability exists in the OAS Engine File Data Source Configuration functionality of Open Automation Software OAS Platform V19.00.0057. A specially crafted series of network requests can cause the running program to stop. An attacker can send a sequence of requests to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

Open Automation Software OAS Platform V19.00.0057

PRODUCT URLS

OAS Platform - https://openautomationsoftware.com/knowledge-base/getting-started-with-oas/

CVSSv3 SCORE

4.9 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H

CWE

CWE-130 - Improper Handling of Length Parameter Inconsistency

DETAILS

The OAS Platform, capable of running on a variety of systems including Windows, Linux, and Docker, was built to facilitate simplified communication between various proprietary devices and applications that might otherwise be incompatible. This is done through use of the “Universal Data Connector”. In the “Connectivity Layer” OAS acts as an “IoT Gateway and protocol bus,” allowing for native communication with devices, databases, and cloud services. Connectors implemented in the “Connectivity Layer” can then communicate with each other via the OAS Live Data Cloud, representing the “Aggregation Layer”. This information can then be stored, analyzed, and visualized through the data historian, alarm logging/notification, and visualization tools that make up the “Application Layer”. OAS additionally exposes a few sets of developer tools, allowing for programmatic access to the platform.

The OAS Engine provides authenticated users access to a variety of user-modifiable configuration fields. Included within these options is the File Data Source configuration, allowing users to specify a system path and filename to use with specially configured Tag entities.

The File Data Source configuration can be set through use of a CSV_Import protobuf as part of a greater authenticated request. The format of this structure resembles the following, where the Strings field contains the configuration options in CSV format with the File Data Source Path containing the target filepath and File Data Source File Name containing the target name.

message CSV_Import {
  int32 Version = 1;
  U_EP UEP = 2;
  repeated string Strings = 3;
}

When a File Data Source Path is set, it is first checked to ensure that the provided value is not a blank string in the case of Linux, or the root C directory in Windows. This can be seen in the code snippet below where the global::i.aej variable contains a slightly modified value provided to the File Data Source Path field.

if (!(Operators.CompareString(global::i.aej, "", false) == 0 | Operators.CompareString(global::i.aej, "C:\\", false) == 0))

If that passes, the value is next checked to ensure that it begins with one (and only one) backslash, as seen in the code snippet below.

if (Operators.CompareString(global::i.aej.Substring(0, 1), "\\", false) == 0 & Operators.CompareString(global::i.aej.Substring(0, 2), "\\\\", false) != 0)

If a blank string is provided as the value of File Data Source Path it is modified by the Engine to contain a single backslash. This modification causes the first check to succeed and allows execution to continue to the second check. At this time, the second call to Substring will raise an ArgumentOutOfRangeException exception due to the Length field of the Substring call being greater (0x02) than the length of the string itself (0x01). Since this exception is not caught it causes the OAS Engine process to die.

Crash Information

System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
   at System.String.Substring(Int32 startIndex, Int32 length)
   at i.t(Object A_0)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
TIMELINE

2024-02-29 - Vendor Disclosure
2024-03-04 - Vendor Patch Release
2024-04-03 - Public Release

Credit

Discovered by Jared Rittle of Cisco Talos.