12 KiB
VMware Tools service discovery LPE (CWE-426) via regex-based binary discovery (CVE-2025-41244)
{{#include ../../banners/hacktricks-training.md}}
यह तकनीक उन regex-driven service discovery पाइपलाइनों का दुरुपयोग करती है जो चल रहे process command lines को पार्स करके service versions का अनुमान लगाती हैं और फिर एक candidate binary को "version" फ़्लैग के साथ execute करती हैं। जब permissive patterns untrusted, attacker-controlled paths (उदाहरण के लिए /tmp/httpd) स्वीकार करते हैं, तो privileged collector untrusted location से arbitrary binary को execute कर देता है, जिससे local privilege escalation होता है। NVISO ने इसे VMware Tools/Aria Operations Service Discovery में 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)
VMware service discovery कैसे काम करता है (उच्च स्तर पर)
- Credential-based (legacy): Aria configured privileged credentials का उपयोग करके VMware Tools के माध्यम से guest के अंदर discovery scripts को execute करता है।
- Credential-less (modern): Discovery logic VMware Tools के भीतर चलता है, जो पहले से ही guest में privileged होता है।
दोनों मोड अंततः shell logic चलाते हैं जो listening sockets वाले processes को scan करता है, regex के जरिए matching command path निकालता है, और first argv token को version flag के साथ execute करता है।
मूल कारण और असुरक्षित पैटर्न (open-vm-tools)
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:
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 (नॉन-व्हाइटस्पेस) शामिल होता है, जो उपयोगकर्ता-लिखने योग्य स्थानों में गैर-सिस्टम पथों से आसानी से मेल खा लेगा:
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
- एक्सट्रैक्शन grep -Eo का उपयोग करता है और पहला टोकन लेता है: ${COMMAND%%:space:*}
- No whitelist/allowlist of trusted system paths; any discovered listener with a matching name is executed with -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.
Exploitation (both credential-less and credential-based modes)
Preconditions
- आप एक unprivileged process चला सकते हैं जो guest पर listening socket खोलता है।
- discovery job सक्षम है और periodically चलता है (इतिहास में ~5 मिनट)।
Steps
- permissive regexes में से किसी एक से मेल खाने वाले पाथ में binary stage करें, उदाहरण के लिए /tmp/httpd या ./nginx
- इसे low-privileged user के रूप में चलाएँ और सुनिश्चित करें कि यह कोई भी listening socket खोलता है
- discovery cycle की प्रतीक्षा करें; privileged collector स्वतः execute करेगा: /tmp/httpd -v (या समान), जिससे आपका प्रोग्राम root के रूप में चलेगा
Minimal demo (using NVISO’s approach)
# 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
सामान्य प्रोसेस वंशावली
- क्रेडेंशियल-आधारित: /usr/bin/vmtoolsd -> /bin/sh /tmp/VMware-SDMP-Scripts-.../script_...sh -> /tmp/httpd -v -> /bin/sh -i
- क्रेडेंशियल-रहित: /bin/sh .../get-versions.sh -> /tmp/httpd -v -> /bin/sh -i
आर्टिफैक्ट्स (क्रेडेंशियल-आधारित) /tmp/VMware-SDMP-Scripts-{UUID}/ के अंतर्गत पुनःप्राप्त SDMP wrapper स्क्रिप्ट्स में rogue path का सीधे निष्पादन दिख सकता है:
/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)
कई agents और monitoring suites version/service discovery को इस तरह लागू करते हैं:
- Listening sockets के साथ processes की enumeration
- argv/command lines को permissive regexes से grep करना (उदा., patterns जिनमें \S शामिल हो)
- मेल खाए हुए path को benign flag जैसे -v, --version, -V, -h के साथ execute करना
यदि regex untrusted paths को स्वीकार करता है और path privileged context से execute होता है, तो आपको CWE-426 Untrusted Search Path execution मिलता है।
दुरुपयोग नुस्खा
- अपने binary का नाम ऐसे रखें जैसे सामान्य daemons जिनसे regex मिल सकता है: httpd, nginx, mysqld, dataserver
- इसे writable directory में रखें: /tmp/httpd, ./nginx
- सुनिश्चित करें कि यह regex से मेल खाता है और किसी भी port को खोलता है ताकि उसे enumerate किया जा सके
- शेड्यूल किए गए collector का इंतजार करें; आपको -v का automatic privileged invocation मिल जाएगा
Masquerading note: यह MITRE ATT&CK T1036.005 (Match Legitimate Name or Location) के अनुरूप है, जिससे match probability और stealth बढ़ती है।
Reusable privileged I/O relay trick
- अपने helper को इस तरह बनाएं कि privileged invocation (-v/--version) पर यह किसी ज्ञात rendezvous (उदा., a Linux abstract UNIX socket जैसे @cve) से connect करे और stdio को /bin/sh -i से bridge कर दे। यह on-disk artifacts को रोकता है और कई environments में काम करता है जहाँ वही binary flag के साथ फिर से invoke किया जाता है।
Detection and DFIR guidance
Hunting queries
- vmtoolsd या get-versions.sh के असामान्य children जैसे /tmp/httpd, ./nginx, /tmp/mysqld
- discovery scripts द्वारा non-system absolute paths का कोई भी execution ( ${COMMAND%%...} expansions में spaces के लिए देखें)
- ps -ef --forest से ancestry trees visualize करें: vmtoolsd -> get-versions.sh ->
On Aria SDMP (credential-based)
- /tmp/VMware-SDMP-Scripts-{UUID}/ की जांच करें transient scripts और stdout/stderr artifacts के लिए जो attacker paths के execution को दिखाते हैं
Policy/telemetry
- जब privileged collectors non-system prefixes से execute करें तो alert करें: ^/(tmp|home|var/tmp|dev/shm)/
- get-versions.sh और VMware Tools plugins पर file integrity monitoring रखें
Mitigations
- Patch: CVE-2025-41244 (Tools and Aria Operations SDMP) के लिए Broadcom/VMware updates लागू करें
- जहाँ संभव हो credential-less discovery को disable या restrict करें
- Trusted paths को validate करें: execution को allowlisted directories (/usr/sbin, /usr/bin, /sbin, /bin) तक सीमित करें और केवल exact known binaries की अनुमति दें
- \S जैसे permissive regexes से बचें; anchored, स्पष्ट absolute paths और exact command names को प्राथमिकता दें
- जहाँ संभव हो discovery helpers के privileges घटाएँ; प्रभाव कम करने के लिए sandbox (seccomp/AppArmor) का उपयोग करें
- vmtoolsd/get-versions.sh द्वारा non-system paths के execute होने पर मॉनिटर और अलर्ट करें
रक्षा और लागू करने वालों के लिए नोट्स
बेहतर matching और execution पैटर्न
# 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
संदर्भ
- NVISO – You name it, VMware elevates it (CVE-2025-41244)
- Broadcom advisory for CVE-2025-41244
- open-vm-tools – serviceDiscovery/get-versions.sh (stable-13.0.0)
- MITRE ATT&CK T1036.005 – Match Legitimate Name or Location
- CWE-426: Untrusted Search Path
{{#include ../../banners/hacktricks-training.md}}