Rebuild and Reissue: SMA 1000 Remediation After INC Ransomware

If you run a SonicWall SMA 1000 VPN appliance on one of the affected 12.4.3 or 12.5.0 firmware builds (exact build numbers below), and it faced the internet before mid-July, the patch you applied on or after July 14 may not have ended an incident that had already started. The secondary bulletins list the 6210, 7210, and 8200v; if you run Central Management Server or another SMA 1000 form factor, settle your scope against SonicWall’s own notice rather than inferring it from those. Attackers chained the two flaws in the advisory with two further design weaknesses SonicWall did not separately assign a CVE in that advisory, and got complete control of the box. In the intrusions researchers have documented, an appliance reached before patching gave up the things that let them keep walking back in: user credentials, the database of live login sessions, and the secret seeds behind your users’ six-digit MFA codes. Those seeds are shared secrets. Once copied, they keep generating valid codes on the attacker’s laptop — whether or not the appliance is fixed, and for as long as the user keeps that authenticator enrolled. The fixed firmware blocks this documented exploit chain, but it does not remove persistence or invalidate credentials, sessions, or TOTP seeds stolen before patching. Rapid7 and Resecurity both assess INC Ransomware as the dominant actor currently weaponizing the chain, per Resecurity’s August 1 analysis, and for an appliance that was exposed and unpatched, the remediation question is rebuild-and-reissue, not patch-and-move-on.

The chain: CVE-2026-15409 (CVSS 10.0, CWE-918) is a pre-auth SSRF in the /wsproxy WebSocket endpoint of the SMA1000 WorkPlace interface, which happily opens a netcat-style TCP tunnel to a user-supplied host and port. Point it at loopback and you inherit the appliance’s localhost network position. CVE-2026-15410 (CVSS 7.2, classified CWE-94) is the privilege primitive: sysCtrl.execRemoveHotfix on ctrl-service at 127.0.0.1:8188 builds an execution path by string-concatenating attacker input, so a traversal sequence in the hotfix name reaches an arbitrary file and runs it as root. Affected firmware is 12.4.3-03245/-03387/-03434 and 12.5.0-02283/-02624/-02800; fixed builds are 12.4.3-03453 and 12.5.0-02835 or later. The published version tables are keyed to the three appliance models, which is why the scope question above is worth closing against the vendor notice rather than a bulletin. Volexity’s UTA0533 was on this before disclosure, from at least June 22, 2026. CISA added both CVEs to KEV on July 14 with a July 17 remediation date for federal civilian executive branch agencies, three days, and flagged both as known ransomware campaign use, which tells you how the agency read the exploitation reporting.

TL;DR

  • The fixed firmware blocks the documented chain but does not evict an attacker or invalidate what was already taken: Rapid7 reports that in observed cases attackers extracted credentials, active session databases, and TOTP seed configurations for long-term access, and a stolen seed keeps producing valid codes after a rebuild or a config restore until that authenticator is re-enrolled.
  • The published two-CVE framing hides the middle of the chain: /wsproxy SSRF opens a loopback socket, the CouchDB Erlang service on port 1050 (hardcoded admin:admin) was used to stage a script that read the product_uuid, and that world-readable value, with its dashes stripped and base64’d, is the ctrl-service Basic-auth password, so the “post-auth admin” 7.2 is reachable pre-auth.
  • Triaging off SonicWall’s advisory mis-sequenced the work, because a CVE record describes a primitive and never the composite it assembles into. Read the researcher writeup before writing the POA&M milestone.
  • Detection keys on the host/port tuple in extraweb_access.log (HTTP 101 on /wsproxy to loopback, or to 1050/8188 outside your approved ranges), not on the rotatable SMA Connect Agent UA or -3389 bmID values; validate that your pipeline preserves the query string first, or the search returns zero forever and looks like “no attacks.”
  • Split the POA&M into a CM item closed by a version string (12.4.3-03453 or 12.5.0-02835) and an IA item closed by evidence that appliance-managed authenticators were replaced and exposed credentials rotated. Close only the first and you get a green dashboard, a patched box, and an attacker holding working MFA.

The two-primitive framing undersells it

The clean story is reachability plus privilege. That’s how the advisories read, and it’s how most of the coverage has framed it. The actual chain in Volexity’s writeup has a third hop in the middle, and it’s the most interesting part of the whole thing.

/wsproxy gets you a socket to loopback. It does not get you code execution and it does not get you a file on disk. To reach remove_hotfix you need to talk to ctrl-service on 8188, and ctrl-service answers with 401 Unauthorized and a WWW-Authenticate: Basic realm="XMLRPC" header. It wants a password.

The attacker next tunneled to the appliance’s CouchDB-related Erlang service on loopback port 1050, which Volexity labels “CouchDB Erlang distribution,” alongside EPMD on 1051 and the control service on 8188. Volexity found that shipped CouchDB instances carry hardcoded credentials of admin:admin, and found forensic evidence that the couchdb account was used to write and run /tmp/1234.sh, a 123-byte script that read /sys/class/dmi/id/product_uuid. It says plainly that the exact operation used for the CouchDB exploitation in the observed intrusion remains unknown to it; the evidence is file ownership plus a timestamp match between port-1050 access and the script write. Rapid7 separately demonstrated Erlang-distribution command execution against its own test appliance using a hardcoded Erlang cookie, which Volexity notes was not present on the systems it analyzed. Two related findings, not one uniform proven mechanism.

Whichever operation it was, the payoff is the UUID. Strip its dashes, base64 it, and that is the ctrl-service password.

Read that again. The authentication secret for the root-privileged control service is a derivation of a world-readable DMI field.

There is a shortcut here that the observed intruders did not need. Volexity found that on multiple physical appliances the product_uuid was set to a common default shipped by hardware vendors and shared across unrelated customers, meaning an attacker who simply knows that default value can authenticate to the control service with no other exploitation at all. Volexity observed this only on physical devices, so virtual appliances were not exposed to that particular known-value condition, and it says this bypass does not appear to have been used in the incident it investigated. The attackers took the long way round and read the real UUID off the box instead. The shortcut is still sitting there.

So the sequence is: an unauthenticated HTTP request opens a loopback socket, a loopback service reachable with hardcoded credentials provides file write and execution as a low-privilege user, a world-readable hardware identifier provides the credential for the privileged service, and a traversal in that service executes the file you already staged. sysCtrl.execRemoveHotfix assembles /var/lib/aventail/avp/rollback/${__hotfix}, chmods it executable, and execs it. Supply ../../../../../tmp/1234.sh as the hotfix name and you are root.

Every individual link is a design decision someone made deliberately. /wsproxy proxying to arbitrary host:port is a product feature — that is literally what Connect Tunnel does. CouchDB on loopback is an implementation detail nobody expected to be routable. The DMI-derived password is an internal service-to-service convenience. None of them is a memory-safety bug or a fuzzing find. This is what an appliance looks like when the loopback interface is treated as a trust boundary and then something makes it routable.

Neither the hardcoded CouchDB credentials nor the UUID-derived control-service password was separately identified as a CVE in SonicWall’s July advisory, which covers the SSRF and the code-injection primitive and nothing else. That is a statement about the advisory, not a prediction. Absence from it does not establish that these conditions will never receive identifiers of their own.

Where SonicWall’s advisory misleads triage

SonicWall’s own description of CVE-2026-15410 is a post-authentication code injection in the Appliance Management Console, exploitable by a remote authenticated administrator. Arctic Wolf carries that framing verbatim, as do most of the bulletins that pulled from the advisory.

Technically that’s defensible. Operationally it’s wrong, and it cost people time. Read as written, a 7.2 post-auth admin-only code injection is a Wednesday item. You’d tell your ISSO it requires admin credentials and network access to the management console, and you’d sequence it behind the 10.0. But the “authentication” here is a base64’d hardware UUID that any process on the box can read, and the “remote administrator” position is manufactured by the 10.0 SSRF in the same request chain. The composite is pre-auth root, and neither CVE record says so.

If you triaged off the vendor advisory and deferred the 7.2 to your normal patch window, you had a window where an attacker who read the actual exploit chain understood your risk better than your vulnerability management program did. I don’t think this is malice from SonicWall — a CVE record describes a primitive and says nothing about the composite it can be assembled into, but it’s a good argument for reading the researcher writeup before you write the POA&M milestone, not after.

What they took

Once root, UTA0533’s tooling is competent and appliance-aware. ROOTRUN is a 13KB setuid ELF dropped at /usr/bin/xzfind, so any subsequent unprivileged shell can re-elevate. KNUCKLEBALL (deploy_new.py), persisted by a line added to the legitimate /etc/init.d/workplace startup script, uses the Java Attach API to inject two JARs into the running workplace.startup.CommandStartup process as instrumentation agents, and the NGINX Unit config at /var/lib/unit/conf.json is modified to proxy /__api__/login and /__api__/logout to them on local port 8085. The payloads are Suo5, an HTTP forwarding proxy gated on a specific user-agent, and ORANGETAIL, a Behinder-style Java webshell with a hardcoded AES-128-ECB key.

The JVM injection matters for your hunt. KNUCKLEBALL loads the Suo5 agent into the existing WorkPlace JVM and replaces the pre-existing com/aventail/jsp/workplace/error_jsp class with its payload implementation. Nothing is deployed as a JSP file on disk, and the hosting process was already running and already legitimate. If your entire integrity check is a filesystem sweep of /tmp and find / -perm -4000, you find the dropper and the setuid binary and you miss the resident implant.

Inspect both persistent and memory-resident artifacts, and do not use a reboot as evidence that the appliance is clean. Volexity observed that a reboot on one appliance had apparently removed the memory-resident implants — but the startup-script line and the conf.json routes were still there, ready to restore attacker functionality, and the reboot also destroyed the volatile evidence that would have told you what ran. If compromise is confirmed, preserve evidence first, then rebuild or redeploy on fixed firmware.

Then the collection. Cached credentials on the appliance. On at least one host Volexity found tcpdump running against TCP/389, harvesting cleartext LDAP binds, which is a reminder that plenty of shops still have their SMA doing unencrypted LDAP to a domain controller because LDAPS certificate validation broke once in 2019 and someone turned it off. And per Rapid7’s analysis relayed by The Hacker News, the extraction included active session databases and TOTP MFA seed configurations, explicitly for long-term persistence. Note the split in sourcing: the on-disk malware and the exploit chain come from Volexity, which does not discuss session databases or TOTP seeds at all; the credential-and-authenticator theft is Rapid7’s finding.

That last item is the whole argument. A TOTP seed is a symmetric shared secret. If it left the appliance, the attacker can generate valid codes for that user indefinitely, from anywhere, with no further access to anything of yours. Rebuilding the appliance does not invalidate it. Restoring from backup does not invalidate it; the backup contains the same seeds. The fix is re-enrollment, which is a helpdesk event you should be scheduling now rather than discovering in November when someone’s “MFA-protected” account authenticates from an ASN you’ve never seen.

Be careful about the scope you claim here, because the public reporting does not define it. Rapid7 says attackers systematically extracted TOTP seed configurations; it does not say whether every seed on every affected appliance was copied as one complete store. So the defensible population is every enrolled account whose TOTP configuration was stored on the compromised appliance, unless forensic evidence can reliably bound which seed records were actually accessed or exfiltrated. In practice most teams will not be able to bound it, and re-enrolling everyone is the correct conservative response, but write it down as a conservative assumption, not as an established fact, because your assessor will eventually ask which one it was.

Resecurity’s position is factory reset, reimage on fixed firmware, restore config from a backup predating the vulnerable branches. That’s right, and it’s still the easy half. The hard half is the credential material, and here the sources diverge in a way worth being explicit about. SonicWall and Rapid7 both condition reimaging, password changes, and TOTP resets on confirmed compromise: indicators found. Resecurity goes further and tells you to assume that any internet-facing, unpatched appliance running vulnerable firmware during the exposure window is either compromised or under active targeting, and to rotate on that basis.

Where compromise is confirmed, rotate administrator and directory-service credentials (LDAP, RADIUS, Active Directory bind accounts), reset appliance-managed TOTP enrollment, invalidate active sessions, and reset passwords for accounts that authenticated during the exposure window. Reissue appliance certificates, API keys, and other secrets where forensic review cannot establish that their private material stayed inaccessible. Root on the box makes certificate-key exposure possible, but the published investigations do not establish that the appliance private key was actually stolen in every intrusion, so reissue it because you cannot rule it out, not because someone proved it was taken. Where compromise is not confirmed but the appliance was exposed and unpatched, you are choosing between SonicWall’s evidence-led posture and Resecurity’s presumed-compromise posture. That is a risk decision with a real cost on both sides, and it belongs to your organization rather than to a blog post. Make it deliberately and record which one you picked.

On the scale question: INC’s leak site shows 885 claimed victims to date (Ransomware.Live figures cited by The Hacker News, most recent August 2), which is the group’s cumulative total across all intrusion vectors and years rather than an SMA-attributable count. Nobody has published an SMA-specific victim number, and the public reporting describes the recent attacks as suspected or assessed to involve these vulnerabilities rather than confirmed for each victim. Treat the 885 as evidence the group is prolific, not as a measure of this campaign.

Detection, and what breaks the first week

The signature is good, which is rare. Legitimate /wsproxy use targets internal RDP, SSH, and web hosts on your actual subnets. It never targets the appliance’s own loopback interface. So the discriminator is the host/port tuple in the query string, and for the loopback case the expected true volume is zero.

In /var/log/aventail/extraweb_access.log, look for HTTP 101 responses on /wsproxy where the host parameter resolves to loopback (127.0.0.1, localhost, 0.0.0.0, ::1, ::ffff:127.0.0.1), or where the port parameter is 1050 or 8188 and the destination sits outside the internal ranges you actually tunnel to. Splunk shape, assuming a sourcetype that preserves the query string:

sourcetype=sonicwall:sma:extraweb uri_path="/wsproxy" status=101
| eval uri_query=urldecode(uri_query)
| rex field=uri_query "(?:^|&)host=(?<ws_host>[^&]+)"
| rex field=uri_query "(?:^|&)port=(?<ws_port>\d+)"
| eval ws_host=replace(ws_host,"[\[\]]","")
| where match(ws_host,"^(127\.|0\.0\.0\.0$|localhost$|::1$|::ffff:127\.)")
   OR (
        ws_port IN (1050,8188)
        AND NOT cidrmatch("<approved-internal-ranges>",ws_host)
      )

Three notes on the query itself. Two of those lines are load-bearing and easy to drop. The urldecode handles percent-encoded IPv6 (%3A%3A1), which turns up in real traffic and will slide past a literal comparison, so decode before you match, not after. Decoding does not strip brackets, and a bracketed literal like [::1] survives it and still fails an anchored ^::1$, which is what the replace is there for. Anchor the extractions too: an unanchored host= will match inside vhost= and an unanchored port= inside export=, and either one hands you a value from the wrong parameter. 0.0.0.0 is in the host list for a related reason: it is not a loopback address, it is INADDR_ANY, but a connect() to it lands on localhost on Linux, which makes it a standard loopback-bypass string and worth matching.

Second, the two conditions are deliberately asymmetric, and an earlier version of this query got that wrong. A loopback destination is the real signal: Volexity’s own captured log lines show host=0.0.0.0 against ports 1050 and 8188, and legitimate /wsproxy use never targets the appliance itself, so the loopback clause can stand alone at any port. The port clause is the weaker half: a bare ws_port IN (1050,8188) with no host constraint also matches a perfectly legitimate tunnel to an internal host that happens to run something on those ports, which contradicts the “expected true volume is zero” claim I just made. Constrain it to destinations outside your approved internal ranges. Fill in the cidrmatch placeholder with your own ranges, and note that cidrmatch only evaluates literal IPs, so decide deliberately how you want hostname destinations handled rather than letting them fall through the comparison silently.

Ports 1051 (EPMD) and 8085 belong in enrichment, not in the alert. Volexity verified 1051 was externally reachable through the bypass, but the ports seen throughout the actual investigation were 1050 and 8188; 8085 is where the nginx routes proxy internally to the implants, so it is a post-compromise artifact rather than an inbound /wsproxy target. The loopback clause already catches all four when the destination is the appliance itself.

Third, if your ingestion rewrites or drops the WebSocket upgrade status, relax status=101 and key on the path and parameters alone; the host/port tuple is what carries the signal.

Four things will go wrong before that works.

The query string may not survive ingestion. If you’re taking the appliance’s syslog export rather than pulling the raw access log, you may be getting path-only URIs, and everything above silently returns zero results forever — which looks exactly like “no attacks.” Validate first with sourcetype=sonicwall:sma:extraweb uri_query=* | head 5. If that’s empty, fix the pipeline before you write the alert. Do not assume your existing SonicWall or generic web sourcetype preserves and parses the SMA1000 query string correctly. SonicWall does publish an SMA 1000 technical add-on for Splunk, but what your particular add-on, version, and locally installed content actually extract from this log is a question to answer by looking at the raw events and field extractions, not by assuming. Custom props.conf or transforms.conf work may be required.

Don’t key on the artifacts that rotate. Volexity documented the SMA Connect Agent user-agent and bmID values starting -3389, and Resecurity confirms both. Those are free to change and cost the operator nothing. The loopback host and the 1050/8188 ports are semantically required by the chain. Key on those, and keep the UA and bmID as enrichment fields for your analyst.

Log volume on a busy appliance is real. A few thousand tunnel users generate constant /wsproxy traffic, and extraweb_access.log is one of the noisier things you’ll onboard. Resist the urge to sample it — the events you need are individually rare and sampling is how you lose them. If retention cost is the blocker, index the full log hot for 30 days and summary-index the /wsproxy subset with the host/port fields extracted for the year.

There is a second on-appliance log worth pulling, and it is more direct than anything above. /var/log/aventail/ctrl-service.log records what ctrl-service was asked to execute, and Volexity’s published examples show the exploitation in plain text:

2026-06-28 22:34:34,527 - INFO - running hotfix removal for:../../../../../tmp/1234.sh
2026-06-28 22:52:19,293 - ERROR - Command '['/usr/local/bin/remove_hotfix',
  '../../../../../tmp/1234.sh']' exited with status '1'

A traversal sequence in a hotfix name is not something a legitimate operation produces. Grep for running hotfix removal for: and flag any value containing ../ or resolving outside /var/lib/aventail/avp/rollback/. Collect this log alongside extraweb_access.log; the access log tells you someone opened the tunnel, this one tells you what they ran as root through it.

And the on-appliance logs are only trustworthy up to the moment of root. Root can edit /var/log/aventail/*. If you have confirmed compromise, the forwarded copy in your SIEM is your evidence and the appliance copy is an artifact of unknown integrity. This is AU-9 in the most literal sense.

The correlation that survives all of this lives off the appliance. Rapid7 observed attacker-controlled workstation names such as KALI and DESKTOP-KRLUI3J in NTLM type-3 logons (Windows Event ID 4624) into internal domain controllers, sourced from the appliance’s internal IP. Your DCs are not compromised, so those events are honest. The tuning problem: if your SMA does NTLM passthrough, that source IP already has a baseline of type-3 logons, so presence alone is not the signal.

WorkstationName is the discriminator, but establish its legitimate distribution for your own environment rather than assuming one. Rapid7 gives you the attacker examples, not a statement about what normal looks like, and what your appliance populates that field with depends on your deployment. Baseline 30 days, then alert on new or non-inventory values that have no corresponding VPN session. Expect a handful of false positives from your own admins’ jump boxes and, occasionally, from a pentest nobody told the SOC about.

Time skew will make the correlation annoying. If the SMA syncs to a public NTP pool while your DCs follow the PDC emulator, the /wsproxy 101 and the resulting 4624 can land seconds to minutes apart. Measure the actual skew among the appliance, your SIEM ingestion path, and the domain controllers, and set the correlation window from that. Five minutes is a defensible starting point for incident hunting where synchronization quality is unknown; it is a tuning parameter, not a property of the product.

Control mapping

Control What this chain did to it
IA-5 Default CouchDB credentials on loopback and a service password derived from a world-readable DMI field. Inherited from the vendor build; you cannot fix it, only detect the consequence.
CM-7 An internal database and an XML-RPC control service listening on loopback with no expectation of ever being routable. Least functionality assessed at the wrong boundary.
SC-7 The appliance is the boundary device. /wsproxy made the boundary transitive.
SI-7 Setuid binary planted at /usr/bin/xzfind, JARs injected into a live JVM. No vendor-supplied integrity verification you can run yourself on SMA1000, though Volexity has published YARA signatures for the malware families.
AU-9 Root access means appliance-local logs are attacker-writable. Only forwarded copies are evidence.
IA-2, IA-5, AC-12 Compromise of authenticator secrets and active session state. Reset affected authenticators, rotate associated credentials, and invalidate active sessions.
SR-3, SR-11 You inherited the vendor’s internal service-to-service authentication design without ever being able to review it. SR-11 is the weaker of the two here: it addresses component authenticity and anti-counterfeit rather than the design quality of genuine vendor code, so treat it as an interpretive mapping.
CA-7, RA-5 The composite risk of the two CVEs was not visible in either CVE record. Scanner output alone would have mis-sequenced this.

The part your POA&M has to say

Write the remediation entry as two separate items with different owners and different closure evidence. Firmware to 12.4.3-03453 or 12.5.0-02835 is a CM task, closed by a version string.

Credential and authenticator remediation is an IA task, and it closes on evidence that all appliance-managed TOTP enrollments were replaced, relevant sessions were invalidated, administrator and service credentials were rotated, and passwords were reset for accounts whose credentials were stored, processed, captured, or otherwise exposed during the compromise window, plus a reissued appliance certificate where private-key exposure cannot be excluded. Note that those are different populations with different justifications. TOTP enrollment and password rotation address different authenticators, so “every account enrolled on the appliance” is the right basis for re-enrollment and the wrong basis for mandatory password rotation. Say in the artifact which population each action covers and why, because an assessor who finds one population silently standing in for the other will ask, and “we reset everything” is a defensible answer only when you can show it was a decision rather than an accident.

If you close the first and leave the second open, you have a patched appliance and an attacker with valid MFA. That is a worse position than being unpatched and knowing it, because the dashboard is green.

Sources


This post was engineered and validated through a multi-agent AI workflow — drafted, adversarially reviewed by several independent models, checked against primary sources, and given a human review before publishing. See an inaccuracy, or found this useful? Leave a comment below — corrections and feedback are read and shape what comes next.

Leave a comment