daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md (10082B)


      1 ---
      2 title: "VMware Tools service discovery LPE (CWE-426) via regex-based binary discovery (CVE-2025-41244)"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/main-system-information/kernel-lpe-cves/vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/main-system-information/kernel-lpe-cves/vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # VMware Tools service discovery LPE (CWE-426) via regex-based binary discovery (CVE-2025-41244)
     14 
     15 This technique abuses regex-driven service discovery pipelines that parse running process command lines to infer service versions and then execute a candidate binary with a "version" flag. When permissive patterns accept untrusted, attacker-controlled paths (e.g., /tmp/httpd), the privileged collector executes an arbitrary binary from an untrusted location, yielding local privilege escalation. NVISO documented this in VMware Tools/Aria Operations Service Discovery as CVE-2025-41244.<sup>[[1]](#references)[[2]](#references)</sup>
     16 
     17 - Impact: Local privilege escalation to root (or to the privileged discovery account).<sup>[[1]](#references)[[2]](#references)</sup>
     18 - Root cause: Untrusted Search Path (CWE-426) + permissive regex matching of process command lines.<sup>[[1]](#references)[[3]](#references)[[5]](#references)</sup>
     19 - Affected: open-vm-tools/VMware Tools on Linux (credential-less discovery), VMware Aria Operations SDMP (credential-based discovery via Tools/proxy).<sup>[[1]](#references)[[2]](#references)</sup>
     20 
     21 ## How VMware service discovery works (high level)
     22 
     23 - Credential-based (legacy): Aria executes discovery scripts inside the guest via VMware Tools using configured privileged credentials.<sup>[[1]](#references)</sup>
     24 - Credential-less (modern): Discovery logic runs within VMware Tools, already privileged in the guest.<sup>[[1]](#references)</sup>
     25 
     26 Both modes ultimately run shell logic that scans processes with listening sockets, extracts a matching command path via a regex, and executes the first argv token with a version flag.<sup>[[1]](#references)[[3]](#references)</sup>
     27 
     28 ## Root cause and vulnerable pattern (open-vm-tools)
     29 
     30 In open-vm-tools, the serviceDiscovery plugin script get-versions.sh matches candidate binaries using broad regular expressions and executes the first token without any trusted-path validation.<sup>[[1]](#references)[[3]](#references)</sup>
     31 
     32 ```bash
     33 get_version() {
     34   PATTERN=$1
     35   VERSION_OPTION=$2
     36   for p in $space_separated_pids
     37   do
     38     COMMAND=$(get_command_line $p | grep -Eo "$PATTERN")
     39     [ ! -z "$COMMAND" ] && echo VERSIONSTART "$p" "$("${COMMAND%%[[:space:]]*}" $VERSION_OPTION 2>&1)" VERSIONEND
     40   done
     41 }
     42 ```
     43 
     44 It is invoked with permissive patterns containing \S (non-whitespace) that will happily match non-system paths in user-writable locations.<sup>[[1]](#references)[[3]](#references)</sup>
     45 
     46 ```bash
     47 get_version "/\S+/(httpd-prefork|httpd|httpd2-prefork)($|\s)" -v
     48 get_version "/usr/(bin|sbin)/apache\S*" -v
     49 get_version "/\S+/mysqld($|\s)" -V
     50 get_version "\.?/\S*nginx($|\s)" -v
     51 get_version "/\S+/srm/bin/vmware-dr($|\s)" --version
     52 get_version "/\S+/dataserver($|\s)" -v
     53 ```
     54 
     55 - Extraction uses grep -Eo and takes the first token: ${COMMAND%%[[:space:]]*}.<sup>[[1]](#references)[[3]](#references)</sup>
     56 - No whitelist/allowlist of trusted system paths; any discovered listener with a matching name is executed with -v/--version.<sup>[[1]](#references)[[3]](#references)</sup>
     57 
     58 This creates an untrusted search path execution primitive: arbitrary binaries located in world-writable directories (e.g., /tmp/httpd) get executed by a privileged component.<sup>[[1]](#references)</sup>
     59 
     60 ## Exploitation (both credential-less and credential-based modes)
     61 
     62 Preconditions
     63 - You can run an unprivileged process that opens a listening socket on the guest.<sup>[[1]](#references)</sup>
     64 - The discovery job is enabled and runs periodically (historically ~5 minutes).<sup>[[1]](#references)</sup>
     65 
     66 Steps
     67 1) Stage a binary in a path matching one of the permissive regexes, e.g. /tmp/httpd or ./nginx.<sup>[[1]](#references)</sup>
     68 2) Run it as a low-privileged user and ensure it opens any listening socket.<sup>[[1]](#references)</sup>
     69 3) Wait for the discovery cycle; the privileged collector will automatically execute: /tmp/httpd -v (or similar), running your program as root.<sup>[[1]](#references)</sup>
     70 
     71 Minimal demo (using NVISO’s approach).<sup>[[1]](#references)</sup>
     72 ```bash
     73 # Build any small helper that:
     74 #  - default mode: opens a dummy TCP listener
     75 #  - when called with -v/--version: performs the privileged action (e.g., connect to an abstract UNIX socket and spawn /bin/sh -i)
     76 # Example staging and trigger
     77 cp your_helper /tmp/httpd
     78 chmod +x /tmp/httpd
     79 /tmp/httpd          # run as low-priv user and wait for the cycle
     80 # After the next cycle, expect a root shell or your privileged action
     81 ```
     82 
     83 Typical process lineage.<sup>[[1]](#references)</sup>
     84 - Credential-based: /usr/bin/vmtoolsd -> /bin/sh /tmp/VMware-SDMP-Scripts-.../script_...sh -> /tmp/httpd -v -> /bin/sh -i
     85 - Credential-less: /bin/sh .../get-versions.sh -> /tmp/httpd -v -> /bin/sh -i
     86 
     87 Artifacts (credential-based)
     88 Recovered SDMP wrapper scripts under /tmp/VMware-SDMP-Scripts-{UUID}/ may show direct execution of the rogue path.<sup>[[1]](#references)</sup>
     89 ```bash
     90 /tmp/httpd -v >"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stdout" 2>"/tmp/VMware-SDMP-Scripts-{UUID}/script_-{ID}_0.stderr"
     91 ```
     92 
     93 ## Generalizing the technique: regex-driven discovery abuse (portable pattern)
     94 
     95 Many agents and monitoring suites implement version/service discovery by:
     96 - Enumerating processes with listening sockets
     97 - Grepping argv/command lines with permissive regexes (e.g., patterns containing \S)
     98 - Executing the matched path with a benign flag like -v, --version, -V, -h
     99 
    100 If the regex accepts untrusted paths and the path is executed from a privileged context, you get CWE-426 Untrusted Search Path execution.<sup>[[5]](#references)</sup>
    101 
    102 Abuse recipe for these patterns.<sup>[[1]](#references)</sup>
    103 - Name your binary like common daemons that the regex is likely to match: httpd, nginx, mysqld, dataserver
    104 - Place it in a writable directory: /tmp/httpd, ./nginx
    105 - Ensure it matches the regex and opens any port to be enumerated
    106 - Wait for the scheduled collector; you get an automatic privileged invocation of <path> -v
    107 
    108 Masquerading note: This aligns with MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) to increase match probability and stealth.<sup>[[4]](#references)</sup>
    109 
    110 Reusable privileged I/O relay trick
    111 - Build your helper so that on privileged invocation (-v/--version) it connects to a known rendezvous (e.g., a Linux abstract UNIX socket like @cve) and bridges stdio to /bin/sh -i. This avoids on-disk artifacts and works across many environments where the same binary is re-invoked with a flag.<sup>[[1]](#references)</sup>
    112 
    113 ## Detection and DFIR guidance
    114 
    115 Hunting queries
    116 - Uncommon children of vmtoolsd or get-versions.sh such as /tmp/httpd, ./nginx, /tmp/mysqld.<sup>[[1]](#references)</sup>
    117 - Any execution of non-system absolute paths by discovery scripts (look for spaces in ${COMMAND%%...} expansions).<sup>[[1]](#references)[[3]](#references)</sup>
    118 - ps -ef --forest to visualize ancestry trees: vmtoolsd -> get-versions.sh -> <non-system path>.<sup>[[1]](#references)</sup>
    119 
    120 On Aria SDMP (credential-based)
    121 - Inspect /tmp/VMware-SDMP-Scripts-{UUID}/ for transient scripts and stdout/stderr artifacts showing execution of attacker paths.<sup>[[1]](#references)</sup>
    122 
    123 Policy/telemetry
    124 - Alert when privileged collectors execute from non-system prefixes: ^/(tmp|home|var/tmp|dev/shm)/
    125 - File integrity monitoring on get-versions.sh and VMware Tools plugins
    126 
    127 ## Mitigations
    128 
    129 - Patch: Apply Broadcom/VMware updates for CVE-2025-41244 (Tools and Aria Operations SDMP).<sup>[[2]](#references)</sup>
    130 - Disable or restrict credential-less discovery where feasible.<sup>[[1]](#references)</sup>
    131 - Validate trusted paths: restrict execution to allowlisted directories (/usr/sbin, /usr/bin, /sbin, /bin) and only exact known binaries
    132 - Avoid permissive regexes with \S; prefer anchored, explicit absolute paths and exact command names.<sup>[[1]](#references)[[3]](#references)</sup>
    133 - Drop privileges for discovery helpers where possible; sandbox (seccomp/AppArmor) to reduce impact
    134 - Monitor for and alert on vmtoolsd/get-versions.sh executing non-system paths.<sup>[[1]](#references)[[3]](#references)</sup>
    135 
    136 ## Notes for defenders and implementers
    137 
    138 Safer matching and execution pattern
    139 ```bash
    140 # Bad: permissive regex and blind exec
    141 COMMAND=$(get_command_line "$pid" | grep -Eo "/\\S+/nginx(\$|\\s)")
    142 [ -n "$COMMAND" ] && "${COMMAND%%[[:space:]]*}" -v
    143 
    144 # Good: strict allowlist + path checks
    145 candidate=$(get_command_line "$pid" | awk '{print $1}')
    146 case "$candidate" in
    147   /usr/sbin/nginx|/usr/sbin/httpd|/usr/sbin/apache2)
    148       "$candidate" -v 2>&1 ;;
    149   *)
    150       : # ignore non-allowlisted paths
    151       ;;
    152 esac
    153 ```
    154 
    155 ## References
    156 
    157 - [1] [NVISO – You name it, VMware elevates it (CVE-2025-41244)](https://blog.nviso.eu/2025/09/29/you-name-it-vmware-elevates-it-cve-2025-41244/)
    158 - [2] [VMSA-2025-0015.1 – VMware Aria Operations and VMware Tools updates address multiple vulnerabilities (CVE-2025-41244, CVE-2025-41245, CVE-2025-41246) (Broadcom)](https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/36149)
    159 - [3] [open-vm-tools – serviceDiscovery/get-versions.sh (stable-13.0.0)](https://github.com/vmware/open-vm-tools/blob/stable-13.0.0/open-vm-tools/services/plugins/serviceDiscovery/get-versions.sh)
    160 - [4] [MITRE ATT&CK T1036.005 – Match Legitimate Name or Location](https://attack.mitre.org/techniques/T1036/005/)
    161 - [5] [CWE-426: Untrusted Search Path](https://cwe.mitre.org/data/definitions/426.html)