This is Part six of Team82's OPC UA Deep Dive Series, a comprehensive guide to the security of the OPC UA network protocol for unified OT communication. In this entry, we will unveil a unique exploit framework that was crucial to our OPC UA research journey. As of today, the framework will be freely and publicly available on our Git Hub repository.
Team82’s extensive Deep Dive Series on OPC UA has arrived at the point where we discuss the tools we’ve developed to examine this critical OT protocol, as well as the vulnerabilities uncovered throughout this lengthy research project.
The centerpiece tool of our research is an advanced OPC UA Exploit Framework we built and used to execute many unique attacks against OPC UA implementations. It’s been immensely useful in finding close to 50 vulnerabilities in products using the protocol from OPC-UA client to servers to protocol gateways. Today, we are announcing it during a presentation at the Black Hat Briefings in Las Vegas, and are making it publicly available on our GitHub repository. We invite fellow researchers and vendors to use this framework to test their code bases and the security of your respective products.
Download our Exploit Framework Here
Many leading vendors in the OPC UA community have already had limited access to our framework. We created a coalition of vendor representatives on a private Slack channel to share best practices around improving the security of the protocol stack and how it is implemented. These vendors have also used the framework to test their products, and numerous vulnerabilities have been uncovered and addressed since this effort started.
Researchers and vendors will find this one-of-a-kind framework useful because each of the attack techniques exploits specific functions within the OPC UA protocol implementation. Users can send attacks that contain malformed or malicious packets to subsets of OPC UA, for example, that could trigger vulnerabilities when parsed. While not all vendor implementations were vulnerable during our research, we did find exploits impacting OPC UA servers, for example, that were prone to specific classes of vulnerabilities.
We collected these methods and used the framework to test them on a wide range of servers; this is a unique capability that allowed us to trigger certain bugs or flaws in more than one server implementation.
Team82 has used iterations of this framework for some time, including our successful participation at the annual Pwn2Own Miami ICS hacking event run during the annual S4 Conference in Miami.
We hope that researchers and vendors take advantage of the free availability of the framework to test all the concepts we developed on their products. Our GitHub also includes a detailed explainer on how to use the tool.
In this blog, we’re going to explain how the framework is structured and reveal some of the unique attack capabilities available in the framework, and the currently supported OPC UA servers.
We divided the framework into four categories of payloads: Sanity, Attacks, Corpus, Server.
Sanity: Sanity payloads include Reading Nodes, specific NodeID information given a namespace and NodeID, etc.
Attacks: Unique OPC UA-specific attacks that can cause a denial of service, leak sensitive information, or even execute code remotely.
Corpus: Reproducing payloads from corpus; useful for fuzzing iterations and reproducers.
Server: Simple server implementations (currently one example with cross-site scripting (XSS) payloads).
Basic Usage: python main.py SERVER_TYPE IP_ADDR PORT ENDPOINT_ADDRESS FUNC_TYPE [DIR]
Examples:
Sanity: python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer sanity
Attack (DoS): python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer thread_pool_wait_starvation
python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer opcua_file FILE_PATH NUM_REQUESTS
python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer opcua_dir PATH_TO_DIR_WITH_CORPUS
python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer boofuzz_db BOOFUZZ_DB_FILEPATH
python main.py prosys 1.2.3.4 53530 /OPCUA/SimulationServer threads_run FUNC_NAME COUNT
Server Types: softing, unified, prosys, kepware, triangle, dotnetstd, open62541, ignition, rust, node-opcua, opcua-python, milo
Function types: threads_run, sanity , sanity_read_nodes , sanity_translate_browse_path , sanity_read_diag_info , sanity_get_node_id_info , opcua_dir , opcua_file , boofuzz_db , attack_file_nodejs_opcua_v8_oom , attack_file_ASNeG_OpcUaStack_unhandled_exception , chunk_flood , open_multiple_secure_channels , close_session_with_old_timestamp , complex_nested_message , translate_browse_path_call_stack_overflow , thread_pool_wait_starvation , unlimited_persistent_subscriptions , function_call_null_deref , malformed_utf8 , race_change_and_browse_address_space , certificate_inf_chain_loop , unlimited_condition_refresh
Sanity Name | Description | Function Keyword | Reference |
Diagnostic Info | Diagnostic summary information for the server |
| |
Get Node ID Info | Node ID is an identifier for a node in an OPC server’s address space. |
| |
Read Nodes | Read service is used to read attributes’ Nodes |
| |
Translate Browse Path | Translates browse paths to NodeIds. Each browse path is constructed of a starting Node and a RelativePath |
|
Sanity Name | Description | Function Keyword | Reference |
Diagnostic Info | Diagnostic summary information for the server | sanity_read_diag_info | |
Get Node ID Info | Node ID is an identifier for a node in an OPC server’s address space. | sanity_get_node_id_info | |
Read Nodes | Read service is used to read attributes’ Nodes | sanity_read_nodes | |
Translate Browse Path | Translates browse paths to NodeIds. Each browse path is constructed of a starting Node and a RelativePath | sanity_translate_browse_path |
Attack Name | Description | Vulnerability Type | Function Keyword | CVE and Reference |
Certificate Infinite Chain Loop | Some servers implemented the certificate chain check by themselves and forgot to protect against a chain loop. Example: Cert A is signed by Cert B which is signed by Cert A | Denial of Service |
| |
Chunk Flooding | Sending large amount of OPC UA MSG chunks without the Final chunk | Denial of Service |
| CVE-2022-29864, CVE-2022-21208, CVE-2022-25761, CVE-2022-25304, CVE-2022-24381, CVE-2022-25888 |
Open Multiple Secure Channels | Flooding the server with many open channel requests leads to a denial of service | Denial of Service |
| |
Close Session With Old Timestamp | Sending bad timestamp in the CLOSE session message leads to an uncaught stacktrace with sensitive information | Information Leakage |
| |
Complex Nested Message | Sending a complex nested variant leads to a call stack overflow | Denial of Service / Information Leakage |
| |
Translate Browse Path Call Stack Overflow | Triggering a stack overflow exception in a server that doesn't limit TranslateBrowsePath resolving calls | Denial of Service |
| |
Thread Pool Wait Starvation | Thread pool deadlock due to concurrent worker starvation | Denial of Service |
| |
Unlimited Persistent Subscriptions | Flooding the server with many monitored items with “delete” flag set to False leads to uncontrolled memory allocation and eventually to a denial of service | Denial of Service |
| |
Function Call Null Dereference | Triggering an application crash after several OPC UA methods have been called and the OPC UA session is closed before the methods have been finished. | Denial of Service |
| |
Malformed UTF8 | Triggering an application crash after processing malformed UTF8 strings | Remote Code Execution |
| |
Race Change And Browse Address Space | Adding nodes to the server address space and removing the nodes in a loop while browsing the entire address space. | Denial of Service |
| |
Unlimited Condition Refresh | Sending many ConditionRefresh method calls leads to uncontrolled memory allocations and eventually to a crash | Denial of Service |
|
We've implemented a simple way to fire up an OPC UA corpus at the servers. Our framework will wrap these samples in an OPC UA session so it’s very easy to use. This is very useful to reproduce bugs that were found using fuzzers.
opcua_message_boofuzz_db
: can be used to shoot an entire boofuzz db at a target
opcua_message_file
: can be used to shoot an a single file or directory of files with OPC-UA payloads (OPC-UA content itself)
In the repository we also included a lot of corpus we collected from our fuzzing attempts; check: input_corpus_minimized
. They are the result of many hours of fuzzing different targets via various methods and tools.
Currently our simple server PoC is a standalone script that is built on top of Python OPC-UA (asyncua). The current example was used in some RCE client exploitation (for example, see here).
Server Name | Default URI | Default Port | Server Keyword |
| 49320 |
| |
| 62541 |
| |
| 4897 |
| |
| 53530 |
| |
| 48050 |
| |
| 62541 |
| |
| 4885 |
| |
| 4840 |
| |
| 4855 |
| |
| 26543 |
| |
| 4840 |
| |
| 62541 |
|
We urge vendors and researchers alike to use our OPC UA Exploit Framework to test the security of OPC UA implementations. This is a unique collection of attacks, a one-stop for security testing of this crucial OT protocol stack. We already shared this framework with representatives of some of the leading OT vendors, and close to 50 vulnerabilities surfaced and were addressed.
We’re hoping to see more of you leverage this tool to test your products and in your research, and coordinate the disclosure of any vulnerabilities you may find with the affected vendor.
A Complete Guide to the OPC UA Attack Surface
Part 1: History of the OPC UA Protocol
Part 3: Exploring the OPC UA Protocol
Part 4: Targeting Core OPC UA Components
Part 5: Inside Team82’s Research Methodology
CWE-547 USE OF HARD-CODED, SECURITY-RELEVANT CONSTANTS:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 are vulnerable to an attacker impersonating the web application service and mislead victim clients.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 7.5
CWE-288 AUTHENTICATION BYPASS USING AN ALTERNATE PATH OR CHANNEL:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 contain an exposed web management service that could allow an attacker to bypass authentication measures and gain controls over utilities within the products.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 9.8
CWE-547 USE OF HARD-CODED, SECURITY-RELEVANT CONSTANTS:
Optigo Networks Visual BACnet Capture Tool and Optigo Visual Networks Capture Tool version 3.1.2rc11 contain a hard coded secret key. This could allow an attacker to generate valid JWT (JSON Web Token) sessions.
Optigo Networks recommends users to upgrade to the following:
CVSS v3: 7.5
CWE-912 HIDDEN FUNCTIONALITY:
The "update" binary in the firmware of the affected product sends attempts to mount to a hard-coded, routable IP address, bypassing existing device network settings to do so. The function triggers if the 'C' button is pressed at a specific time during the boot process. If an attacker is able to control or impersonate this IP address, they could upload and overwrite files on the device.
Per FDA recommendation, CISA recommends users remove any Contec CMS8000 devices from their networks.
If asset owners cannot remove the devices from their networks, users should block 202.114.4.0/24 from their networks, or block 202.114.4.119 and 202.114.4.120.
Please note that this device may be re-labeled and sold by resellers.
Read more here: Do the CONTEC CMS8000 Patient Monitors Contain a Chinese Backdoor? The Reality is More Complicated….
CVSS v3: 7.5
CWE-295 IMPROPER CERTIFICATE VALIDATION:
The affected product is vulnerable due to failure of the update mechanism to verify the update server's certificate which could allow an attacker to alter network traffic and carry out a machine-in-the-middle attack (MITM). An attacker could modify the server's response and deliver a malicious update to the user.
Medixant recommends users download the v2025.1 or later version of their software.
CVSS v3: 5.7