漏洞分析:
static class SandBox extends GroovyInterceptor {
static List<Class> RECEIVER_WHITE_LIST = [
Number[].class,
Number.class,
long[].class,
long.class,
int[].class,
int.class,
short[].class,
short.class,
double[].class,
double.class,
float[].class,
float.class,
String[].class,
String.class,
Date[].class,
Date.class,
Map.class,
Collection.class,
Script.class,
Enum[].class,
Enum.class
]
static void checkReceiver(Object obj) {
checkReceiver(obj.getClass())
}
static void checkReceiver(Class clz) {
for (Class wclz : RECEIVER_WHITE_LIST) {
if (wclz.isAssignableFrom(clz)) {
return
}
}
throw new Exception("invalid operation on class[${clz.name}]")
}
static void checkMethod(String method) {
if (method == "sleep") {
throw new Exception("invalid operation[${method}]")
}
}
Object onMethodCall(GroovyInterceptor.Invoker invoker, Object receiver, String method, Object... args) throws Throwable {
checkReceiver(receiver)
checkMethod(method)
return super.onMethodCall(invoker, receiver, method, args)
}
Object onStaticCall(GroovyInterceptor.Invoker invoker, Class receiver, String method, Object... args) throws Throwable {
checkReceiver(receiver)
checkMethod(method)
return super.onStaticCall(invoker, receiver, method, args)
}
.......
}
Script.class
,并且可以注意到,在check白名单判断的时候用的是isAssignableFrom方法,这就意味着我们可以使用任意的Script类的子类。结合上面所说的Groovy-Sandbox只能防御住最外层的恶意代码执行,我们只需要找到一个Script的子类进行二次Script执行,就可以绕过所有的过滤。由于Script本身就具有eval脚本的能力,所以这种类型是非常好找的,在测试里用的是groovy.ui.ConsoleView。修补方案:
时间线:
2021年9月24日 亿格云科技向ZStack官方报告了该漏洞
2021年10月27日 ZStack官方合并补丁到主分支
2021年11月15日 ZStack官方发布公告,公开致谢亿格云科技
相关链接:
https://securitylab.github.com/advisories/GHSL-2021-065-zstack/
https://github.com/zstackio/zstack/security/advisories/GHSA-99wx-p6w8-3hg8
原文始发于微信公众号(亿格云科技):亿格云科技发现ZStack高危RCE漏洞 获得ZStack官方致谢