Cutting Edge, Part 3: Investigating Ivanti Connect Secure VPN Exploitation and Persistence Attempts | Mandiant

Mandiant observed China-nexus actor UNC5325 actively exploiting an SSRF in Ivanti Connect Secure (CVE-2024-21893), chaining it to command injection to deploy web shells and appliance-specific backdoors. The intrusions use living-off-the-land techniques and novel malware (for example, BUSHWALK and LITTLELAMB.WOOLTEA) that attempt persistence across upgrades and factory resets. #UNC5325 #BUSHWALK

Keypoints

  • UNC5325 exploited CVE-2024-21893 (SSRF in the SAML component) and chained it to CVE-2024-21887 (command injection) to execute arbitrary commands and establish shells.
  • BUSHWALK, a Perl web shell embedded in querymanifest.cgi, was deployed and can perform arbitrary file reads and command execution when activated.
  • LITTLELAMB.WOOLTEA (libchilkat.so) is a JNI-loaded shared object that daemonizes, hardens itself (OOM adjustment, signal trapping), and implements multiple persistence strategies across upgrades and factory resets.
  • Persistence methods include modifying SparkGateway configuration to load malicious plugins (PITFUEL/PITDOG), injecting shared objects into the web process (PITSOCK/PITHOOK), and appending malicious components into system backup archives restored during upgrades.
  • Detection artifacts include unauthenticated request log event AUT31556, saml-server crash event ERR31903, core dumps under /data/var/cores/, and specific filenames/hashes (e.g., querymanifest.cgi, libchilkat.so, plugin.jar).
  • Attackers used living-off-the-land utilities on the appliance (configdecrypt, mount/losetup, tar, touch) and public callback services (e.g., Interactsh / oast.live) to validate and exploit targets.
  • Ivanti released mitigations and an Integrity Checking Tool (ICT) update; organizations should analyze allocated/unallocated disk and core dumps because attackers attempted log deletion and timestomping to evade detection.

MITRE Techniques

  • [T1190] Exploit Public-Facing Application – Used via SSRF to gain initial access and chain to command injection (‘server-side request forgery (SSRF) vulnerability in the SAML component’).
  • [T1059] Command and Scripting Interpreter – Executed Python one-liners to perform reconnaissance and establish reverse shells (‘GET /api/v1/license/keys-status/;python -c …’).
  • [T1505.003] Web Shell – BUSHWALK was embedded in a legitimate Ivanti component to enable remote file reads and command execution (‘web shell tracked as BUSHWALK’ and embedded in querymanifest.cgi).
  • [T1070.006] Timestomping – The actor timestomps files to hide activity during deactivation routines (‘touch -r /home/webserver/htdocs/dana-na/auth/setcookie.cgi /home/webserver/htdocs/dana-na/jam/querymanifest.cgi’).
  • [T1055] Process Injection – Malicious shared objects (PITHOOK/PITSOCK) hook web process functions by modifying the procedure linkage table (PLT) to intercept sockets (‘modifying its procedure linkage table (PLT)’).
  • [T1543] Create or Modify System Process – SparkGateway plugins (PITFUEL/PITDOG) and configuration edits were used to load and persist malicious plugins (‘pluginFile = /home/runtime/SparkGateway/plugin.jar’).
  • [T1574] Hijack Execution Flow – JNI/System.load and other dynamic library loading techniques were used to load malicious shared objects into legitimate processes (‘System.load(“/home/runtime/SparkGateway/libchilkat.so”)’).

Indicators of Compromise

  • [CVE] exploited/targeted – CVE-2024-21893, CVE-2024-21887
  • [Filename / Host-based] observed malicious files – querymanifest.cgi (BUSHWALK) (hash e48716521dc48425feae71bc9dc768cd), libchilkat.so (LITTLELAMB.WOOLTEA) (hash fd83b3e9db57838b62c5baf8218ce5a8), and 12 more filenames/hashes.
  • [File hash] examples – e48716521dc48425feae71bc9dc768cd (querymanifest.cgi), fd83b3e9db57838b62c5baf8218ce5a8 (libchilkat.so).
  • [Event IDs / Logs] appliance log indicators – AUT31556 (unauthenticated request to /dana-ws/saml.ws), ERR31903 (saml-server process crash).
  • [Domain / callback] validation and callbacks – use of Interactsh / ‘.oast.live’ to validate SSRF targets.
  • [Unix sockets / IPC] local backdoor communication – /tmp/clientsDownload.sock (PITSOCK), /data/runtime/cockpit/wd.fd (PITSTOP).

UNC5325 exploited an SSRF in the SAML component (CVE-2024-21893), chaining it to known command-injection vectors to run arbitrary commands and drop web shells. Attack validation frequently used public callback services (for example, Interactsh / <randomstring>.oast.live), and actors executed python one-liners to perform reconnaissance and open reverse shells. Detection markers from exploitation include AUT31556 (unauthenticated request to /dana-ws/saml.ws), ERR31903 (saml-server crash), and recoverable core-dump fragments under /data/var/cores/ when available.

Post-exploitation components centered on a Perl web shell (BUSHWALK) and two plugin-based persistence chains. BUSHWALK is stored encrypted in /data/runtime/cockpit/diskAnalysis and activated/deactivated by modifying DSUserAgentCap.pm to remount filesystems, run /home/bin/configdecrypt to decrypt diskAnalysis, move the web shell into the webroot, and restart the webserver; deactivation restores the original querymanifest.cgi and timestomps it to conceal activity. The SparkGateway plugin chain uses plugin.jar (PITFUEL) to System.load() libchilkat.so (LITTLELAMB.WOOLTEA), which daemonizes, traps signals, adjusts oom_adj, and appends its components to /data/pkg/data-backup.tgz so they are restored during system upgrades; a second plugin (security.jar / PITDOG) uses Kubo Injector (memorysCounter) to inject mem.rd (PITHOOK) into the web process and launch dsAgent (PITSTOP) for command execution and file operations over local sockets.

Persistence across upgrades and factory resets leverages two archive-based techniques: edit_current_data_backup() appends plugin.jar, libchilkat.so, and gateway.conf into /data/pkg/data-backup.tgz (restored post-upgrade), and upgrade_monitor()/edit_factory_reset() insert malicious components into samba_upgrade.tar or trojanize tar inside the mounted factory-reset image so the post-install script extracts them to the active partition. The factory-reset persistence attempt failed on analyzed devices when losetup could not decrypt the factory image due to kernel/encryption-key mismatches. For detection, analyze allocated and unallocated disk, recover core dumps, check for the listed filenames/hashes, watch for PLT-hooking behaviors in web process memory, and monitor the integrity checker exclusions and SparkGateway configuration for unauthorized plugin entries.

Read more: https://www.mandiant.com/resources/blog/investigating-ivanti-exploitation-persistence