Java安全之Cas反序列化漏洞分析
0x00 前言
某次專案中遇到Cas,以前沒接觸過,藉此機會學習一波。
0x01 Cas 簡介
CAS 是 Yale 大學發起的一個開源專案,旨在為 Web 應用系統提供一種可靠的單點登入方法,CAS 在 2004 年 12 月正式成為 JA-SIG 的一個專案,開源的企業級單點登入解決方案。
0x02 遠端除錯環境搭建
下載地址,將環境war包下載,部署到tomcat即可
tomcat目錄bin檔案下,startup_debug.bat
call %EXECUTABLE%" start %CMD_LINE_ARGS%
改為
set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=5005
set JPDA_SUSPEND=n
call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%
IDEA中設定Remote遠端除錯5005即可完成。
0x03 漏洞分析
漏洞詳情
4.1.7版本之前存在一處預設金鑰的問題,利用這個預設金鑰我們可以構造惡意資訊觸發目標反序列化漏洞,進而執行任意命令。
- 影響版本 Apereo CAS <= 4.1.7
實際上 4.2.X也能打,但是 <= 4.1.7使用的是硬編碼,而後者屬於隨機金鑰
感覺上和Shiro的 550有點類似
解析流程分析
看web.xml得知,該專案基於Spring MVC開發。
上圖請求路徑是/login
的這裡來直接找login的處理方法進行跟蹤。
從web.xml中可見,交給了DispatcherServlet
去處理。
這時候可以檢視springmvc的配置檔案cas-servlet.xml
注意loginHandlerAdapter
這個配置的bean,其中的屬性有supportedFlowId
的值為"login",同時屬性flowExecutor-ref的引用值為loginFlowExecutor
。
再看loginFlowExecutor
這個bean中所配置的登入流程屬性引用值就是我們webflow上下文配置中的loginFlowRegistry
這個屬性。
因此我們來看一下loginHandlerAdapter
這個bean對應的類為org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter
所起的作用,是如何來處理登入動作的。先來看一下這個類的父類org.springframework.webflow.mvc.servlet.FlowHandlerAdapter
,這個是Springmvc中的一個類。
FlowHandlerAdapter
實現介面HandlerAdapter
,而SelectiveFlowHandlerAdapter
繼承自FlowHandlerAdapter
。
SelectiveFlowHandlerAdapter
類在cas-server-webapp-actions
模組下的org.jasig.cas.web.flow
包下。
因此Spring的DispatcherServlet找到要處理的handleAdapter
是SelectiveFlowHandlerAdapte
。並且根據地址http://localhost:8080/cas/login?service=XXX,得到handler的flowId="login",即流程:loginFlowRegistry
。
然後進入下面的handle方法,開始調取流程:
當有登入請求時,spring則會呼叫該org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter
跟進this.flowUrlHandler.getFlowExecutionKey(request)
可見,該方法會獲取請求中的execution
引數。
而後會進行呼叫 this.executionRepository.parseFlowExecutionKey(flowExecutionKey);
獲取到key。
跟進檢視
可見從execution
引數,後分割UUID和_
後面部分,而後面部分進行base64解密。對返回id和data進行賦值,然後返回ClientFlowExecutionKey
物件
下面呼叫this.executionRepository.getFlowExecution(key);
,將剛剛獲取到的ClientFlowExecutionKey
物件,即key變數傳遞。跟進。
這地方進行了資料的反序列化操作。先來看到構造方法,使用AES/CBC/PKCS7
加密方式,並且金鑰使用預設的金鑰進行加密。
而在解密後還會對資料進行解壓縮GZIPInputStream
處理後進行反序列化。
漏洞復現與利用
根據以上資料解析分析,我們只需要將cas中加密部分扣出來,然後進行GZIPOutputStream
處理,而後將他進行base64加密,將處理後的gadgets加入到execution
引數裡面即可,當然還需要構造一下前面UUID的值。
從github找到現成工具。
Reference
https://www.anquanke.com/post/id/198842
0x04 結尾
除此外,還有一些值得探討的地方例如,回顯方式的構造