可領全套安全課程、配套攻防靶場
![Tomcat-Ajp漏洞:一步步調試寫出POC的歷程](http://p2.ttnews.xyz/loading.gif)
前言
晚上,朋友圈有人發了篇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的歷程](http://p2.ttnews.xyz/loading.gif)
三.ajp協議學習
到目前為止,我還不知道什麼是ajp協議,這個協議是幹啥的,但是既然知道此次tomcat漏洞是ajp協議造成的。
我們肯定要去了解下這個協議是什麼。
Apache官方有說明文檔
http://tomcat.apache.org/connectors-doc-archive/jk2/common/AJPv13.html
當然這個文檔一眼看上去,是不太容易理解的,於是百度一番
我理解的是,我們要訪問tomcat網站有兩種方式,一種是通過瀏覽器直接輸入url地址。
另外一種就是通過ajp協議訪問。
AJP協議是定向包(面向包)協議,採用二進制形式代替文本形式,以提高性能。
所以我們需要寫個ajp的客戶端程序用來與tomcat服務器的8009端口進行數據交互。
當然我們可以自己從頭寫一個ajp客戶端,前提是我們需要很詳細瞭解ajp協議及其各個字段含義。
我並不打算如此,畢竟自己從頭寫起來還是很費勁的。
我先到github上用關鍵詞ajp和ajp client搜了一下,看來白的人運氣不會太差,發現已經有別人的ajp-client項目。
我把三個ajp-client都下了下來,經過測試和對比(邊調試邊測試),最後使用了
https://github.com/espenhw/ajp-client
這個項目,最後poc也是在這個項目上完成的。
這裡我們需要說下ajp協議中比較重要的字段。
Forward Request包就是我們要發送給tomcat 8009端口的內容,用來觸發漏洞的。
該字段中比較重要的字段是attributes,後面調試跟蹤的時候,也會發現的,後面再說。
四.調試跟蹤
通過參考我們知道,tomcat在接收ajp請求的時候調用org.apache.coyote.ajp.AjpProcessor來處理ajp消息
prepareRequest將ajp裡面的內容取出來設置成request對象的Attribute屬性。
我們現在AjpProcessor中定位到prepareRequest()函數,並在函數開始出下上斷點,在request.setAttribute(n, v )也下上斷點。
編寫測試代碼如下(test_servlet是我自己編寫的servlet代碼,放在了webapps目錄下):
運行程序,程序成功斷在了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()。
在query函數中添加,處理atrribute代碼
修改測試代碼如下
(test_servlet/xx是一個不存在的地址或映射,只有設置成不存在的地址,代碼流程才會進入DefaultServlet)
運行程序,程序成功進入while循環
至於addAttributes參數為什麼這樣寫,我已開始自然也是不知道的,多跟蹤調試幾次就知道了。
程序執行了request.setAttribute(n, v )函數,接下來就是DefaultServlet的serveResource函數。
跟蹤到getRelativePath函數中
這裡就會獲取我們設置的attributes值。
然後通過resources.getResource(path);判斷設置的路徑文件是否存在,如果存在則返回文件內容,不存在則報錯。
已經成功讀到文件。
關於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
今天你知道了嗎
加群,黑客技術大咖在線解答(群號評論區見)
閱讀更多 暗網視界 的文章