Keypoints
- Zscaler detected exploitation activity for CVE-2024-3400 almost immediately after an exploitation script was published publicly.
- The Upstyle backdoor uses a three-layer design with base64-encoded payloads and installs a malicious /usr/lib/python3.6/site-packages/system.pth to auto-execute on Python startup.
- Upstyle’s launcher implements persistence and a check to run only under a specific process invocation (/usr/local/bin/monitor mp) to avoid duplicate threads.
- Command reception uses encoded commands injected into error logs (matching patterns like img[base64] or img{base64}) which the backdoor decodes and executes; output is exfiltrated by appending it inside comment blocks to a public stylesheet (bootstrap.min.css).
- The backdoor removes traces by purging attacker-generated lines from the error log, restoring file timestamps, and deleting the installer and specific license files.
- Zscaler observed scanning from known malicious IPs (e.g., 23.227.194.230) and recorded several SHA256 hashes associated with the activity.
MITRE Techniques
- [T1190] Exploit Public-Facing Application – The vulnerability allowed unauthenticated command execution: (‘an unauthenticated user to run arbitrary commands on the target system with root privileges.’)
- [T1546] Event Triggered Execution – The backdoor achieves auto-execution by writing a .pth file under site-packages which is executed whenever Python starts: (‘any .pth file under site-packages is run at every Python startup and the lines starting with import … are executed’)
- [T1027] Obfuscated Files or Information – The installer and launcher layers are stored as base64-encoded blobs to hide functionality: (‘the installer which contains the next layer in a base64-encoded format’)
- [T1059] Command and Scripting Interpreter – The backdoor decodes base64 commands from logs and executes them via a shell (os.popen): (‘the command is base64 decoded, executed, and the output is appended to the bootstrap.min.css file’)
- [T1071.001] Application Layer Protocol: Web Protocols – Command output is communicated to the operator by appending it to a publicly accessible stylesheet (bootstrap.min.css) so the operator can retrieve results over HTTP(S): (‘the output is appended to the bootstrap.min.css file inside the comment tags’)
- [T1070] Indicator Removal on Host – The backdoor purges attacker-generated entries from the error log and restores timestamps, and the installer deletes itself and a license file to remove traces: (‘Finally, the log file is purged … and the error-log-file timestamps are restored. … the installer script deletes itself and the /opt/pancfg/mgmt/licenses/PA_VM`* file.’)
Indicators of Compromise
- [IP] vulnerability scan / exploitation sources – 23.227.194.230, 154.88.26.223 (and 2 other scanning IPs)
- [IP] VPN-associated IP observed – 67.55.94.84 (SaferVPN IP)
- [SHA256] payload hashes observed – ab3b9ec7bdd2e65051076d396d0ce76c1b4d6f3f00807fa776017de88bebd2f3, 3de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac (and 2 more hashes)
- [File path / filename] persistence and artifact locations – /usr/lib/python3.6/site-packages/system.pth, /var/appweb/sslvpndocs/global-protect/portal/css/bootstrap.min.css, /var/log/pan/sslvpn_ngx_error.log
The Upstyle deployment follows a compact, repeatable sequence: an installer writes a base64-decoded launcher into /usr/lib/python3.6/site-packages/system.pth to force execution whenever Python is launched, then deletes itself and a license file to reduce evidence. The launcher decodes a further base64 blob containing the backdoor functions protect (to maintain the .pth content and handle termination by rewriting the file) and check (which verifies execution only when /proc/self/cmdline matches /usr/local/bin/monitor mp to avoid duplicate threads). These mechanisms together ensure persistence and controlled activation.
The active backdoor preserves original bootstrap.min.css content and timestamps, then enters a loop scanning /var/log/pan/sslvpn_ngx_error.log for patterns like img[base64] or img{base64}. When it finds a match it base64-decodes the embedded command, runs it (via os.popen), appends the command output inside comment blocks (/* … */) to bootstrap.min.css for operator retrieval, and then purges the injected log entries while restoring log timestamps; after a short delay it restores the stylesheet content and timestamps as well. The operator thus receives command outputs over a public web resource while the malware minimizes forensic traces by deleting installer artifacts and restoring timestamps.
Defenders should look for creation of .pth files under site-packages (notably /usr/lib/python3.6/site-packages/system.pth), unusual writes to GlobalProtect static assets (bootstrap.min.css), repeated base64 patterns in sslvpn_ngx_error.log, and the listed IPs and SHA256 hashes; monitoring for these indicators and applying the PAN-OS patch for CVE-2024-3400 are immediate mitigations.