搭建环境
参考链接:https://www.heshuyun.com/265.html
环境:WindowsServer 2012 + 金蝶云星空 7.6
(建议自己用一个云服务器或者纯净的虚拟机)
如果利用dnSpy远程调试环境
https://github.com/dnSpy/dnSpy/releases/tag/v6.1.8 (这个漏洞复现是利用win64版本)
-
首先添加系统环境变量,COMPLUS_ZapDisable = 1
-
然后需要调试IIS进程,进入到
C:WindowsSystem32inetsrv
目录,利用cmd执行appcmd list wp
查看对应的应用程序池进程ID -
打开dnSpy,调试-->附加到进程-->选择相应的进程ID-->附加
-
调试-->窗口-->模块-->搜索要调试的程序集-->双击
-
在程序集资源管理器找到要调试的类打开,然后就可以打断点,发送payload进行调试
反序列化漏洞
开始
环境搭建起来后,有一个用户端和管理端,我们看website端
搭建起来的源码在C:Program Files (x86)KingdeeK3CloudWebSite
中
首先看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);
最后调用了ExecuteServiceModule
的OnProcess
方法
在这个方法中有三个比较重要的地方
重点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
对于接口的配置文件,是在WebSiteApp_DataCommon.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为空,字符串是肯定包含空的,从而实现绕过。
后面就是需要加个FID
和dbId_v
参数赋值
最后就是文件上传,然后利用文件名中的../
和windows的特性(会在文件上传时,对最后一个点会删除)
总结
对于这个漏洞学到的trick就是,在文件上传的时候,对于文件名后缀的匹配利用到Contains
,而当后缀为空时,依然可以绕过,同时利用到windows会处理掉最后的.
点号。
最后的POC
来源:【https://xz.aliyun.com/】
原文始发于微信公众号(衡阳信安):某云星空的前台反序列化和任意文件上传漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论