用友U8Cloud ServiceDispatcherServlet 反序列化漏洞分析与利用研究
1. 前言
用友U8 Cloud近期曝光了多个可链式利用的安全缺陷,其中ServiceDispatcherServlet的反序列化入口是核心攻击向量。攻击者可通过此漏洞组合实现"先获取执行权限,再落地webshell"的攻击链。本文将详细分析三种反序列化方式的原理、利用条件和实战方法。
2. 环境搭建要求
2.1 基础环境
- Java项目基于Maven构建
- JDK版本需与U8 Cloud匹配(建议使用较低版本)
- 准备U8 Cloud完整源码
2.2 依赖配置
- 收集U8 Cloud所有JAR包(fw.jar、commons系列、基础u8包等)
- 如不确定所需JAR,可全部导入项目
- 添加ysoserial JAR用于反序列化payload生成
3. 漏洞分析
3.1 漏洞背景
- 官方公告日期:2025-08-29
- 公告地址:https://security.yonyou.com/#/noticeInfo?id=720
- 漏洞本质:通过反序列化绕过鉴权机制,实现任意文件上传和系统破坏
3.2 请求处理流程分析
Client → POST /ServiceDispatcherServlet
→ 映射CommonServletDispatcher
→ doPost → doGet
→ serviceHandler.execCall(request, response)
→ ServiceDispatcher.execCall()
├─ 反序列化request输入流(NetObjectInputStream)
├─ 得到InvocationInfo(服务名、方法、参数)
├─ 执行目标方法
└─ 将Result对象序列化写回response
3.3 web.xml配置分析
ServiceDispatcherServlet的实际处理类为CommonServletDispatcher,初始化参数为ServiceDispatcher。CommonServletDispatcher仅作为外壳,核心处理逻辑在ServiceDispatcher中。
4. 三种反序列化方式详解
4.1 第一种:修复前的反序列化(需绕过token)
4.1.1 修复前状况
- 2025-04-03之前版本无token校验
- 直接反序列化NetObjectInputStream即可利用
4.1.2 数据格式要求
- 读取4字节长度前缀(对象数据长度)
- 根据长度读取字节数组
- 不符合格式会导致EOF异常
4.1.3 利用方法
- 构造恶意对象
- 使用NetObjectOutputStream写入对象
- 发送精心构造的请求
4.2 第二种:修复后的反序列化(带token验证)
4.2.1 token验证机制
- 从
/ierp/bin/token/trustIPList.conf读取IP列表 - 读取可信服务名
- 使用tokenseed配置生成token
4.2.2 token种子来源
- 文件中的tokenseed值:
ab7d823e-03ef-39c1-9947-060a0a08b931 - 文件不存在时的默认值:
232asfdsjkfmsdgldfg
4.2.3 token生成方式
invInfo.setToken(genToken(userCode));
其中userCode为#UAP#
4.2.4 完整利用流程
- 获取正确的token种子
- 生成合法token
- 构造包含token的InvocationInfo对象
- 执行反序列化攻击
4.2.5 EJB服务查找机制
- 使用自定义ServiceCache缓存对象
- 新模块先查询缓存,未命中则通过JNDI查找
- ServiceCache中的对象会创建EJB代理返回
4.3 第三种:IPFxxFileService反序列化
4.3.1 文件位置
.../modules/uapeai/META-INF/lib/uapeaipfxx.jar!/nc/bs/pfxx/pub/PFxxFileServiceImpl.class
4.3.2 可利用方法分析
writeDocToXMLFile方法
- 参数:byte[] filedata, String filePath
- 可直接写入文件
- 限制:文件后缀强制为.xml
writeInputStreamData方法
- 存在漏洞但利用有限
- 只能覆盖GZIP文件
- 实用性较低
writeMiddleFile方法
- 参数:byte[] filedata, String filePath, String fileName, String billId
- billId参数用途不确定,需要进一步研究
getHomeFileByte方法
- 将指定路径下的多个文件打包为ZIP返回
- 可用于文件读取/下载
4.3.3 writeDocToXMLFile利用细节
写入操作通过XMLUtil.printDOMTree(writer, newdoc, 0, "UTF-8")实现,需要构造byte[]和String类型参数。
4.4 第四种:C6链反序列化(无需token验证)
4.4.1 技术原理
直接通过NetObjectInputStream.readObject(bis, streamRet)重建InvocationInfo对象,在重建过程中执行类的反序列化回调(readObject/readResolve/动态代理初始化等)。
4.4.2 优势
- 完全绕过token验证
- 只需在参数中嵌入恶意对象即可
- 更直接有效
5. 各方式对比与利用特点
5.1 日志痕迹
- 第一、二种方式:只留下少量log,无明显异常信息
- 第三种方式:会产生报错日志,但留痕概率较低
5.2 回显问题
- 通过Tomcat链可实现回显
- 国外环境测试中回显不稳定(原因未明)
- 本地环境回显正常
6. 漏洞修复方案
6.1 官方修复措施
- 增强token验证机制
- 修改文件上传路径,避免文件落地到项目目录
- 加强输入验证和过滤
6.2 修复参考
详细修复方案参考:https://security.yonyou.com/#/home
7. 测试工具与资源
7.1 项目地址
https://github.com/sudo-Yangziran/U8-POC-Study
7.2 使用说明
- 修改测试方式适应实际环境
- 根据研究思路扩展测试用例
- 严格遵守授权测试原则
8. 免责声明
本文内容仅用于技术研究与防御,请勿用于非法用途。使用者需获得目标系统授权并在安全环境进行测试。滥用本文信息产生的后果由使用者自负,与作者无关。
注意:本文提供的Hex编码payload仅用于测试,使用一次后会自动删除,仅限于本机测试使用,不得用于实际攻击。