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

Reading time: 8 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Diese Technik missbraucht regex-gesteuerte Service-Discovery-Pipelines, die laufende Prozess-Kommandozeilen parsen, um Service-Versionen zu ermitteln und dann ein Kandidaten-Binary mit einem "version"-Flag auszuführen. Wenn permissive Patterns untrusted, vom Angreifer kontrollierte Pfade akzeptieren (z. B. /tmp/httpd), führt der privilegierte Collector ein beliebiges Binary aus einem untrusted Speicherort aus, was zu einer lokalen Privilegienerhöhung führt. NVISO dokumentierte dies in VMware Tools/Aria Operations Service Discovery als CVE-2025-41244.

  • Impact: Local privilege escalation to root (or to the privileged discovery account)
  • 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 führt Discovery-Skripte innerhalb des Guests über VMware Tools aus und verwendet konfigurierte privilegierte Anmeldeinformationen.
  • Credential-less (modern): Die Discovery-Logik läuft innerhalb von VMware Tools, bereits mit erhöhten Rechten im Guest.

Beide Modi führen letztlich Shell-Logik aus, die Prozesse mit listening sockets scannt, einen passenden Kommando-Pfad via regex extrahiert und das erste argv-Token mit einem version-Flag ausführt.

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

In open-vm-tools vergleicht das serviceDiscovery-Plugin-Skript get-versions.sh Kandidaten-Binaries mithilfe weit gefasster regulärer Ausdrücke und führt das erste Token ohne jegliche Prüfung des trusted-path aus:

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
}

Es wird mit permissiven Mustern aufgerufen, die \S (kein Leerzeichen) enthalten und problemlos mit Nicht-Systempfaden in von Benutzern beschreibbaren Orten übereinstimmen:

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
  • Extraktion verwendet grep -Eo und nimmt das erste Token: ${COMMAND%%[[:space:]]*}
  • Keine Whitelist/Allowlist vertrauenswürdiger Systempfade; jeder gefundene Listener mit passendem Namen wird mit -v/--version ausgeführt

Dies erzeugt ein untrusted search path execution primitive: beliebige Binärdateien, die sich in weltweit beschreibbaren Verzeichnissen befinden (z. B. /tmp/httpd), werden von einer privilegierten Komponente ausgeführt.

Ausnutzung (sowohl ohne Credentials als auch mit Credentials)

Voraussetzungen

  • Du kannst einen unprivilegierten Prozess ausführen, der auf dem Gast einen Listening-Socket öffnet.
  • Der discovery-Job ist aktiviert und läuft periodisch (historisch ~5 Minuten).

Schritte

  1. Platziere eine Binärdatei in einem Pfad, der einem der permissiven regexes entspricht, z. B. /tmp/httpd oder ./nginx
  2. Starte sie als niedrig privilegierter Benutzer und stelle sicher, dass sie einen Listening-Socket öffnet
  3. Warte auf den Discovery-Zyklus; der privilegierte Collector führt automatisch /tmp/httpd -v (oder Ähnliches) aus, wodurch dein Programm als root läuft

Minimale Demo (unter Verwendung von NVISO’s Ansatz)

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

Typische Prozessabfolge

  • 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

Artefakte (credential-based) Wiederhergestellte SDMP-Wrapper-Skripte unter /tmp/VMware-SDMP-Scripts-{UUID}/ können die direkte Ausführung des bösartigen Pfads zeigen:

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

Verallgemeinerung der Technik: regex-driven discovery abuse (portable pattern)

Viele Agents und Monitoring-Suites implementieren Version-/Service-Discovery durch:

  • Auflisten von Prozessen mit listening sockets
  • Greppen von argv/command lines mit permissiven regexes (z. B. Muster, die \S enthalten)
  • Ausführen des gefundenen Pfads mit einem harmlosen Flag wie -v, --version, -V, -h

Wenn das Regex untrusted Pfade akzeptiert und der Pfad aus einem privilegierten Kontext ausgeführt wird, erhält man CWE-426 Untrusted Search Path execution.

Missbrauchsrezept

  • Benenne deine Binary wie gängige Daemons, die das Regex wahrscheinlich matched: httpd, nginx, mysqld, dataserver
  • Platziere sie in einem beschreibbaren Verzeichnis: /tmp/httpd, ./nginx
  • Stelle sicher, dass sie dem Regex entspricht und irgendeinen Port öffnet, um enumeriert zu werden
  • Warte auf den geplanten Collector; du erhältst eine automatische privilegierte Invocation von -v

Anmerkung zur Verschleierung: Dies stimmt mit MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) überein, um die Trefferwahrscheinlichkeit und Tarnung zu erhöhen.

Wiederverwendbarer privilegierter I/O-Relay-Trick

  • Baue deinen Helper so, dass er bei privilegiertem Aufruf (-v/--version) eine Verbindung zu einem bekannten Rendezvous (z. B. einem Linux abstract UNIX socket wie @cve) herstellt und stdio zu /bin/sh -i bridged. Das vermeidet Artefakte auf der Festplatte und funktioniert in vielen Umgebungen, in denen dieselbe Binary mit einem Flag erneut aufgerufen wird.

Erkennung und DFIR-Anleitung

Hunting-Abfragen

  • Ungewöhnliche Children von vmtoolsd oder get-versions.sh wie /tmp/httpd, ./nginx, /tmp/mysqld
  • Jede Ausführung von non-system absolute paths durch Discovery-Skripte (achte auf spaces in ${COMMAND%%...} expansions)
  • ps -ef --forest zur Visualisierung von Ahnenbäumen: vmtoolsd -> get-versions.sh ->

Bei Aria SDMP (credential-based)

  • Untersuche /tmp/VMware-SDMP-Scripts-{UUID}/ nach transienten Skripten und stdout/stderr-Artefakten, die die Ausführung von Angreiferpfaden zeigen

Policy/Telemetrie

  • Alert, wenn privilegierte Collector aus non-system Präfixen ausgeführt werden: ^/(tmp|home|var/tmp|dev/shm)/
  • File integrity monitoring für get-versions.sh und VMware Tools plugins

Abhilfemaßnahmen

  • Patch: Apply Broadcom/VMware updates for CVE-2025-41244 (Tools and Aria Operations SDMP)
  • Disable or restrict credential-less discovery where feasible
  • Validate trusted paths: restrict execution to allowlisted directories (/usr/sbin, /usr/bin, /sbin, /bin) and only exact known binaries
  • Avoid permissive regexes with \S; prefer anchored, explicit absolute paths and exact command names
  • Drop privileges for discovery helpers where possible; sandbox (seccomp/AppArmor) to reduce impact
  • Monitor for and alert on vmtoolsd/get-versions.sh executing non-system paths

Hinweise für Verteidiger und Implementierer

Sichereres Matching- und Ausführungsmuster

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

Referenzen

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks