Campaign comparison
FortiGate Admin-Hijack Operator Plants Hidden Backdoors and Steals Full Device Configuration vs The Backdoor Key That Puts Itself Back
2026-06-09 · 2026-09-02
Link signals
Analytic
Same stage(s) reached by different techniques: persistence, defense-evasion — same objective, different method
Commodity
Shared ATT&CK technique(s): T1098.004, T1552.001, T1555 — commodity, many actors share these
Actor & objective
Actor
z0r0 (suspected)
vs
unattributed
different
Objective
access-resale
vs
credential harvesting (Jenkins secrets, cloud credentials, SSH keys), banked for later use or resale rather than used immediately, plus opportunistic cryptomining once the initial access is established
different
Kill chain
= same stage & technique ≠ same stage, different technique • unique to one campaign
FortiGate Admin-Hijack Operator Plants Hidden Backdoors and Steals Full Device Configuration
-
unique step: 1. reconnaissance
admin login probing (UA Research/1.0) + firmware version check via python-requests/2.34.2
-
shared step: 2. initial-access
· T1190
CVE-2022-40684 auth bypass via Forwarded: for=127.0.0.1, after failed CVE-2024-21762 SSL-VPN heap-spray attempt
-
divergent step: 3. persistence
· T1136.001
created 6 backdoor super_admin accounts (fortipwn_test, fw1/fw2/fw3, fw_api, fortipwn_admin)
-
shared step: 4. persistence
· T1098.004
planted SSH key on admin account (fingerprint withheld)
-
divergent step: 5. defense-evasion
· T1564
set hidden:1 on admin account (invisible in management GUI)
-
divergent step: 6. defense-evasion
· T1556.006
disabled two-factor authentication on admin account
-
unique step: 7. exfiltration
· T1552.001
downloaded full FortiOS config backup x3 from two IPs (LDAP bind, VPN, SNMP creds)
The Backdoor Key That Puts Itself Back
-
shared step: 1. initial-access
· T1190
unauthenticated Jenkins Script Console reachable from the internet; Groovy code execution as the Jenkins user, no exploit required
-
unique step: 2. discovery
· T1082
host profiling (id, nproc, uname, free) before any deployment decision
-
unique step: 3. discovery
· T1083
checked for aws/kubectl tooling to gauge cloud and Kubernetes access before deploying anything
-
unique step: 4. credential-access
· T1555
in a three-second window, read credentials.xml plus both keys that decrypt it (secrets/master.key, secrets/hudson.util.Secret), the complete set needed to decrypt the whole store offline
-
unique step: 5. credential-access
· T1552.004
read /root/.ssh/id_rsa and id_ed25519 (private key material); neither key was ever presented back to any sensor afterward
-
unique step: 6. credential-access
· T1552.001
read /root/.aws/credentials
-
shared step: 7. persistence
· T1098.004
SSH public key spliced into the middle of authorized_keys (not appended), execute bit set as a side effect
-
divergent step: 8. persistence
· T1053.006
systemd timer re-checks and re-adds the key every 5 minutes, 2 minutes after every reboot
-
divergent step: 9. defense-evasion
· T1036.005
backdoor script disguised as an apt update checker; genuinely runs apt-get -s upgrade so the disguise produces real, plausible log output
-
unique step: 10. credential-access
· T1550.001
used the stolen AWS keys to call sts get-caller-identity and request a federation token, escalating from programmatic keys toward console access
-
unique step: 11. impact
· T1496
XMRig cryptominer, CPU-throttled to the exact core count profiled earlier, pool connection pinned into /etc/hosts to survive DNS-based blocking
-
divergent step: 12. defense-evasion
· T1562.001
kills seven competing cryptojacking families on arrival
Side by side
green = shared by both campaigns.
| FortiGate Admin-Hijack Operator Plants Hidden Backdoors and Steals Full Device Configuration | The Backdoor Key That Puts Itself Back |
|---|---|
| Procedures | |
| config-backup-exfilexploit-escalation:try-newer-then-pivothidden-admin-persistence:hidden-flagmfa-disableredundant-backdoor-accountsssh-key-implanttrusthost-any:0.0.0.0/0 | competing-miner-killcredential-store-full-decrypt-key-theftdns-containment-evasion-etc-hostsmasquerade-as-update-checkermid-file-key-insertionsystemd-timer-self-heal |
| Toolmarks | |
| account-naming:fortipwn_password-style:pentest (Test1234!/Pwn3d123!) | HUNTER_JK_OK_ / HUNTER_VERIFY_ tool markersWO<n>_RCE_OK / WO<n>_VERIFY_OK job markershost-monitor@main SSH key commentnet-maint-keepalive cron markerupdate-check.* masquerading unit names |
| C2 protocol | |
| — | none: all commands arrived inbound as POST requests to the unauthenticated Jenkins Script Console, 855 of them; no outbound C2 channel was ever established |
| Tooling | |
| custom-cve-2022-40684-exploitcve-2024-21762-modulepython-requests | groovy-script-console-abusesystemd-timer-persistencexmrig |
| Capabilities | |
| MFA disableSSH key implantationconfig exfiltrationhidden-admin persistence | XMRig cryptomining with CPU throttling and DNS-block evasioncloud credential harvesting and AWS API escalation attemptsfull Jenkins credential-store decryption key theftself-healing SSH backdoor (systemd timer re-adds a planted key every 5 minutes) |
| C2 | |
| — | 163.192.1.64 (second address, fetches tooling from the staging server)213.171.5.66 (staging server, serves /cdn/ payloads) |
| ASNs | |
| — | AS31898 (Oracle Cloud, second address)AS9123 (Timeweb, staging server) |
| Domains | |
| — | gulf.moneroocean[.]stream (mining pool, pinned into /etc/hosts to survive DNS-based blocking) |
| CVEs | |
| CVE-2022-40684CVE-2024-21762 | — |
| Products | |
| FortiGate | Jenkins |