0x00、前言
用友nc(NCMessageServlet)反序列化漏洞复现与分析,同样也是InvokerServlet引发的问题,调用的Servlet类变成NCMessageServlet类,也是直接实现反序列化,分析内容不多,当做审计过程记录。
0x01、漏洞描述
用友 NC 系统InvokerServlet调用NCMessageServlet过程中存在反序列化漏洞,远程未授权攻击者可向目标服务器发送恶意请求包,最终实现任意代码执行。
0x02、漏洞范围
NC version <= 6.5
0x03、环境搭建
用友NC 6.5安装包网盘下载的,安全性未知,就不贴地址了。
安装步骤可以参考:
https://xz.aliyun.com/t/8242
https://blog.csdn.net/m0_53100713/article/details/130056482
https://www.rstk.cn/news/881081.html?action=onClick


过程没太多的注意点,主要是尽量使用jdk1.7启动服务,高版本jdk启动容易出现问题
运行安装home目录下startServer.bat启动服务器即可


0x04、漏洞复现
这里用CC6链进行复现

0x05、原理分析
同样还是NCInvokerServlet

访问/service/和/servlet/目录下即可访问NCInvokerServlet

跟进nc.bs.framework.server.InvokerServlet,get/post都会调用doAction方法,doAction前半段获取token、userCode不重要,用不到这些字段。

直接看下面部分,这里对Path路径有个取值逻辑
若path以/~开头,则取值/~后的字符串,若该字符串存在/符号,则/前面的字符串赋值给module,/符号后面的字符赋值给serviceName,例如path路径为/~modulename/servicename,则modulename赋值给module,servicename赋值给serviceName

获取到模块module和服务名serviceName过后,调用getServiceObject方法获取服务对象

getServiceObject方法开始判断moduleName是否为空,由于存在,因此进入else判断体

从serviceObjMap常量中获取moduleName:serviceName,由于并未添加该内容,因此此时返回给的retObject为null

接着获取模块moduleName的容器Container,为了后面的jndi调用


获取到容器后,再获取上下文器然后进行jndi调用,查询对象为serviceName,如果serviceName对象在jndi注册对象中不存在,则会抛出异常进入catch代码段,这里直接获取容器的类加载器,直接类加载serviceName,然后newInstance()实例化,因此找到module下存在实现反序列化功能的serviceName类,即可实例化触发反序列化漏洞

因此该漏洞找到了baseapp模块下的nc.message.bs.NCMessageServlet类

实例化时调用父类的doAction方法,从而调用子类nc.message.bs.NCMessageServlet的doAction方法

该类很直接,直接获取序列化输入流然后直接反序列化触发漏洞

因此直接向该类发送序列化数据,即可直接反序列化触发漏洞

0x06、漏洞修复
官方以发布修复补丁:
https://security.yonyou.com/#/noticeInfo?id=293