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-191 INTEGER UNDERFLOW (WRAP OR WRAPAROUND):
The affected product is vulnerable to an integer underflow. An unauthenticated attacker could send a malformed HTTP Requesty, which could allow the attacker to crash the program.
Planet Technology recommends users upgrade to version 1.305b241111 or later.
CVSS v3: 5.3
CWE-78 IMPROPER NEUTRALIZATION OF SPECIAL ELEMENTS USED IN AN OS COMMAND ('OS COMMAND INJECTION'):
The affected product is vulnerable to a command injection. An unauthenticated attacker could send commands through a malicious HTTP request which could result in remote code execution.
Planet Technology recommends users upgrade to version 1.305b241111 or later.
CVSS v3: 9.8
CWE-121 STACK-BASED BUFFER OVERFLOW:
The affected product is vulnerable to a stack-based buffer overflow. An unauthenticated attacker could send a malicious HTTP request that the webserver fails to properly check input size before copying data to the stack, potentially allowing remote code execution.
Planet Technology recommends users upgrade to version 1.305b241111 or later.
CVSS v3: 9.8
CWE-359 Exposure of Private Personal Information to an Unauthorized Actor:
Ruijie Reyee OS versions prior to 2.260.0.1329 contains a a feature that could enable sub accounts
or attackers attackers to view and exfiltrate sensitive information from all cloud accounts registered to Ruijie's services.
CVSS v3: 6.5
CWE-1391 Use of Weak Credentials:
Ruijie Reyee OS versions prior to 2.260.0.1329 uses weak credential mechanism that could allow
an attacker to easily calculate MQTT credentials.
Ruijie reports that the issues have been fixed on the cloud and no action is needed by end users.
CVSS v3: 7.5