daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

4840-pentesting-opc-ua.md (14294B)


      1 ---
      2 title: "4840 - Pentesting OPC UA"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/4840-pentesting-opc-ua.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/4840-pentesting-opc-ua.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # 4840 - Pentesting OPC UA
     14 
     15 ## Basic Information
     16 
     17 **OPC UA**, standing for **Open Platform Communications Unified Access**, is a crucial open-source protocol used in various industries like Manufacturing, Energy, Aerospace, and Defence for data exchange and equipment control. It uniquely enables different vendors' equipment to communicate, especially with PLCs.
     18 
     19 Its configuration allows for strong security measures, but often, for compatibility with older devices, these are lessened, exposing systems to risks. Additionally, finding OPC UA services can be tricky since network scanners might not detect them if they're on nonstandard ports.
     20 
     21 **Default port:** 4840 (binary `opc.tcp`). Many vendors expose separate discovery endpoints (`/discovery`), HTTPS bindings (4843/443), or vendor-specific listener ports such as 49320 (KepServerEX), 62541 (OPC Foundation reference stack) and 48050 (UaGateway). Expect multiple endpoints per host, each advertising transport profile, security policy and user-token support.
     22 
     23 | Built-in NodeId | Why it matters |
     24 | --- | --- |
     25 | `i=2253` (`0:Server`) | Holds `ServerArray`, vendor/product strings and namespace URIs.
     26 | `i=2256` (`ServerStatus`) | Reveals uptime, current state, and optionally build info.
     27 | `i=2267` (`ServerDiagnosticsSummary`) | Shows session counts, aborted requests, etc. Great for fingerprinting brute-force attempts.
     28 | `i=85` (`ObjectsFolder`) | Entry point to walk exposed device tags, methods and alarms.
     29 
     30 ```text
     31 PORT     STATE SERVICE REASON
     32 4840/tcp open  unknown syn-ack
     33 ```
     34 
     35 ## Pentesting OPC UA
     36 
     37 To reveal security issues in OPC UA servers, scan it with [OpalOPC](https://opalopc.com/).<sup>[[1]](#references)</sup>
     38 
     39 ```bash
     40 opalopc -vv opc.tcp://$target_ip_or_hostname:$target_port
     41 ```
     42 
     43 ### Discovery & Enumeration Playbook
     44 
     45 1. **Locate all OPC UA transports**
     46    ```bash
     47    nmap -sV -Pn -n --open -p 4840,4843,49320,48050,53530,62541 $TARGET
     48    ```
     49    Repeat on UDP group addresses if the environment uses LDS-ME multicast discovery.
     50 
     51 2. **Fingerprint endpoints**
     52    - Invoke `FindServers`/`GetEndpoints` over each transport to capture `SecurityPolicyUri`, `SecurityMode`, `UserTokenType`, application URI and product strings.
     53    - Enumerate namespaces so you can resolve vendor-specific NodeIds; abuse namespace collisions to coax clients into loading attacker-controlled schemas.
     54 
     55 3. **Walk the address space**
     56    - Start at `ObjectsFolder (i=85)` and recursively `Browse`/`Read` to find writable process variables, `Method` nodes and historian/log nodes.
     57    - Query `ServerStatus.BuildInfo` to understand firmware provenance, and `ServerCapabilities.OperationLimits` to gauge how easy it is to exhaust server resources.
     58    - If anonymous access is allowed, immediately test `Call` on maintenance methods (e.g., `ns=2;s=Reset`, `ns=2;s=StartMotor`). Many vendors forget to bind role permissions to custom methods.
     59 
     60 4. **Session abuse**
     61    - Reuse or clone `AuthenticationToken` values from other sessions (captured via MITM or diagnostics exposure) to hijack existing subscriptions.
     62    - Force the server into `SessionDiagnostics` flooding by creating dozens of inactive sessions; some stacks crash once the `MaxSessionCount` limit is exceeded.
     63 
     64 ### Automated assessment with OpalOPC
     65 
     66 - The scanner can run interactively or headless, which is handy for CI/CD style OT baselines. Pipe its machine-readable findings into your reporting pipeline to highlight anonymous logins, weak policies, certificate validation errors and writable variables in minutes.<sup>[[1]](#references)</sup>
     67 - Combine OpalOPC output with manual browsing: feed the discovered endpoint list back into your custom tooling, then selectively weaponize high-impact nodes (e.g., `MotorControl/StartStop`, `RecipeManager/Upload`).
     68 
     69 ### Targeting discovery infrastructure, GDS & Reverse Connect
     70 
     71 - **Unsecured discovery still leaks plenty:** `FindServers`, `FindServersOnNetwork`, and LDS-ME/mDNS discovery are often reachable without transport security. Use them to harvest `ApplicationUri`, product/vendor strings, and alternate endpoint URLs before touching the actual server endpoint.
     72 - **Rogue discovery server angle:** A Global Discovery Server (GDS) can return server inventories, accept registrations, and manage certificates/trust lists. If you can register a rogue server or tamper with GDS responses, clients may be redirected to attacker-controlled endpoints before operators ever notice a certificate prompt.
     73 - **Reverse Connect widens the client-side attack surface:** In Reverse Connect mode the server initiates the TCP socket to the client, which is useful in segmented OT networks but also means an attacker-controlled server can reach engineering clients that never expose inbound OPC UA ports. When emulating a rogue server, test how strictly the client validates `ServerUri`, `EndpointUrl`, and the server certificate before it starts browsing or parsing responses.
     74 
     75 ### Attacking legacy security policies (Basic128Rsa15)
     76 
     77 - **Bleichenbacher-style oracle:** Systems that still allow the deprecated `Basic128Rsa15` policy (often toggled via build flags such as `CMPOPCUASTACK_ALLOW_SHA1_BASED_SECURITY`) leak padding validation differences. Exploit this by flooding `CreateSession` / `OpenSecureChannel` handshakes with crafted PKCS#1 v1.5 blobs to recover the server certificate’s private key, then impersonate the server or decrypt traffic.<sup>[[7]](#references)</sup>
     78 - **Authentication bypass:** OPC Foundation’s .NET Standard stack prior to 1.5.374.158 (CVE-2024-42512) and dependent products let unauthenticated attackers force that legacy policy and subsequently skip application-level authentication. Once you own the key material you can present arbitrary `UserIdentityTokens`, replay signed `ActivateSession` requests, and operate the plant as a trusted engineering workstation.<sup>[[7]](#references)</sup>
     79 - **Operational workflow:**
     80   1. Enumerate policies with `GetEndpoints` and note any `Basic128Rsa15` entries.
     81   2. Negotiate that policy explicitly (`SecurityPolicyUri` in `CreateSession`), then run your oracle loop until the recovered key validates.
     82   3. Abuse the key to forge a high-privilege session, switch roles, or silently downgrade other clients by acting as a rogue reverse proxy.
     83 - **CODESYS Runtime Toolkit (<3.5.21.0)** re-enabled Basic128Rsa15 whenever integrators compile with `CMPOPCUASTACK_ALLOW_SHA1_BASED_SECURITY`. Flip that flag, re-run the oracle workflow above, and you can leak the runtime's private key to impersonate trusted engineering workstations until patch level 3.5.21.0 or later is deployed.<sup>[[3]](#references)</sup>
     84 - **HTTPS reflection / relay bypasses:** 2025 research showed that HTTPS bindings deserve separate testing. OPC UA over HTTPS skips the binary `OpenSecureChannel` handshake, so endpoints that trust their own certificate or can be chained in a relay can still yield application-authentication bypasses (the same area covered by CVE-2024-42513 in the OPC Foundation .NET stack).<sup>[[7]](#references)</sup>
     85 - **Practical tooling:** Secura's `opcattack` turns the theory above into a repeatable test flow:<sup>[[6]](#references)</sup>
     86   ```bash
     87   # Enumerate binary + HTTPS endpoints and flag applicable attacks
     88   opcattack.py check opc.tcp://$TARGET:4840
     89   opcattack.py check https://$TARGET:4843
     90 
     91   # Test for unauthenticated access or HTTPS reflection/relay auth bypasses
     92   opcattack.py auth-check opc.tcp://$TARGET:4840
     93   opcattack.py reflect https://$TARGET:4843/
     94 
     95   # Demonstrate a padding oracle with signature forgery or ciphertext decryption
     96   opcattack.py sigforge opc.tcp://$TARGET:4840 deadbeef
     97   opcattack.py decrypt opc.tcp://$TARGET:4840 <hex_ciphertext>
     98   ```
     99 - Even if the target claims TLS, make sure it is not silently falling back to Basic128Rsa15 for the binary transport behind the proxy.
    100 
    101 ### 2024-2025 exploit watchlist
    102 
    103 - **open62541 fuzz_binary_decode (CVE-2024-53429):** SecureChannel chunks that declare oversized `ExtensionObject` bodies make the decoder dereference freed memory, so a pre-auth attacker can repeatedly crash UA servers that embed open62541 ≤1.4.6. Reuse the Claroty corpus (`opcua_message_boofuzz_db`) or craft your own Boofuzz harness to spam mutated `OpenSecureChannel` requests until the watchdog kills the process, then re-enumerate because many integrators fall back to anonymous mode after the reboot.<sup>[[4]](#references)</sup>
    104 - **Softing OPC UA C++ SDK / edgeConnector / edgeAggregator (CVE-2025-7390):** The TLS client-auth pipeline accepts any certificate that replays a trusted Common Name, so you can mint a throwaway cert, copy the CN from a plant engineer, and log in with arbitrary `UserNameIdentityToken` or `IssuedIdentityToken` data. Pair this with a downgrade to Basic128Rsa15 to strip integrity checks and persistently impersonate operators until trustlists are rebuilt.<sup>[[5]](#references)</sup>
    105 
    106 ### Crafting OPC UA clients for exploitation
    107 
    108 - **Custom clients:** Drop-in libraries (python-opcua/asyncua, node-opcua, open62541) let you drive exploit logic yourself. Always enforce your target namespace index to avoid accidental cross-namespace writes when vendors reorder namespaces after firmware updates.
    109 - **Node abuse checklist:**
    110   - `HistoryRead` on production tags to snapshot proprietary recipes.
    111   - `TranslateBrowsePathsToNodeIds` to resolve human-readable asset names into NodeIds that can be fed to gadgets like Claroty’s framework.
    112   - `Call` + `Method` nodes to trigger maintenance tasks (firmware upload, calibration, device reboots).
    113   - `RegisterNodes` mis-use to pin frequently accessed nodes and then starve legitimate clients by never releasing the handles.
    114 - **Session hardening tests:** Attempt to bind dozens of subscriptions with extremely low publishing intervals (below 50 ms) plus oversized monitored-item queues. Many stacks miscalculate `RevisedPublishingInterval` and crash due to scheduler overflows.
    115 
    116 ### Fuzzing & exploit development tooling
    117 
    118 Claroty Team82 released an open-source `opcua-exploit-framework` that packages years of Pwn2Own-grade research into reusable modules:<sup>[[2]](#references)</sup>
    119 
    120 - **Modes:** `sanity` (lightweight reads/browses), `attacks` (e.g., thread pool starvation, file upload DoS), `corpus` (replay fuzzing payloads), `server` (rogue OPC UA server to backdoor clients).
    121 - **Usage pattern:**
    122   ```bash
    123   # Run a DoS attack against a Prosys Simulation Server endpoint
    124   python3 main.py prosys 10.10.10.10 53530 /OPCUA/SimulationServer thread_pool_wait_starvation
    125 
    126   # Replay an entire Boofuzz corpus against open62541
    127   python3 main.py open62541 192.168.1.50 4840 / opcua_message_boofuzz_db input_corpus_minimized/opcua.db
    128   ```
    129 - **Rogue server scenario:** The bundled asyncua-based server lets you target client software by serving malicious address spaces (for example, responses with oversized `ExtensionObject`s to trigger parsing bugs in UA Expert clones).
    130 - **Target coverage:** Built-in profiles map to Kepware, Ignition, Unified Automation, Softing SIS, Triangle Microworks, Node-OPCUA, Python OPC UA, Milo, open62541, etc., so you can quickly swap between stacks without rewriting payloads.
    131 - **Integration tips:** Chain its output with your own fuzzers—spray the `corpus` payloads first, then have OpalOPC re-verify whether the crash resurrected insecure defaults (anonymous login, setpoint write access, etc.).
    132 
    133 ### Exploiting authentication bypasses
    134 
    135 If authentication bypass vulnerabilities are found, you can configure an [OPC UA client](https://www.prosysopc.com/products/opc-ua-browser/) accordingly and see what you can access. This may allow anything from merely reading process values to actually operating heavy-duty industrial equipment.
    136 
    137 To get a clue of the device you have access to, read the "ServerStatus" node values in the address space and google for a usage manual.
    138 
    139 ### Targeting OPC UA clients instead of servers
    140 
    141 - **Rogue-server testing is worth it:** Recent research against Ignition and Softing edgeAggregator showed that the client side can be just as exposed as the server side. If engineers browse to an attacker-controlled endpoint or import attacker-supplied backup/configuration content, you may be able to pivot from XSS/path-traversal style bugs into full client-side RCE.
    142 - **Offensive workflow:** Stand up a rogue OPC UA server, advertise realistic `ApplicationDescription`/`EndpointDescription` data, then feed clients malformed `ExtensionObject`s, hostile browse trees, or malicious backup artefacts. This is especially useful in environments where Reverse Connect allows servers to reach clients through the firewall.
    143 
    144 ## Shodan
    145 
    146 - `port:4840`
    147 - `port:62541 "OPC UA"`
    148 - `ssl:"urn:opcua"`
    149 - `product:"opc ua"`
    150 
    151 Combine the search with vendor strings (`"Ignition OPC UA"`, `"KepServerEX"`) or certificates (`"CN=UaServerCert"`) to prioritize high-value assets before starting intrusive testing.
    152 
    153 ## References
    154 
    155 - [1] [How to Hack OPC UA - OpalOPC](https://opalopc.com/how-to-hack-opc-ua/)
    156 - [2] [opcua-exploit-framework - Claroty Team82](https://github.com/claroty/opcua-exploit-framework)
    157 - [3] [VDE-2025-022: CODESYS Control V3 - OPC UA Server Authentication Bypass (CVE-2025-1468)](https://certvde.com/en/advisories/VDE-2025-022/)
    158 - [4] [CVE-2024-53429 - open62541 fuzz_binary_decode assertion failure](https://nvd.nist.gov/vuln/detail/CVE-2024-53429)
    159 - [5] [CVE-2025-7390 - Softing OPC UA client certificate trust bypass](https://industrial.softing.com/fileadmin/psirt/downloads/2025/CVE-2025-7390.html)
    160 - [6] [opcattack - Secura OPC UA attack tool](https://github.com/SecuraBV/opcattack)
    161 - [7] [No VPN Needed? Cryptographic Attacks Against the OPC UA Protocol - Black Hat USA 2025 (Tervoort/Secura)](https://i.blackhat.com/BH-USA-25/Presentations/USA-25-Tervoort-No-VPN-Needed-Cryptographic-Attacks.pdf)