← all research
2026-07-21 active exploitation

Tunnel Vision: Sonicwall Insecure Mobile Access

How UTA0533 turned a WebSocket proxy and a hotfix rollback script into root on SonicWall SMA1000

CVE-2026-15409CVE-2026-15410sonicwallvulnerabilityforensics
CVE
CVE-2026-15409, CVE-2026-15410
Severity
10.0
Critical
Vendor
SonicWall
Affected product
SMA1000 (6210, 7210, 8200v)
Disclosed
2026-07-14
Earliest known exploitation
2026-06-22
Patch status
Hotfix available · 12.4.3-03453 / 12.5.0-02835
timeline proof of concept details exploitation analysis considerations and limitations detection and hunting remediation and workarounds

CVE-2026-15409 and CVE-2026-15410 are the kind of pairing that makes threat actors happy and defenders tired. One is a pre-auth SSRF that turns a VPN appliance’s own WebSocket proxy into a tunnel straight to its internal-only services. The other is a path traversal in a “remove a hotfix” workflow that happily executes whatever you point it at, as root, no questions asked. Chain them together and you’ve got unauthenticated code execution on a SonicWall SMA1000 appliance sitting on the edge of somebody’s network. This isn’t theoretical. UTA0533 was doing this in production since at least late June 2026, and Volexity caught them in the act during an incident response engagement in early July.

The Vulnerabilities

CVE-2026-15409 (CVSS 10.0) lives in the /wsproxy endpoint of the SMA1000 WorkPlace web portal. This feature exists to proxy WebSocket connections to internal resources for legitimate remote access purposes. The problem is that with the right User-Agent and the right magic prefix on a request parameter, it will happily proxy a connection to 0.0.0.0 or 127.0.0.1, no authenticated session required. That gets an unauthenticated attacker a WebSocket tunnel directly to services that were only ever supposed to be reachable from inside the box: an Erlang Port Mapper Daemon, a CouchDB instance, and a control service listening on port 8188.

CVE-2026-15410 (CVSS 7.2) is a path traversal in sysCtrl.execRemoveHotfix, a method exposed by that same control service. The helper script it invokes, /usr/local/bin/remove_hotfix, builds a file path from caller-supplied input without meaningfully constraining it to the rollback directory it’s supposed to live in. Feed it a value like ../../../../../tmp/1234.sh and it will chmod +x and execute whatever’s sitting at /tmp/1234.sh, as root. SonicWall’s own advisory frames this as requiring authenticated administrator access to the Appliance Management Console. In practice, once you’ve tunneled into the control service through the wsproxy bypass, that authentication requirement is a formality you can route around, and Volexity’s forensic reconstruction shows the requirement wasn’t a meaningful obstacle in the observed intrusion at all.

Individually these are a critical info-disclosure-adjacent bug and a local privilege escalation. Chained, they’re a full pre-auth to root exploit against a VPN appliance, which is about as bad a sentence as you can write in this line of work.

Timeline

The public disclosure timeline is compressed, but the actual abuse window is longer and murkier, which is the usual story with edge appliances.

So the honest answer to “when did abuse start” is at least June 22, 2026, three weeks before public disclosure, and that’s just the earliest artifact Volexity happened to find timestamps for. Given this was caught mid-investigation rather than through proactive hunting, earlier undetected activity against other targets is entirely plausible.

Affected Versions and Patch Status

The vulnerabilities affect the SonicWall SMA1000 Series exclusively: models 6210, 7210, and 8200v. SSL-VPN functionality on SonicWall firewalls and the separate SMA 100 Series product line are not affected, so don’t go patching the wrong product line out of panic.

Vulnerable builds observed or referenced across advisories include:

Fixed versions:

There is no workaround that fully closes this off. SonicWall and multiple responders are explicit that patching alone is not sufficient either. If your appliance was internet-facing and running a vulnerable build any time between late June and mid-July 2026, you patch and then you go looking for evidence of compromise, in that order of urgency but not as a substitute for each other.

Proof of Concept Details

Rapid7 released a working Python PoC for CVE-2026-15409 targeting the Erlang process on localhost:1050, available at remmons-r7/rapid7-CVE-2026-15409. A Metasploit module covering the full chain was reported to be in development as of publication.

Example invocation from Rapid7’s writeup:

python3 cve-2026-15409.py --ws-url 'wss://192.168.1.46/wsproxy?bmID=-3389c1b25ccd&serviceType=SSH&host=0.0.0.0&port=1050' --ws-user-agent 'SMA Connect Agent' --ws-insecure-tls --cookie 10ecad5b446e86864832904cd439b6b70262 --exec 'whoami && id && pwd && hostname'

Example output:

Authenticated to SMAAppliance.sma
Peer flags: 0xd07df7fbd
Peer creation: 1784069352
RPC os:cmd/1 => couchdb
uid=1010(couchdb) gid=1(daemon) groups=1(daemon)
/opt/couchdb
SMAAppliance.sma

Notably, the Erlang distribution cookie used to authenticate to port 1050 is hardcoded on production appliances, so no credential guessing or brute forcing is required once the tunnel is up. Rapid7 also flagged that a separately released PoC targeting the sysCtrl control service depends on a hardcoded cookie value that only matches the publicly downloadable virtual SMA appliance, not the physical appliances Volexity examined in the wild, which explains why the actual in-the-wild path to the control service ran through CouchDB rather than the control service’s own authentication scheme.

Exploitation Analysis

Here’s where it gets fun. The chain has four moving parts: the wsproxy bypass, the internal service you land on, the privilege escalation, and the persistence mechanism the attacker builds once they’ve got root. Let’s walk through each.

Stage 1: The wsproxy Bypass (CVE-2026-15409)

The /wsproxy endpoint exists to let authenticated SMA users tunnel to internal resources over WebSockets, the kind of thing you’d expect for RDP or SSH proxying through a remote access gateway. The bypass hinges on two conditions:

  1. The User-Agent header is set to SMA Connect Agent, mimicking the appliance’s own native client rather than a browser.
  2. The bmID parameter begins with the literal prefix -3389.

Satisfy both and the appliance will establish a WebSocket tunnel to whatever host and port you specify, without a valid SMA session cookie. Here’s the request shape, distilled to its essential elements:

GET /wsproxy?bmID=-3389<suffix>&serviceType=SSH&host=0.0.0.0&port=<target-port>
User-Agent: SMA Connect Agent

A successful bypass gets you a WebSocket protocol upgrade:

HTTP/1.1 101 Switching Protocols
Sec-WebSocket-Protocol: binary

serviceType is nominally checked against expected values like SSH, but functionally it doesn’t gate what host and port you can reach. Volexity confirmed external reachability to three localhost-bound services through this bypass:

A read-only EPMD names query against port 1051 returns the registered node name couchdb on port 1050, which is a nice bit of free recon: the tunnel tells you exactly what’s listening before you even try to touch it.

Stage 2: Landing on CouchDB

This is the part Volexity couldn’t fully reconstruct from artifacts alone, and they’re upfront about that gap. What’s known:

Whether the actual technique used against CouchDB was identical to Rapid7’s Erlang RPC method, some CouchDB HTTP API abuse, or something else entirely, is something Volexity flags as unconfirmed. What’s not in question is the outcome: command execution in the context of the couchdb user, evidenced by a file at /tmp/1234.sh owned by couchdb:daemon with permissions -rwx--x--x.

Worth noting: Volexity separately identified that the control service’s Basic Auth can be bypassed entirely on many physical appliances, because the product_uuid value used to derive the password is a default UUID shared across large numbers of devices from the same hardware vendor, unrelated to the specific appliance’s identity. Virtual appliances weren’t affected by this particular shortcut. Volexity states this authentication weakness does not appear to be what UTA0533 actually used, since the actor still went to the trouble of reading the file locally rather than assuming the default value, but it’s a second, independent way into the same control service that anyone auditing these appliances should be aware of.

Stage 3: Root via Path Traversal (CVE-2026-15410)

With the product_uuid in hand and access to the control service on port 8188, the attacker can call sysCtrl.execRemoveHotfix. This method exists to let administrators roll back applied hotfixes. It builds an execution path like this:

__rollback="/var/lib/aventail/avp/rollback/${__hotfix}"
chmod +x ${__rollback}
exec ${__rollback} --unattended

${__hotfix} is caller-controlled and insufficiently sanitized against traversal sequences. Supply ../../../../../tmp/1234.sh as the hotfix value and the resulting path resolves to /tmp/1234.sh, well outside the intended rollback directory. The helper chmod +x’s it and executes it with --unattended, as root, because remove_hotfix runs in a privileged context regardless of who or what asked it to run.

Rapid7’s reconstruction shows this can also be reached through the web management console via an authenticated rollbackConfirm.action POST:

POST /rollbackConfirm.action HTTP/1.1
Host: 192.168.181.46:8443
Content-Type: application/x-www-form-urlencoded

csrfToken=GFEJUCQBUZOLUCCOO3YBA8G30ZE9VKDP&command=rollback&rollbackUpgradeTime=&hotfix=../../../../../tmp/1234.sh&rollbackHotfixTime=

Process monitoring during exploitation captures the privileged chain cleanly:

CMD: UID=0 PID=10355 | chmod +x /var/lib/aventail/avp/rollback/../../../../../tmp/1234.sh
CMD: UID=0 PID=10355 | /bin/bash /var/lib/aventail/avp/rollback/../../../../../tmp/1234.sh --unattended
CMD: UID=0 PID=10361 | /usr/bin/python3 /usr/local/ctrl-service/bin/ctrl-service.py
CMD: UID=0 PID=11124 | shutdown -r now

That last line matters: if the supplied hotfix file exists and executes, the appliance reboots shortly after as part of the normal rollback workflow. That reboot is a side effect the attacker has to plan around, and as we’ll get to, it’s also an accidental gift to defenders in at least one case.

Stage 4: Persistence and the Malware

Once root is established, UTA0533 didn’t sit on a shell. They built durable, memory-resident access with a purpose-built loader Volexity calls KNUCKLEBALL (deploy_new.py), dropped to /usr/lib/python3.11/site-packages/. The script’s job is to inject two Java payloads directly into the memory of a legitimate, already-running SonicWall process, workplace.startup.CommandStartup, rather than dropping a standalone malicious binary that antivirus or file integrity monitoring might catch.

The mechanics: KNUCKLEBALL enumerates /proc/<pid>/cmdline to find the target JVM’s process ID, then uses the Java Attach API (/tmp/.attach_pid<PID> and /tmp/.java_pid<PID>) to load two Base64-encoded JAR files as instrumentation agents:

load instrument false <path>

Before injection, it symlinks the agents’ internal log files (/tmp/agent_wp8.log, /tmp/agent_wp9.log) to /dev/null, so the injected code never leaves a log trail on disk. After injection succeeds, both staged JAR files are deleted from disk entirely. The only things left behind are the loaded classes sitting in the JVM’s memory and two new proxy routes quietly added to the local NGINX Unit config over its Unix socket:

[
  {
    "match": { "uri": "/__api__/login" },
    "action": { "rewrite": "/workplace/error.jsp", "proxy": "http://127.0.0.1:8085" }
  },
  {
    "match": { "uri": "/__api__/logout" },
    "action": { "rewrite": "/workplace/dialogs/errorDialog.jsp", "proxy": "http://127.0.0.1:8085" }
  }
]

Those two implants are:

Both gate access behind an identical, deliberately inconsistent user-agent string:

Mozilla/6.0 (Windows NT 11.0; Win64; x64) AppleWebKit/1537.136 (KHTML, like Gecko) Chrome/149.0.0.1 Safari/1537.136

There is no browser on Earth producing that exact combination of version numbers, which makes it a fantastic detection hook and a mildly funny attacker mistake.

ORANGETAIL specifically was engineered to not look like Behinder to signature-based detection: hand-rolled Base64 instead of java.util.Base64, fully reflective class loading (Class.forName to getMethod to invoke) instead of direct javax.crypto.Cipher imports, a hardcoded AES-128-ECB key instead of one derived from an authentication password, JSON-wrapped responses instead of raw encrypted bytes, and a 404 response to any request lacking the correct user-agent instead of rendering normally. Every meaningful string in the payload is built character by character via String.valueOf() rather than as plain literals, which is a small but deliberate move against static string-matching detection.

The net effect: an attacker gets two internet-reachable, memory-resident implants riding on top of a completely legitimate SonicWall JVM process, with no persistent malicious file on disk after the injection completes, and no log trail from the implants themselves.

Considerations and Limitations

This is the section where the gap between “we found evidence of compromise” and “we know everything that happened” opens up, and it’s a wide gap here.

Memory-resident implants leave nothing on disk once loaded. Suo5 and ORANGETAIL exist only as loaded classes inside a legitimate JVM’s memory after the staging JARs are deleted. If you’re doing disk forensics on a live-imaged appliance without capturing memory first, you will not find these implants. You’ll find the NGINX Unit config changes and maybe the deleted-file remnants if you’re doing careful filesystem carving, but the actual malicious code is gone the moment the process exits or the box reboots.

A reboot is an anti-forensic event here, whether intentional or not. Appliance 2 in Volexity’s investigation had been rebooted on July 2, 2026. Volexity’s own assessment is that this likely wiped the memory-resident backdoors along with other volatile artifacts. Recall that CVE-2026-15410’s own remove_hotfix workflow triggers a reboot as a side effect of successful exploitation. Whether that particular reboot was attacker-triggered cleanup, an unrelated maintenance reboot, or just the mechanical consequence of running the privesc exploit again, the result is the same: the richest evidence source for this intrusion evaporates on restart, and there’s no way after the fact to prove which of those explanations is correct.

Log-only investigation would have missed most of this. Volexity is explicit that working from exported logs alone, without a confirmed system-level compromise and on-system evidence to correlate against, makes it genuinely difficult to connect the dots or prove what happened. The logs told them exploitation attempts occurred. They did not, by themselves, tell them root was achieved, malware was loaded, or what that malware did next. It took SSH access, full memory acquisition, and disk imaging to turn “suspicious log entries” into a confirmed, reconstructed kill chain.

The CouchDB-to-control-service path has an evidentiary hole. Volexity could not conclusively determine the exact technique used to achieve code execution as the couchdb user. They have file ownership, timestamps, and a plausible mechanism (matching Rapid7’s independently developed Erlang RPC PoC), but not a confirmed, first-hand reproduction of what the attacker actually sent. That’s an honest gap, and it’s worth sitting with: even a thorough, well-resourced investigation with full memory and disk access can end up with “this is almost certainly how it happened” rather than “this is exactly how it happened” for one stage of a four-stage chain.

The control service’s default-UUID auth bypass complicates attribution of intent. Since a large number of physical SMA1000 appliances ship with the same default hardware UUID, and thus the same derivable control-service password, an investigator finding evidence of control-service access can’t automatically assume the attacker went through the CouchDB path versus just knowing (or guessing) the common default. In this specific case Volexity’s evidence points to the file-read approach, but that determination required the full forensic picture, not just the presence of control-service activity in isolation.

Attacker infrastructure resists simple network-based attribution. Over 200 distinct source IPs were used across the intrusion, with a mix of commercial VPN exit nodes (ExpressVPN, Mullvad, confirmed via Spur) and other addresses with no discernible shared infrastructure pattern. IP-based blocking or geofencing would have been a losing game here even if it had been attempted in real time.

Patching does not evict an attacker who already has root, and some attackers have proven that in practice. Rapid7’s incident response lead has since described cases where a customer applied the hotfix, and the threat actor, already established with root-level persistence, simply rolled the appliance’s own upgrade back down to the vulnerable build to restore their access path. That is a genuinely nasty forensic and operational problem: a patched build number in your asset inventory is not evidence of a clean appliance, it may just be evidence of the most recent state the attacker was willing to tolerate. This is the practical argument for treating “patch applied” and “compromise remediated” as two separate checkboxes that both need their own verification, rather than assuming the first implies the second.

LDAP traffic capture depends on the network being unencrypted in the first place. The tcpdump-based credential harvesting observed on Appliance 2 only worked because internal LDAP traffic was unencrypted. That’s not a gap in forensic visibility so much as a gap in the environment’s own hygiene, but it’s the kind of detail that determines whether “attacker got root on an appliance” turns into “attacker got a pile of domain credentials.”

Detection and Hunting

The good news: this intrusion left a lot of log evidence, assuming you’re looking at the right logs and they haven’t rotated out from under you.

Key Log Sources

/var/log/aventail/extraweb_access.log captures external web interaction, including the wsproxy bypass and webshell access. Look for:

GET /wsproxy?bmID=-3389<suffix>&serviceType=SSH&host=0.0.0.0&port=1050 HTTP/1.1" 101

The combination of wsproxy, a bmID beginning with -3389, and an HTTP 101 response status is the single strongest indicator in the whole chain. Rapid7’s guidance is to search this log for the string pattern "GET" AND "wsproxy" AND "=-3389" AND " 101 ". A host value of localhost, 0.0.0.0, or ::ffff:127.0.0.1 alongside that pattern all but confirms exploitation attempts against CVE-2026-15409. Legitimate uses of serviceType=SSH shouldn’t be pointing at 0.0.0.0.

Also watch for successful hits against the persistence routes:

POST /__api__/logout HTTP/1.1" 200
POST /__api__/login HTTP/1.1" 200

HTTP 200 responses on these paths are a red flag; these paths only resolve to something meaningful once the attacker’s NGINX Unit route rewrites are in place.

/var/log/aventail/access_servers.log provides corroborating WebSocket-level detail, including the client IP, connection port, and success/failure of the backend socket connection:

::WEBSOCK::Socket connected to backend success host = 0.0.0.0 and port =1050

/var/log/aventail/ctrl-service.log captures the privilege escalation itself:

running hotfix removal for:../../../../../tmp/1234.sh

Any traversal sequence in a remove_hotfix invocation pointing outside the expected rollback directory is confirmed exploitation of CVE-2026-15410, full stop.

Additional Hunting Steps

Volexity has published YARA signatures for KNUCKLEBALL, Suo5, and ORANGETAIL in their threat-intel GitHub repository, and both Rapid7 and Horizon3.ai have released independent validation and Rapid Response tooling.

Remediation and Workarounds

Patch. There is no meaningful workaround here, and multiple responders are explicit on this point.

Update to:

Beyond patching, given confirmed active exploitation and a demonstrated ability to persist without leaving disk artifacts:

Closing Assessment

What makes this chain notable isn’t any single vulnerability class. SSRF and path traversal are both well-worn categories. What makes it notable is the discipline behind the operation built on top of them: an authentication bypass that only activates for a specific user-agent and parameter prefix, a privilege escalation routed through a service account rather than the more obvious control-service path, malware that injects into a legitimate process instead of dropping a standalone binary, log files symlinked to /dev/null before injection, staged JARs deleted immediately after loading, and a custom webshell deliberately re-engineered to avoid the fingerprints of the well-known tool it’s functionally based on. This was not a smash-and-grab.

Three things stand out from a forensic-reality standpoint, which is the lens this blog usually cares about most:

  1. Memory-resident malware means disk forensics alone will miss the implant entirely. Suo5 and ORANGETAIL exist only in the memory of a legitimate process once staging files are deleted. Without memory acquisition, you get the persistence hooks (the NGINX route changes) but not the payloads themselves.

  2. A reboot is the great equalizer against your evidence, and this exploit chain causes one as a side effect of its own privilege escalation step. Whether by attacker design or accident, Appliance 2’s evidence trail was measurably thinner after its July 2 reboot. If your incident response process treats “reboot the affected device” as a routine containment step, reconsider that instinct for anything running memory-resident implants.

  3. A confirmed, evidence-backed reconstruction still had at least one honest gap. Even with SSH access, full memory capture, and disk imaging, Volexity could not conclusively pin down the exact CouchDB exploitation technique. That’s not a criticism of the investigation, it’s a reminder that “we reconstructed the chain” and “we have first-hand proof of every step” are not the same claim, and good forensic writeups say so out loud instead of papering over it.

  4. This was never just an espionage-flavored curiosity, and it isn’t a single-actor story anymore. UTA0533’s tradecraft (memory-resident implants, log manipulation, custom webshells built to dodge known signatures) reads like a patient, access-focused operation. But Rapid7 has since attributed a separate slice of the exploitation to Inc ransomware, with at least one case where ransomware was actually deployed, and Huntress has independently tied the same vulnerability chain to yet another, unrelated pair of intrusion sets across at least seven customers. The lesson isn’t “watch out for UTA0533 specifically.” It’s that once a chain like this is being used in the wild, whoever built the original tooling stops being the only threat model that matters. A capable initial-access broker’s work gets reused, copied, or independently rediscovered by whoever else is watching the same KEV entry, ransomware crews very much included.

Patch your SMA1000 appliances. Then go find out if you already needed to, and don’t assume the answer stays “no” just because the actor who compromised you isn’t the one everyone’s been writing about.

References