Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

可領全套安全課程、配套攻防靶場


Tomcat-Ajp漏洞:一步步調試寫出POC的歷程


前言


晚上,朋友圈有人發了篇tomcat-ajp漏洞的通告和一個簡要分析的文章,也是當時唯一的參考文章,本著“好好學習、天天向上”的態度,作為小白,就想試著分析下,看看能不能寫出poc。


所以本文主要講述一個小白(當然也不能太白,java至少要會吧,網站要知道是啥吧)如何一步步調試分析,編寫poc的過程。


一.漏洞介紹


簡單來說就是apache tomcat服務器的8009端口上的ajp協議存在漏洞,導致未授權用戶可以讀網站目錄下的任意文件。


漏洞編號:

CNVD-2020-10487/CVE-2020-1938

受影響版本:

ApacheTomcat 9.x < 9.0.31

ApacheTomcat 8.x < 8.5.51

ApacheTomcat 7.x < 7.0.100

ApacheTomcat 6.x

二.調試環境搭建


為了觀察數據流向、編寫poc,我們需要搭建調試環境。


tomcat是開源項目,所以我首先想的是下載源碼,在源碼基礎上調試,這裡我下載的版本是9.0.2的代碼。調試器選擇的是Idea。


我先在網上搜索了下idea 調試 tomcat源碼的文章。最後參考了

https://blog.csdn.net/weixin_30631587/article/details/96528373

這篇文章,將pom.xml中tomcat的版本由9.0.14修改成9.0.2。,不過這裡我覺得不改也不會影響結果。


成功運行tomcat服務。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程


三.ajp協議學習


到目前為止,我還不知道什麼是ajp協議,這個協議是幹啥的,但是既然知道此次tomcat漏洞是ajp協議造成的。


我們肯定要去了解下這個協議是什麼。


Apache官方有說明文檔

http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html

當然這個文檔一眼看上去,是不太容易理解的,於是百度一番

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

我理解的是,我們要訪問tomcat網站有兩種方式,一種是通過瀏覽器直接輸入url地址。


另外一種就是通過ajp協議訪問。


AJP協議是定向包(面向包)協議,採用二進制形式代替文本形式,以提高性能。


所以我們需要寫個ajp的客戶端程序用來與tomcat服務器的8009端口進行數據交互。


當然我們可以自己從頭寫一個ajp客戶端,前提是我們需要很詳細瞭解ajp協議及其各個字段含義。


我並不打算如此,畢竟自己從頭寫起來還是很費勁的。


我先到github上用關鍵詞ajp和ajp client搜了一下,看來白的人運氣不會太差,發現已經有別人的ajp-client項目。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程


我把三個ajp-client都下了下來,經過測試和對比(邊調試邊測試),最後使用了


https://github.com/espenhw/ajp-client


這個項目,最後poc也是在這個項目上完成的。

這裡我們需要說下ajp協議中比較重要的字段。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

Forward Request包就是我們要發送給tomcat 8009端口的內容,用來觸發漏洞的。


該字段中比較重要的字段是attributes,後面調試跟蹤的時候,也會發現的,後面再說。


四.調試跟蹤


通過參考我們知道,tomcat在接收ajp請求的時候調用org.apache.coyote.ajp.AjpProcessor來處理ajp消息


prepareRequest將ajp裡面的內容取出來設置成request對象的Attribute屬性。


我們現在AjpProcessor中定位到prepareRequest()函數,並在函數開始出下上斷點,在request.setAttribute(n, v )也下上斷點。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

編寫測試代碼如下(test_servlet是我自己編寫的servlet代碼,放在了webapps目錄下):

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

運行程序,程序成功斷在了prepareRequest(),繼續向下單步執行,期間可以觀察一些字段的變化。


但是程序並沒有進入while循環,自然也不會執行request.setAttribute(n, v )函數。


(此時我對attributes還不懂,不知道這個字段的意義),再次跟蹤時發現while循環的判斷條件中在獲取attitudes的值時,返回值為-1。


然後又回頭重新看了下前一節所說的Forward Request結構,看到了其中的attitudes字段,心想這個字段也許和代碼中while循環判斷的attitudecode有關。


然後看了看ajp-client中代碼對attitudes字段的處理,發現該項目沒有處理attitudes字段。


就按照自己的理解在AjpClient.java中添加了attitudes處理相關代碼。


<code>public List<pair>> headers = new LinkedList<pair>>(); public List<pair>> attributes = new LinkedList<pair>>();/<pair>/<pair>/<pair>/<pair>/<code>


添加函數setHeaders()此函數並不重要,添加函數addAttributes()。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

在query函數中添加,處理atrribute代碼

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

修改測試代碼如下

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

(test_servlet/xx是一個不存在的地址或映射,只有設置成不存在的地址,代碼流程才會進入DefaultServlet)


運行程序,程序成功進入while循環

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

至於addAttributes參數為什麼這樣寫,我已開始自然也是不知道的,多跟蹤調試幾次就知道了。


程序執行了request.setAttribute(n, v )函數,接下來就是DefaultServlet的serveResource函數。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

跟蹤到getRelativePath函數中

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

這裡就會獲取我們設置的attributes值。


然後通過resources.getResource(path);判斷設置的路徑文件是否存在,如果存在則返回文件內容,不存在則報錯。


已經成功讀到文件。

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程

關於org.apache.jasper.servlet.JspServlet類實現文件包含,這裡就不分析了,有興趣的如法炮製即可。

五.編寫poc


如何編寫poc就不在講了,上面的測試代碼稍微修改,就是poc了。


六.總結


總的來說,該漏洞的利用並不是很難,即使你不懂ajp協議,有些參考,稍微花點時間,還是能夠獨立寫出poc的,當然我實際調試的時候也沒有文章中那麼順的,要有耐心,多調試幾次就好。


修復的話,如果不需要ajp的,可以把配置文件中的8009配置關閉,或者更新到最新版本。

參考:

https://blog.csdn.net/u012206617/article/details/104416626/

https://blog.csdn.net/kalman2008/article/details/24487703

https://blog.csdn.net/jeikerxiao/article/details/82745516

http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html



今天你知道了嗎

Tomcat-Ajp漏洞:一步步調試寫出POC的歷程


加群,黑客技術大咖在線解答(群號評論區見)


分享到:


相關文章: