该漏洞与之前利用 Comparator.compare()
链的思路不同,主要是利用 defineClass
加载自定义类实现的远程代码执行。
利用类是 com.tangosol.internal.util.invoke.RemoteConstructor
,先来看我们能够控制的部分,也就是构造方法:
传入了 ClassDefinition
,继续跟进:
传入一个 ClassIdentity
类型的 id
和对象的字节数组,在继续跟进 ClassIdentity
,可以看到,在其构造方法中需传入一个 class
获得赋值sPackage
,sBaseName
,sVersion
:
在来看反序列化的部分,该类是通过 readResolve
进行反序列化的,readResolve
可以覆盖 readobject
的内容。
进入 this.newInstance()
方法:
最终进入 com.tangosol.internal.util.invoke.RemotableSupport
的 realize
方法:
由于之前未加载过该自定义类,所以会进入 this.defineClass(definition)
方法,跟进:
大概看了下就知道和之前的构造方法中的参数基本相同,也就是都是我们可以控制的,进入 definition.getId().getName()
:
最终执行的是 getSimpleName()
方法,返回的是 BaseName+$+Version
的值,返回 defineClass
方法:
接下来就是把处理的类名、类对象的字节数组及长度传入 this.defineClass
,由于 com.tangosol.internal.util.invoke.RemotableSupport
是继承 ClassLoader
的,所以这里的 this.defineClass
实际上是 ClassLoader.defineClass
也就是创建类,最后创建类的实例,达到实现自定义类的目的:
过程中需要注意的一点就是自定义的类名是由2部分组成的。
利用方式有2种,第一种就是利用重写原有的类,如这里是 LambdaIdentity
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.tangosol.internal.util.invoke.lambda;
import java.io.IOException;
public class LambdaIdentity$423B02C050017B24DB10DFF759AA56BF{
public LambdaIdentity$423B02C050017B24DB10DFF759AA56BF() {
}
static {
try {
Runtime.getRuntime().exec("open /Applications/Calculator.app");
} catch (IOException var1) {
var1.printStackTrace();
}
}
}
这样的好处是后面的 hash
相对固定,第二种是先计算 hash
,然后通过 javaassist
动态修改自定义类的名字。
整个逻辑还是相对清晰,过程也并不复杂,也提供了一种新的挖掘思路,注意构造方法中能直接传入字节数组的类