环境配置
l 系统:Winserver2008R2
l 数据库:Oracle11G
l JDK:java 1.7.0_51
l 复现版本:用友NC6.5
源码分析
Jar包所在目录为:yonyou/modules/uapfw/META-INF/lib/uapfw_jsframeworkLevel-1.jar;
接口对应的路径为:
/nc/bs/framework/js/servlet/InternalJsInvokeServlet.class,接口页面方法代码如下图所示:
对request调用
CommandFactory.getCommand()方法,
并把结果赋值给ICommand对象cmd,如果cmd不为null,则执行它的execute()方法。
先看CommandFactory.getCommand()方法的具体代码实现如下:
使用自定义的readJSONString()方法对request的数据进行序列化,然后根据获取“action”参数值进入不同if分支。我们这里进入“invoke”的分支,并使用data创建InvokeCommand对象来进行一个赋值。最后返回cmd。
回到InternalJsInvokeServlet.class如下图:
接收到的cmd不为null,进入if语句,
执行cmd.execute()方法,该方法详细代码如下:
新建一个GsonBuilder对象并调用其create()创建Gson对象,
通过g.fromJson()方法
把this.data数据进行反序列化并转换为MethodInvocation类型。
i.getMethod()获取我们要用的方法;
m.getGenericParameterTypes()获取方法传入的参数类型;
m.getGenericReturnType()获取方法返回的结果类型;
继续往下看:
对我们要调用的方法invocation
使用handler.handleMethodInvocation()句柄处理。追踪进去看看:
查找invocation的 ServiceName并赋值给stub,
且如果不为null就调用invocation.invoke()方法来激活我们要使用的方法,跟进去看看:
通过.getClass()反射的方式获取Method后,激活我们需要使用的方法。
我们需要调用的方法代码如下图所示:
从ResourceManager资源管理器中获取我们的文件,显然不存在,所以下面根据传入的参数值进行文件创建。
第93行代码:创建FileOutputStream文件输出流以覆盖的方式将数据写到file,创建“UTF-8”编码器的OutputStreamWriter,将XML声明写入文件。使用getXStream().toXML()方法将“config”转换为xml格式并写入到文件file。
分析过程中,没有看到有对我们的data进行过滤处理,以及saveXStreamConfig()方法中对文件上传的内容以及文件名没有做任何限制,因此通过这个漏洞点实现在任意目录下写入任意内容的文件。
因为文件会写入XML声明,所以可以在该文件内构造:能通过反射获取Interpreter实例化eval方法去执行系统函数,然后在访问该文件的时候传入系统函数,即可导致REC。
漏洞验证
构造任意文件上传的数据包如下图所示:
发送数据包,即可在系统路径下看到该文件如下图所示:
构造REC的数据包如下图所示:
发送数据包,即可在系统中弹出的计算器如下图所示:
公众号:
刑天攻防实验室
扫码关注 了解更多内容
原文始发于微信公众号(刑天攻防实验室):用友NC6.5 uapjs 任意文件上传&RCE漏洞分析及复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论