用友NC(NCMessageServlet)反序列化漏洞原理分析
2023-06-07 12:00:00

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.InvokerServletget/post都会调用doAction方法,doAction前半段获取tokenuserCode不重要,用不到这些字段。

直接看下面部分,这里对Path路径有个取值逻辑

path/~开头,则取值/~后的字符串,若该字符串存在/符号,则/前面的字符串赋值给module/符号后面的字符赋值给serviceName,例如path路径为/~modulename/servicename,则modulename赋值给moduleservicename赋值给serviceName

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

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

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

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


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

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

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

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

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

0x06、漏洞修复

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

0x07、参考链接

https://nox.qianxin.com/article/590