OPC-UA Design Practice from an Attacker’s Perspective
In our previous article, we discussed how the flexibility of OPC-UA has made it a popular choice for many industrial control system vendors, while simultaneously attracting attention from potential attackers as a vast blue ocean full of untapped resources. But how can we study this with a practical lens? Let’s delve into the research entitled “A Broken Chain: Discovering OPC-UA Attack Surface and Exploiting the Supply-Chain” presented at Black Hat USA, where researcher Eran Jacob gave us a look at vulnerability mining in products using the OPC-UA protocol from an attacker’s perspective.
Eran Jacob, adopting the perspective of an attacker, initially investigated the various versions of OPC-UA function libraries utilized in market products. The original suites of implementation were open-sourced, maintained, and championed by the OPC Foundation, made available as ANSI C, .NET, and JAVA versions. In response to market demand, three commercial OPC-UA suites were developed. This research reveals that these three suites, produced by Softing, the OPC Foundation, and Unified Automation, collectively hold 80% of the market share. Intrigued, Eran Jacob concentrated his research on finding common vulnerabilities among these three suites.
The dominant use of these three implementations in market products can be divided into two types: C/C++ and .NET. This research reveals that both the commercial C++ and .NET function libraries from Softing or Unified Automation have a high degree of similarity with the versions open-sourced by the OPC Foundation. This discovery was confirmed with reverse engineering. Therefore, Jacob attempted to dig into the common architectural issues in the original OPC Foundation suites, hoping to simultaneously impact Softing, Unified Automation, or even more third-party commercial OPC-UA suites.
OPC-UA’s Flexible Features: An Asset or a Potential Breach Point?
Before diving into architectural issues, the researcher attempted to understand the touted flexible features of OPC-UA and whether its potential could present exploitable opportunities. Figure 2 indicates that OPC-UA’s reputed flexibility and adaptability in practice are comprised of three aspects: Complex Datatypes, Flexible Encoding, and Pre-security Messages.
Our previous article on OPC-UA mentioned a Trust List mechanism, which guarantees that both the Client and Server involved in setting up a connection are on the trust list. This mechanism provides diverse, user-friendly data structures and enables data to be encapsulated and transmitted in a variety of encodings. Additionally, to improve ‘efficiency’, the OPC Server eliminates the need for expensive whitelist verification processes when dealing with certain API requests that it frequently receives from the Client.
In OPC-UA, in addition to the most basic variable types (such as arrays, strings, text, etc.), there are four additional unique data structures that can be used, namely Variant, Extension Objects Used as Containers, Diagnostic Info, and Data Value. The most intriguing feature is that any variable in OPC-UA can contain any OPC-UA structure, XML, or even binary code. There can even be problematic situations where, within the structure of Extension Objects there are variables that also contain Extension Objects; this creates an issue of self-referential complex variables in the data structure, caught in a recursive loop that can affect the normal operations of the system. This piqued the researcher’s attention: could an OPC Server, which is supposed to operate efficiently, function well if this issue of Unlimited Nesting (self-referencing complex variables) arises?
Recursive Structure Causing Stack Overflow in .NET Runtime Parsing
Under the promotion of the OPC Foundation, their official .NET Standard open-source implementation (and other commercial variations) has become the preferred suite for the production stage in the industry. Upon studying the public source code of .NET Standard, researchers discovered that the official version had made some patch measures as early as 2018 to defend against Nesting Issue type of attack tactics. The patch method is such that each time an OPC server parses a complex variable, if it needs to recursively unfold a variable and its sub-variables, it will then record and confirm that the current recursion depth does not exceed a certain threshold. Should the recursion depth exceed that threshold, the server will abandon parsing the current connection so as to prevent a server crash.
However, why does the official version claim to modify numerous parts of the code to guard against this type of issue? This sparked the researcher’s intense interest and was mentioned in the lecture, “The Current Mainstream OPC-UA Suites are all Based on .NET Runtime (.NET Framework / .NET Core)”. Running on .NET can be considered a natural defense against traditional hacker RCE attacks and Memory Corruption tactics. However, .NET language isn’t particularly suited for handling recursive function behavior. This is because the default stack memory size of .NET Runtime is limited, and exceeding a certain recursion depth can easily trigger Stack Overflow in the underlying .NET Runtime, leading to a crash. This is a problem not initially considered in the OPC-UA concept. For example, the famous CVE-2018-12086 caused the OPC Server to crash just by transmitting a 64KB Extension Object structure.
Naturally, one might presume that after the fallout of CVE-2018-12086, the subsequent official patch should have rendered this category of attack strategies ineffective. This, however, may not be entirely accurate. There may be persisting issues related to other OPC-UA language features, which could be exploited to uncover more vulnerabilities for the same type of attacks.
The research team provided a specific instance from OPC-UA where they utilized a feature to unearth a fresh OPC vulnerability in 2021: They declared an OPC Variant variable and incorporated a Variant array within its structure. Each Variant in this array accommodates another array, and this continues in a chain.
If the data is nested deep enough, and is transmuted into an XML encoding package supported by OPC, which is then dispatched to the server for interpretation, it’s worth observing whether this practical illustration could inflict any substantial impact on the server’s performance, or perhaps even provoke a disastrous system crash due to vulnerability exploitation.
Learning from History: A Real Vulnerability That Devastates All OPC Servers
At this point, one can’t help but wonder: even if there are such maliciously tailored OPC packets that attackers want to send, shouldn’t the highly secure OPC be able to protect the trustworthiness of both ends of the connection through the Client/Server mechanism with a Trust List whitelist? How could there still be a chance for attack requests to be sent to the server? This goes back to what was previously mentioned: for the sake of efficiency, the server does not actually enforce a whitelist verification on high-frequency operation APIs such as OpenSecureChannel, GetEndpoints, FindServers, etc.
Therefore, in practical instances, an attacker can masquerade as an OPC Client, initiating a FindServersRequest to the server that isn’t restricted by the whitelist, and embed highly nested OPC variables within this request. This would render the server’s whitelist mechanism ineffective, and it would accept the malicious OPC variable from the attacker. During the parsing process, the attacker can recursively call functions an excessive number of times, ultimately leading to a stack overflow, causing the .NET Runtime to proactively shut down the software process of the OPC server.
This is the exploitation process of the infamous CVE-2021-27432. When this vulnerability was reported, not only were all OPC packages from the OPC Foundation affected, but the scope also extended to third-party cooperative OPC packages—including those from Softing and Unified Automation—with over 80% of the market’s products being affected. This also marked the first attempt by a research team to attack and maliciously exploit weaknesses of the abnormal crash type since the OPC Foundation made major security revisions in 2018.
From Service Crash to People: Attackers Target Factory Maintenance Personnel
Contrary to past IT vulnerabilities where attackers often aimed to take control of the machine, the researchers in this study suggest that this type of attack could become a new pattern in OT/ICS, shifting the ultimate goal from machine control to a higher level of human risk. This is due to the unique role of the OPC Server in the industrial control domain: the OPC Server is responsible for receiving information and issuing commands to endpoint devices like PLCs, HMIs, robotic arms, etc., within the factory. This allows engineers at the SCADA workstation to keep real-time tabs on factory operations without physically being in the factory.
Therefore, an abrupt halt in the OPC Server, which serves as the eyes within the factory, would result in engineers and maintenance personnel being unable to immediately grasp the status of the factory, leaving them effectively blind and defenseless. Subsequent physical attacks that the attacker truly wants to launch against the factory would be dangerous and destructive, potentially leading to a repeat of historical tragedies such as the Stuxnet incident.
Digging into the OPC Specifications for More Exploitation Opportunities – XXE
From the perspective of an attacker, any opportunity to collect more components for weaponization cannot be overlooked. The researchers found that during their code review of the commercial OPC package Unified Automation, a typical XXE vulnerability commonly exploited in traditional web penetration activities had not been properly addressed and protected against.
As previously mentioned, regardless of brand, all implementations of OPC-UA must support XML encoding and decoding by design. During their reverse engineering of Unified Automation’s code, the researchers discovered that the package does not disable the built-in XXE (XML External Entity) function of the XML parser during XML string parsing. This means that an attacker could craft an XML document that directs the parser to pull content from a URL or file path and parse it into the XML document.
This attack method is similar to the previously mentioned nested parsing supported by OPC variables, and can thus be maliciously exploited to dramatically increase the memory consumed by the OPC Server during XML parsing, eventually leading to a stack overflow and server crash. This vulnerability was reported and assigned the identifier CVE-2021-27434.
The Issue of Deserialization: Even Commercial OPC-UA Suites Designed in C/C++ Contain Vulnerabilities
In an effort to thoroughly probe all potential vulnerabilities in OPC-UA, the researchers also explored whether there were other potential exploitable tactics in the C/C++ (or ANSI C) implementation of OPC-UA suites, beyond the server stack overflow strategies resulting from nested variable parsing. For this, they selected the commercial OPC-UA suite Softing’s C/C++ package as their target for vulnerability mining.
The researchers point out that to ensure the effective transmission of diverse OPC data structures, the Softing C/C++ suite first encapsulates each OPC structure carrying data into a specific C++ structure known as OpcUa_ExtensionObject_Body. This is done prior to every transmission for network transmission. When this C++ structure is received at the server, the TB5OT.dll function is invoked to parse and then deserialize it, converting it back into the corresponding data laden OPC structure.
How can the C/C++ structure ‘OpcUa_ExtensionObject_Body’ being transmitted across the network be maliciously manipulated to cause a system crash on the Softing OPC Server? The researchers propose two feasible methods. The first involves transmitting a variable with XML content through the Softing OPC suite, then intercepting the packet with tools like Wireshark, and substituting any data structure for the XML type marker in the structure. This forced conversion of XML content data into an OPC data structure would induce a conversion anomaly, causing the system to crash. The second method is similar to the first, except it transmits an OPC structure through the Softing OPC suite, intercepts the packet, and replaces the structure’s ID with an incorrect structure ID. This, too, would prompt an anomaly in the OPC structure conversion, often leading to a service crash. Both of these attack approaches have been logged under the CVE number CVE-2021-32994.