某云星空的前台反序列化和任意文件上传漏洞分析
2023-11-20 16:47:56 Author: xz.aliyun.com(查看原文) 阅读量:15 收藏

搭建环境

参考链接:https://www.heshuyun.com/265.html

环境:WindowsServer 2012 + 金蝶云星空 7.6

(建议自己用一个云服务器或者纯净的虚拟机)

如果利用dnSpy远程调试环境

https://github.com/dnSpy/dnSpy/releases/tag/v6.1.8 (这个漏洞复现是利用win64版本)

  1. 首先添加系统环境变量,COMPLUS_ZapDisable = 1
  2. 然后需要调试IIS进程,进入到C:\Windows\System32\inetsrv目录,利用cmd执行appcmd list wp 查看对应的应用程序池进程ID
  3. 打开dnSpy,调试-->附加到进程-->选择相应的进程ID-->附加
  4. 调试-->窗口-->模块-->搜索要调试的程序集-->双击
  5. 在程序集资源管理器找到要调试的类打开,然后就可以打断点,发送payload进行调试

反序列化漏洞

开始

环境搭建起来后,有一个用户端和管理端,我们看website端

搭建起来的源码在C:\Program Files (x86)\Kingdee\K3Cloud\WebSite

首先看web.config配置文件,发现对于我们.kdsvc后缀的文件我们是通过KDServiceHandler处理的

Kingdee.BOS.ServiceFacade.KDServiceFx.KDServiceHandler,Kingdee.BOS.ServiceFacade.KDServiceFx

对于这个handler就很类似于Spring中的controller,直接去处理我们的请求

KDServiceHandler中,返回了一个KSDVHandler,所以就是KSDVHandler去处理的

而在KSDVHandler是在ProcessRequest方法中处理

通过一个Action类进入ProcessRequestInternal,然后再进入ExecuteRequest方法

进入StartRequest

进入BeginRquest方法中,会先处理一些会话session的问题

继续进入RequestExcuteRuntime.pipeline.ExcuteRequest(kdserviceContext);

最后调用了ExecuteServiceModuleOnProcess方法

在这个方法中有三个比较重要的地方

重点1--GetServiceParameters()

string[] serviceParameters = requestExtractor.GetServiceParameters((from **p** in kdservice.MapToMethod.GetParameters()

this.form: 在KDSVCHandler#ProcessRequest 中通过Create()方法,对 requestExtractor 进行了初始化,会将JSON body里面的参数变成一个key-value的form,如果Content-Type:text/json就会调用 JQueryRequestExtractor 将参数变成 form。如果不是JSON的格式,就直接是一个key-value的form

1.如果在我们的POST参数中有parameters,获取到后变成JSON数组,然后将数组里的值给Array返回回去。

所以在payload中,如果是含有parameters,就直接是"parameters": "[\"gadget\"]"的形式(字符串里有个数组形式)

{"format": 3,  "parameters": "[\"gadget\"]"}

2.如果我们走else,参数就可以为pparams(不固定的)或者ap0的形式

{"ap0":"gadget","format":"3"}
{"pparams":"gadget","format":"3"}

重点2-- new SerializerProxy()

根据我们传的format,然后选择对应的SerializerProxy(JSON or Binary)

因为我们传入的format是3,所以直接跟Binary匹配到,利用的是BinaryFormatterPorxy

重点3--this.executor.Execute()

调用相应的serializer进行反序列化

调用了BinaryFormatterProxy。

对于this.encoder.Decoding就会根据对应的编码进行解析。所以在payload中,不仅可以利用Base64进行编码,我们还可以利用Hex进行编码

最后

对于整个的payload,一是我们的路由很多都可以通用的,只要可以进KDSVCHandler这个handler;二是和整体的JSON参数key可以有几种形式,但是format是必需的;三是payload的加密的方式,这个不仅可以利用JSON格式传入还可以直接是常规POST参数传入。

漏洞复现

直接利用ysoserial.net生成payload

ysoserial.exe -o base64 -f BinaryFormatter -g ClaimsIdentity -c "cmd /c \"ping xxxx\""

补丁

直接是把二进制序列化的形式给ban了

任意文件上传漏洞

分析

问题出现在ScpSupRegHandler
对于接口的配置文件,是在\WebSite\App_Data\Common.config

配置文件怎么去加载获取的,往上走

FileConfig.xml.deploy,部署时加载了这个Common.config

利用DnSpy反编译后,查看ScpSupRegHandler

ScpSupRegHandler是继承了IHttpHandler接口的,所以默认处理路由的方法是ProcessRequest

如果有方法是POST,且是文件上传的格式,进入到SavaAttach方法中

SavaAttach方法中,

context.Request.Files[0] 获取 HTTP 请求中的文件集合,并选择第一个文件

Path.GetExtension(httpPostedFile.FileName)获取到文件名的扩展名,然后替代.为空,再变成小写

如果是,test.aspx.txt,取到的扩展名是.txt,说明是取最后一个点后面的内容

那如果是test.aspx.,取到的扩展名就是.,替代后就是空

对于"abc".Contains(value),value为空,字符串是肯定包含空的,从而实现绕过。

后面就是需要加个FIDdbId_v参数赋值

最后就是文件上传,然后利用文件名中的../和windows的特性(会在文件上传时,对最后一个点会删除)

总结

对于这个漏洞学到的trick就是,在文件上传的时候,对于文件名后缀的匹配利用到Contains,而当后缀为空时,依然可以绕过,同时利用到windows会处理掉最后的.点号。

最后的POC


文章来源: https://xz.aliyun.com/t/13079
如有侵权请联系:admin#unsafe.sh