参考链接:https://www.heshuyun.com/265.html
环境:WindowsServer 2012 + 金蝶云星空 7.6
(建议自己用一个云服务器或者纯净的虚拟机)
https://github.com/dnSpy/dnSpy/releases/tag/v6.1.8 (这个漏洞复现是利用win64版本)
C:\Windows\System32\inetsrv
目录,利用cmd执行appcmd list wp
查看对应的应用程序池进程ID环境搭建起来后,有一个用户端和管理端,我们看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);
最后调用了ExecuteServiceModule
的OnProcess
方法
在这个方法中有三个比较重要的地方
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"}
根据我们传的format,然后选择对应的SerializerProxy(JSON or Binary)
因为我们传入的format是3,所以直接跟Binary
匹配到,利用的是BinaryFormatterPorxy
调用相应的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为空,字符串是肯定包含空的,从而实现绕过。
后面就是需要加个FID
和dbId_v
参数赋值
最后就是文件上传,然后利用文件名中的../
和windows的特性(会在文件上传时,对最后一个点会删除)
对于这个漏洞学到的trick就是,在文件上传的时候,对于文件名后缀的匹配利用到Contains
,而当后缀为空时,依然可以绕过,同时利用到windows会处理掉最后的.
点号。