网站建设、公众号开发、微网站、微商城、小程序就找牛创网络 !

7*24小时服务专线: 152-150-65-006 023-68263070 扫描二维码加我微信 在线QQ

漏洞公告团结互助,让我们共同进步!

当前位置:主页 > 技术资讯 > 网络安全 > 漏洞公告 >

我们的优势: 10年相关行业经验,专业设计师量身定制 设计师一对一服务模式,上百家客户案例! 企业保证,正规流程,正规合作 7*24小时在线服务,售后无忧

Apereo CAS 4.X反序列化漏洞:存在于登录的execution参数,漏洞分析及复现

文章来源:重庆网络安全 发布时间:2020-02-10 12:34:11 围观次数:
分享到:

摘要:Apereo CAS 4 X反序列化漏洞:存在于登录的execution参数,漏洞分析及复现。

环境设定


  由于某些cas版本的加密功能进行了相应的更改,因此,如果您想根据本文重现该漏洞,请选择与我的版本相同的版本。


  jdk8u144(不一定相同)

  ApereoCas-4.1.5

  下载CAS-Overlay-Template


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

  在github上有详细的部署操作。 注意pom.xml文件cas的版本:


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

  编译后,将在target目录中生成cas.war war软件包。  war软件包将放置在tomcat Web目录中。 启动tomcat之后,您可以通过http://localhost/cas访问example。


  成功部署后:

blob.png


漏洞分析


  该漏洞存在于登录的execution参数中。 数据包捕获发现参数值应该被加密,因此有必要知道相应的加密方法和处理过程。

blob.pngblob.png

blob.png

检查与登录URL对应的servlet,以了解它是由Spring的DispatcherServlet处理的。 配置文件是/WEB-INF/cas-servlet.xml

blob.png

从springmvc的执行流程图中,您可以知道,只要找到相应的处理器适配器,就可以找到相应的处理器。

blob.png

全局搜索login一词,并查看loginHandlerAdapter适配器,处理器的类名称为org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter

blob.png

org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter此类在登录时继承FlowHandlerAdapter类并调用继承的类的处理程序方法:

//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;    }

其中flowExecutionKey通过getFlowExecutionKey方法获取参数execution值

String flowExecutionKey = this.flowUrlHandler.getFlowExecutionKey(request);

将flowExecutionKey作为参数传递给resumeExecution方法,以跟进该功能。 在第91行,判断flowExecutionKey值的格式,并且字符串通过“-”分为uuid和base64编码的流状态两部分,因此,如果不满意该格式,则无法继续。

blob.png

blob.png

跟进getFlowExecution的第96行。

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);            }        }    }

在第105行,对解码后的已编码base64进行解密,然后再执行解密函数this.transcoder.decode(已编码)

blob.png

blob.png

可以看出,在执行一系列操作之后,密文在第83行被解密,并在第99行被反序列化,从而触发了漏洞。 可以看出,被调用的解码方法属于EncryptedTranscoder类。 此类还定义了加密方法encode。 在这里,可以直接生成恶意对象。 直接调用org.jasig.spring.webflow.plugin.EncryptedTranscoder#encoding生成加密的字节数组base64。 添加“ uuid-”构成执行的价值。


整个调用栈

blob.png

构造payload


  默认环境的jar包中有commons-collections4-4.0.jar。 使用ysoserial直接生成payload。 记住要对payload的特殊符号进行URL编码。

blob.png

blob.png

演示结果


  成功执行系统命令

blob.png

构造回显payload


  文章提到org.springframework.webflow.context.ExternalContextHolder.getExternalContext()方法可以获取上下文信息,然后通过getNativeRequest()方法通过getNativeResponse()方法获取请求对象,以获取响应对象。 它还提到了org.springframework.cglib.core.ReflectUtils.defineClass()。  NewInstance(); 加载有效载荷。 我的猜测想法是通过defineClass从字节[]中恢复Class对象。 恶意对象主要是执行命令,获取响应对象,并在执行命令后通过响应对象的输出流输出结果。 使用commons-collections1时,我发现由于构造函数是私有的,因此无法使用ReflectUtils,并且setAccessible必须设置为true。 因此,如果您使用commons-collections2,则无需担心通过defineClass加载有效负载,只需将其直接写入利用率类即可。

//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;    }

这是ysoserial的commons-collections2构造恶意对象的主要方法。 在这里,我们使用javassist,第66行获取要操作的类,第75行将代码插入此类的构造函数中,因此我们只需要将此类的构造函数ysoserial.payloads.util.Gadgets.StubTransletPayload修改为 执行系统命令,修改响应输出流。 您可以直接修改ysoserial的源代码并重新编译。 为了方便起见,我直接使用payload对其进行了更改。

blob.png

blob.png

blob.png


本文由 重庆网络安全 整理发布,转载请保留出处,内容部分来自于互联网,如有侵权请联系我们删除。

相关热词搜索:Apereo CAS 4 X 反序列化漏洞 execution参数 漏洞分析及复现 重庆网络安全

上一篇:CVE-2019-1215漏洞成因分析:用后释放漏洞,ws2ifsl.sys中,实现本地提权
下一篇:CVE-2020-5316:SupportAssist Client软件漏洞,导致SupportAssist二进制文件加载任意DLL,进而导致执行任意特权代码

热门资讯

鼠标向下滚动