某云星空的前台反序列化和任意文件上传漏洞分析
字数 2430 2025-08-20 18:18:16
某云星空前台反序列化和任意文件上传漏洞分析
环境搭建
所需环境
- 操作系统:Windows Server 2012
- 软件版本:金蝶云星空 7.6
- 建议使用云服务器或纯净虚拟机进行搭建
调试工具
- dnSpy调试工具(推荐使用v6.1.8 win64版本)
- 下载地址:https://github.com/dnSpy/dnSpy/releases/tag/v6.1.8
调试环境配置
- 添加系统环境变量:
COMPLUS_ZapDisable = 1 - 调试IIS进程:
- 进入
C:\Windows\System32\inetsrv目录 - 执行
appcmd list wp查看应用程序池进程ID
- 进入
- 使用dnSpy附加进程:
- 打开dnSpy,选择"调试"->"附加到进程"
- 选择相应的进程ID并附加
- 在"调试"->"窗口"->"模块"中搜索要调试的程序集
- 双击程序集,在程序集资源管理器中找到要调试的类并打断点
反序列化漏洞分析
漏洞入口
- 源码位置:
C:\Program Files (x86)\Kingdee\K3Cloud\WebSite - web.config配置文件中,
.kdsvc后缀文件由KDServiceHandler处理- 处理类:
Kingdee.BOS.ServiceFacade.KDServiceFx.KDServiceHandler,Kingdee.BOS.ServiceFacade.KDServiceFx
- 处理类:
请求处理流程
KDServiceHandler返回KSDVHandler处理请求KSDVHandler在ProcessRequest方法中处理请求- 通过
Action类进入ProcessRequestInternal - 进入
ExecuteRequest方法 - 进入
StartRequest - 进入
BeginRequest方法处理会话session - 调用
RequestExcuteRuntime.pipeline.ExcuteRequest(kdserviceContext) - 最终调用
ExecuteServiceModule的OnProcess方法
关键点分析
1. GetServiceParameters()
requestExtractor在KDSVCHandler#ProcessRequest中通过Create()方法初始化- 将JSON body参数转换为key-value的form
- 如果
Content-Type: text/json,使用JQueryRequestExtractor转换 - 否则直接作为key-value的form
- 如果
参数获取方式:
- 如果POST参数中有
parameters,获取后变成JSON数组- Payload示例:
{"format": 3, "parameters": "[\"gadget\"]"}
- Payload示例:
- 否则参数可以为
pparams或ap0形式- Payload示例:
{"ap0":"gadget","format":"3"} - 或:
{"pparams":"gadget","format":"3"}
- Payload示例:
2. new SerializerProxy()
- 根据传入的
format选择对应的SerializerProxy(JSON或Binary) format=3对应BinaryFormatterProxy
3. this.executor.Execute()
- 调用相应的serializer进行反序列化
- 使用
BinaryFormatterProxy this.encoder.Decoding支持多种编码方式(Base64或Hex)
漏洞复现
使用ysoserial.net生成payload:
ysoserial.exe -o base64 -f BinaryFormatter -g ClaimsIdentity -c "cmd /c \"ping xxxx\""
补丁分析
补丁直接禁用了二进制序列化方式
任意文件上传漏洞分析
漏洞位置
- 处理类:
ScpSupRegHandler(继承IHttpHandler接口) - 配置文件位置:
\WebSite\App_Data\Common.config - 配置文件加载:通过
FileConfig.xml.deploy加载Common.config
漏洞分析流程
ScpSupRegHandler的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特性:
- 文件名中的
../可进行路径遍历 - Windows会删除文件名最后的点号
- 文件名中的
漏洞利用技巧
- 文件扩展名检查使用
Contains方法,空扩展名可绕过 - 利用Windows处理文件名时删除最后点号的特性
POC示例
POST /路径 HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxxxx
------WebKitFormBoundaryxxxx
Content-Disposition: form-data; name="FID"
任意值
------WebKitFormBoundaryxxxx
Content-Disposition: form-data; name="dbId_v"
任意值
------WebKitFormBoundaryxxxx
Content-Disposition: form-data; name="file"; filename="test.aspx."
Content-Type: application/octet-stream
恶意文件内容
------WebKitFormBoundaryxxxx--
总结
反序列化漏洞要点
- 路由通用性:只要能进入
KDSVCHandler的路由都可利用 - JSON参数格式灵活:
parameters、pparams或ap0均可 - 编码方式多样:支持Base64和Hex编码
- 请求格式:支持JSON格式和常规POST参数
文件上传漏洞要点
- 利用
Contains方法检查扩展名的缺陷 - 利用Windows处理文件名的特性
- 需要配合
FID和dbId_v参数
这两个漏洞的组合利用可以实现在目标系统上执行任意代码和上传恶意文件,危害性较高。