Apereo CAS 4.X反序列化漏洞分析及復現

0×01 前言

放假前看到很多文章對這個漏洞進行分析復現,又因為過年期間的特殊情況,實在是無聊至極,所以自己也來學習一下,順便惡補一下反序列化漏洞的知識。這篇文章記錄了自己的一些想法以及相關的知識點,方便自己日後忘記可以重新拾起。第一次寫文章有不好的,希望大家見諒。

0×02 環境搭建

由於部分cas版本的加密函數不同有相應的變化,因此想要按照此文章來複現漏洞的話還是選擇和我一樣的版本。

<code>jdk8u144(不一定完全一樣)ApereoCas-4.1.5/<code>

下載CAS-Overlay-Template

github鏈接:https://github.com/apereo/cas-overlay-template/tree/4.1

github上有詳細的部署操作,這裡要注意要修改pom.xml文件cas的版本:

<code><cas.version>4.1.5/<cas.version>/<code>

編譯完後,會在target目錄生成一個cas.war的war包,將該war包放在tomcat的web目錄上,啟動tomcat即可通過http://localhost/cas訪問example。

成功部署後:

Apereo CAS 4.X反序列化漏洞分析及復現

0×03 漏洞分析

該漏洞存在於登錄的execution參數,抓包發現該參數值應該是加密過的,故要知道對應的加密方法以及處理過程才行。

Apereo CAS 4.X反序列化漏洞分析及復現

web.xml

查看登錄url對應的servlet可知道交給了Spring的DispatcherServlet處理了,配置文件為/WEB-INF/cas-servlet.xml

Apereo CAS 4.X反序列化漏洞分析及復現

從springmvc的執行流程圖(網上找的)可以知道只要找到對應的處理器適配器,就能找到對應的處理器。

Apereo CAS 4.X反序列化漏洞分析及復現

cas-servlet.xml

全局搜索login字眼,看到loginHandlerAdapter適配器,處理器的類名為org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter

Apereo CAS 4.X反序列化漏洞分析及復現

org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter該類繼承FlowHandlerAdapter類,登錄時調用繼承類的handler方法:

<code>//org.springframework.webflow.mvc.servlet.FlowHandlerAdapter#handlepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        FlowHandler flowHandler = (FlowHandler)handler;        this.checkAndPrepare(request, response, false);        String flowExecutionKey = this.flowUrlHandler.getFlowExecutionKey(request);        if (flowExecutionKey != null) {            try {                ServletExternalContext context = this.createServletExternalContext(request, response);                FlowExecutionResult result = this.flowExecutor.resumeExecution(flowExecutionKey, context);                this.handleFlowExecutionResult(result, context, request, response, flowHandler);            } catch (FlowException var11) {                this.handleFlowException(var11, request, response, flowHandler);            }        } else {            try {                String flowId = this.getFlowId(flowHandler, request);                MutableAttributeMap<object> input = this.getInputMap(flowHandler, request);                ServletExternalContext context = this.createServletExternalContext(request, response);                FlowExecutionResult result = this.flowExecutor.launchExecution(flowId, input, context);                this.handleFlowExecutionResult(result, context, request, response, flowHandler);            } catch (FlowException var10) {                this.handleFlowException(var10, request, response, flowHandler);            }        }        return null;    }/<object>/<code>

其中flowExecutionKey通過getFlowExecutionKey方法獲取參數execution的值

<code>String flowExecutionKey = this.flowUrlHandler.getFlowExecutionKey(request);/<code>

flowExecutionKey作為參數傳入resumeExecution方法,跟進函數。在第91行對flowExecutionKey值的格式進行判斷,通過”-”分割字符串為兩部分uuid以及base64編碼flowstate,因此格式不滿足的話是無法繼續走下去的。

Apereo CAS 4.X反序列化漏洞分析及復現

Apereo CAS 4.X反序列化漏洞分析及復現

跟進第96行getFlowExecution。

<code>public FlowExecution getFlowExecution(FlowExecutionKey key) throws FlowExecutionRepositoryException {        if (!(key instanceof ClientFlowExecutionKey)) {            throw new IllegalArgumentException("Expected instance of ClientFlowExecutionKey but got " + key.getClass().getName());        } else {            byte[] encoded = ((ClientFlowExecutionKey)key).getData();            try {                ClientFlowExecutionRepository.SerializedFlowExecutionState state = (ClientFlowExecutionRepository.SerializedFlowExecutionState)this.transcoder.decode(encoded);                FlowDefinition flow = this.flowDefinitionLocator.getFlowDefinition(state.getFlowId());                return this.flowExecutionFactory.restoreFlowExecution(state.getExecution(), flow, key, state.getConversationScope(), this.flowDefinitionLocator);            } catch (IOException var5) {                throw new ClientFlowExecutionRepositoryException("Error decoding flow execution", var5);            }        }    }/<code>

在第105行對之前base64解碼後的encoded進行解密,跟進解密函數this.transcoder.decode(encoded)

Apereo CAS 4.X反序列化漏洞分析及復現

Apereo CAS 4.X反序列化漏洞分析及復現

可以看出在第83行對密文進行解密,經過一系列的操作後在99行進行反序列化,觸發漏洞。可以看出調用的decode方法屬於EncryptedTranscoder類,該類還定義的加密方法encode,這裡可以直接生成惡意對象,直接調用org.jasig.spring.webflow.plugin.EncryptedTranscoder#encode生成加密字節數組後base64,加上”uuid-”構成execution的值。

整個調用棧

Apereo CAS 4.X反序列化漏洞分析及復現

0×03 構造payload

默認環境的jar包中有commons-collections4-4.0.jar,直接使用ysoserial生成payload,這裡記得要將payload的特殊符號進行url編碼。

Apereo CAS 4.X反序列化漏洞分析及復現

Apereo CAS 4.X反序列化漏洞分析及復現

演示結果

成功執行系統命令

Apereo CAS 4.X反序列化漏洞分析及復現

0×04 構造回顯payload

看了大佬的分析,知道可以回顯,文章提及到org.springframework.webflow.context.ExternalContextHolder.getExternalContext()方法可以獲取到上下文關聯信息,然後通過getNativeRequest()方法獲取request對象通過getNativeResponse()方法獲取response對象。同時提及到org.springframework.cglib.core.ReflectUtils.defineClass().newInstance();加載payload。我的猜測大佬的想法是通過defineClass從byte[]還原出一個Class對象,該惡意對象主要是執行命令,獲取response對象,將執行命令後的結果通過response對象的輸出流輸出。在利用commons-collections1是發現ReflectUtils利用不了,因為構造方法為private,要設置setAccessible為true。因此使用commons-collections2的話,實際就不需要這麼麻煩用defineClass來加載payload了,直接在利用類裡面寫就好了。

<code>//org.springframework.cglib.core.ReflectUtilsprivate ReflectUtils() {    }//org.springframework.cglib.core.ReflectUtils#defineClass public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {        Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN};        Class c = (Class)DEFINE_CLASS.invoke(loader, args);        Class.forName(className, true, loader);        return c;    }/<code>

這裡看看ysoserial的commons-collections2的構造惡意對象的主要方法。這裡使用javassist,第66行獲取要操作的類,第75行在該類的構造方法中插入代碼,因此這裡只要修改該類ysoserial.payloads.util.Gadgets.StubTransletPayload的構造方法為執行系統命令,並修改response的輸出流。大家可以直接修改ysoserial的源碼並重新編譯,我這裡為了方便直接用了網上的payload改了一下。

Apereo CAS 4.X反序列化漏洞分析及復現

Apereo CAS 4.X反序列化漏洞分析及復現

演示結果

Apereo CAS 4.X反序列化漏洞分析及復現

0×04 最後

文章中存在錯誤的地方希望大佬們斧正,多多指點。通過這次的分析,其實學到很多東西的,包括commons-collections利用鏈、ysoserial源碼分析。最後,在新的一年裡希望大家身體健康,萬事如意。

0×05參考鏈接:

https://www.00theway.org/2020/01/04/apereo-cas-rce/

https://xz.aliyun.com/t/2041

https://xz.aliyun.com/t/4711

https://xz.aliyun.com/t/7031

https://xz.aliyun.com/t/7032

http://www.vuln.cn/6295

https://www.freebuf.com/vuls/170344.html

https://mp.weixin.qq.com/s/FSMNIkVws3eqDdaheiCviA

https://www.cnblogs.com/gxc6/p/9544563.html


分享到:


相關文章: