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

  1. unique step: 1. reconnaissance
    admin login probing (UA Research/1.0) + firmware version check via python-requests/2.34.2
  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
  3. divergent step: 3. persistence · T1136.001
    created 6 backdoor super_admin accounts (fortipwn_test, fw1/fw2/fw3, fw_api, fortipwn_admin)
  4. shared step: 4. persistence · T1098.004
    planted SSH key on admin account (fingerprint withheld)
  5. divergent step: 5. defense-evasion · T1564
    set hidden:1 on admin account (invisible in management GUI)
  6. divergent step: 6. defense-evasion · T1556.006
    disabled two-factor authentication on admin account
  7. 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

  1. shared step: 1. initial-access · T1190
    unauthenticated Jenkins Script Console reachable from the internet; Groovy code execution as the Jenkins user, no exploit required
  2. unique step: 2. discovery · T1082
    host profiling (id, nproc, uname, free) before any deployment decision
  3. unique step: 3. discovery · T1083
    checked for aws/kubectl tooling to gauge cloud and Kubernetes access before deploying anything
  4. 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
  5. 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
  6. unique step: 6. credential-access · T1552.001
    read /root/.aws/credentials
  7. 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
  8. divergent step: 8. persistence · T1053.006
    systemd timer re-checks and re-adds the key every 5 minutes, 2 minutes after every reboot
  9. 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
  10. 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
  11. 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
  12. divergent step: 12. defense-evasion · T1562.001
    kills seven competing cryptojacking families on arrival

Side by side

green = shared by both campaigns.

Attribute-by-attribute comparison of FortiGate Admin-Hijack Operator Plants Hidden Backdoors and Steals Full Device Configuration and The Backdoor Key That Puts Itself Back. Values labelled "shared" appear in 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/0competing-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-requestsgroovy-script-console-abusesystemd-timer-persistencexmrig
Capabilities
MFA disableSSH key implantationconfig exfiltrationhidden-admin persistenceXMRig 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
FortiGateJenkins

← Compare a different pair