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

Reading time: 8 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Esta técnica abusa de pipelines de descoberta de serviço impulsionadas por regex que analisam as linhas de comando de processos em execução para inferir versões de serviço e então executam um binário candidato com uma flag "version". Quando padrões permissivos aceitam caminhos não confiáveis controlados pelo atacante (ex.: /tmp/httpd), o coletor privilegiado executa um binário arbitrário a partir de uma localização não confiável, resultando em elevação de privilégio local. NVISO documentou isso no VMware Tools/Aria Operations Service Discovery como CVE-2025-41244.

  • Impacto: Elevação de privilégio local para root (ou para a conta de descoberta privilegiada)
  • Causa raiz: Untrusted Search Path (CWE-426) + correspondência permissiva por regex das linhas de comando dos processos
  • Afetados: open-vm-tools/VMware Tools no 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 executa discovery scripts dentro do guest via VMware Tools usando credenciais privilegiadas configuradas.
  • Credential-less (modern): A lógica de discovery roda dentro do VMware Tools, já privilegiada no guest.

Ambos os modos, em última instância, executam lógica de shell que escaneia processos com listening sockets, extrai um caminho de comando correspondente via regex, e executa o primeiro token de argv com uma flag de versão.

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

No open-vm-tools, o script do plugin serviceDiscovery get-versions.sh corresponde binários candidatos usando expressões regulares amplas e executa o primeiro token sem qualquer validação de caminho confiável:

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
}

É invocado com padrões permissivos contendo \S (não é espaço em branco) que irão corresponder sem problemas a caminhos não do sistema em locais graváveis pelo usuário:

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
  • Extração usa grep -Eo e pega o primeiro token: ${COMMAND%%[[:space:]]*}
  • Não há whitelist/allowlist de caminhos do sistema confiáveis; qualquer listener descoberto com um nome correspondente é executado com -v/--version

Isso cria uma primitiva de execução por caminho de busca não confiável: binários arbitrários localizados em diretórios graváveis por qualquer usuário (por exemplo, /tmp/httpd) são executados por um componente privilegiado.

Exploração (modos sem credenciais e com credenciais)

Precondições

  • Você pode executar um processo não privilegiado que abre um socket de escuta no guest.
  • O discovery job está habilitado e é executado periodicamente (historicamente ~5 minutos).

Etapas

  1. Coloque um binário em um caminho que corresponda a um dos regex permissivos, por exemplo /tmp/httpd ou ./nginx
  2. Execute-o como um usuário com poucos privilégios e certifique-se de que ele abra qualquer socket de escuta
  3. Aguarde o ciclo de discovery; o collector privilegiado irá executar automaticamente: /tmp/httpd -v (ou similar), executando seu programa como root

Demonstração mínima (usando a abordagem da 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

Sequência típica de processos

  • Com credenciais: /usr/bin/vmtoolsd -> /bin/sh /tmp/VMware-SDMP-Scripts-.../script_...sh -> /tmp/httpd -v -> /bin/sh -i
  • Sem credenciais: /bin/sh .../get-versions.sh -> /tmp/httpd -v -> /bin/sh -i

Artefatos (com credenciais) Scripts wrapper SDMP recuperados em /tmp/VMware-SDMP-Scripts-{UUID}/ podem mostrar a execução direta do caminho malicioso:

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

Generalizing the technique: regex-driven discovery abuse (portable pattern)

Muitos agentes e suítes de monitoramento implementam descoberta de versão/serviço por:

  • Enumerar processos com sockets de escuta
  • Fazer grep em argv/linhas de comando com regexes permissivas (por exemplo, padrões contendo \S)
  • Executar o caminho correspondido com uma flag benigna como -v, --version, -V, -h

Se a regex aceitar caminhos não confiáveis e o caminho for executado a partir de um contexto privilegiado, você obtém CWE-426 Untrusted Search Path execution.

Abuse recipe

  • Nomeie seu binário como daemons comuns que a regex provavelmente corresponderá: httpd, nginx, mysqld, dataserver
  • Coloque-o em um diretório gravável: /tmp/httpd, ./nginx
  • Garanta que ele corresponda à regex e abra qualquer porta para ser enumerada
  • Espere pelo coletor agendado; você obtém uma invocação privilegiada automática de -v

Masquerading note: This aligns with MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) to increase match probability and stealth.

Reusable privileged I/O relay trick

  • Construa seu helper de forma que, ao ser invocado com privilégios (-v/--version), ele se conecte a um ponto de encontro conhecido (por exemplo, um socket UNIX abstrato do Linux como @cve) e faça uma ponte entre stdio e /bin/sh -i. Isso evita artefatos em disco e funciona em muitos ambientes onde o mesmo binário é re-invocado com uma flag.

Detection and DFIR guidance

Hunting queries

  • Filhos incomuns de vmtoolsd ou get-versions.sh, tais como /tmp/httpd, ./nginx, /tmp/mysqld
  • Qualquer execução de caminhos absolutos não-sistêmicos por scripts de descoberta (procure por espaços em expansões ${COMMAND%%...})
  • ps -ef --forest para visualizar árvores de ancestralidade: vmtoolsd -> get-versions.sh ->

On Aria SDMP (credential-based)

  • Inspecione /tmp/VMware-SDMP-Scripts-{UUID}/ em busca de scripts transitórios e artefatos stdout/stderr mostrando a execução de caminhos do atacante

Policy/telemetry

  • Alertar quando coletores privilegiados executarem a partir de prefixos não-sistêmicos: ^/(tmp|home|var/tmp|dev/shm)/
  • Monitoramento de integridade de arquivos em get-versions.sh e plugins do VMware Tools

Mitigations

  • Correção: Aplique atualizações Broadcom/VMware para CVE-2025-41244 (Tools and Aria Operations SDMP)
  • Desative ou restrinja a descoberta sem credenciais quando viável
  • Valide caminhos confiáveis: restrinja a execução a diretórios permitidos (/usr/sbin, /usr/bin, /sbin, /bin) e apenas binários conhecidos e exatos
  • Evite regexes permissivas com \S; prefira caminhos absolutos explícitos ancorados e nomes de comando exatos
  • Reduza privilégios para helpers de descoberta quando possível; sandbox (seccomp/AppArmor) para reduzir o impacto
  • Monitore e gere alertas sobre vmtoolsd/get-versions.sh executando caminhos não-sistêmicos

Notes for defenders and implementers

Padrão mais seguro de correspondência e execução

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

Referências

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks