利用链

yso给出的利用链:

image-20220106222224668

完整的:

1
2
3
4
5
6
7
8
9
10
ObjectInputStream.readObject()
PriorityQueue.readObject()
PriorityQueue.heapify()
PriorityQueue. siftDown()
PriorityQueue.siftDownUsingComparator()
TransformingComparator.compare()
InvokerTransformer.transform()
TemplatesImpl.newTransformer()
......
Runtime.exec()

可以看到,CC2使用了PriorityQueue reaObject作为了反序列化的入口

这里调用了heapify函数

image-20220106222354454

在这个函数里面又调用了siftDown

image-20220106222427694

在这面又调用了siftDownUsingComparator

image-20220106222811868

image-20220106222851527

这里就调用了comparator.compare(),如果这里的comparator是TransformingComparator类型,则会调用transform函数,达到利用效果。

image-20220106223107986

基于以上,想要满足程序能按照我们预想的顺序执行,我们需要满足几个条件:

  1. comparator不为空,这个条件可以通过PriorityQueue的构造函数完成

image-20220106225752810

  1. size >= 2,这个条件可以通过两个add函数满足

    image-20220106225855042

而且,如果我们直接把恶意类放进PriorityQueue的话,那么在PriorityQueue的add中会调用offer

image-20220106230201022

进而调用siftUp

image-20220106230218569

然后提前触发恶意类的代码执行,所以,要现将无害的信息放进PriorityQueue,然后最后再将恶意的类替换进去:

image-20220106230805865

这里使用了yso工具类进行字段替换:

image-20220106232412250

替换后:

image-20220106232448626

然后,transformer调用newTransformer,然后触发恶意类,完成利用。

image-20220106232623683

TemplatesImpl

我们可以发现,在yso中,和CC1不一样的是,这里没有直接使用InvokerTransformer来完成利用(但是是可以用的),而是使用了TemplatesImpl:

image-20220106232953183

这里的流程是:

TemplatesImpl 存在一个 成员变量_bytecodes,当调用 TemplatesImpl#newTransformer 方法时,将会把

_bytecodes 实例化,所以我们可以将恶意代码写到类的无参构造函数或static代码块中转换为字节码赋值给_bytecodes ,然后找到一个位置调用newTransformer就能完成整个攻击。

但是要注意,这里的_bytecodes对象必须是AbstractTranslet的子类

yso通过以下方法完成了这个_bytecodes的创建

image-20220106233326923

image-20220106233411364

image-20220106233828049