Vaadin反序列化漏洞利用链分析与Tabby工具检测缺陷
前言
本文基于Vaadin框架的反序列化漏洞利用链分析,结合静态分析工具Tabby在实际应用中的表现,总结了Vaadin框架中新的利用方式以及Tabby工具在检测过程中的一些缺陷。主要内容包括MethodProperty类的任意方法调用、TextFileProperty类的文件读取以及J2EEConnectionPool类的JDBC攻击等利用方式。
MethodProperty类的任意方法调用
原始利用方式回顾
原始的Vaadin反序列化Gadget是通过利用NestedMethodProperty#getValue方法进行利用的。而实际上,MethodProperty#getValue方法也可以作为替代使用,且使用更为方便。
MethodProperty#getValue方法分析
MethodProperty#getValue方法的实现非常简洁:
public Object getValue() {
if (instance != null) {
return ReflectTools.invokeMethod(getMethod, instance, getArgs);
}
return null;
}
该方法逻辑为:若instance属性不为空,则反射调用getMethod属性中的方法。
关键属性分析
这些关键属性都是通过MethodProperty类的构造函数进行传入的:
-
第一个构造函数(两个参数:
instance和beanPropertyName):- 获取传入的instance对象的类
- 处理传入的属性名(首字母大写)
- 通过
initGetterMethod获取后续能够反射调用的Method方法 - 可以调用getter/is/are方法
-
倒数第二个构造函数(七个参数):
- 直接反射从传入的instance实例中获取该对象所有的方法列表
- 使用传入的
getMethodName和type与反射获取的方法列表进行比对 - 比对成功则直接将其赋值给
getMethod属性 - 关键点:未对传入的
getMethodName变量做任何限制,不仅可以传入getter方法,也可以传入非getter方法
-
最后一个构造函数:
- 直接赋值构造函数,最为直接
利用方式
Way1:调用getter方法
// 构造调用getter方法的示例
MethodProperty mp = new MethodProperty(targetObject, "propertyName");
Way2:调用任意方法
// 构造调用任意方法的示例
MethodProperty mp = new MethodProperty(targetObject, "methodName", parameterTypes, parameters);
TextFileProperty类的文件读取
com.vaadin.data.util.TextFileProperty类在其getValue方法中:
public Object getValue() {
try {
return FileUtils.readFileToString(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
该方法直接传入file属性(该属性值可控),在读取文件之后将内容进行返回。
注意:在反序列化漏洞场景下,这种文件读取的利用方式需要进一步验证其实际可行性。
JDBC攻击利用
J2EEConnectionPool#reserveConnection利用
J2EEConnectionPool#reserveConnection方法的利用流程:
reserveConnection -> getDataSource -> lookupDataSource
这个流程可以触发JNDI注入。此外,如果dataSource属性值不为空,则会调用DataSource#getConnection,从而触发JDBC攻击。
POC示例
// J2EEConnectionPool#reserveConnection的JDBC attack示例
// 需要使用dbcp依赖,打EL表达式,需添加对应依赖
Tabby工具的检测缺陷分析
现有问题
-
虽然污点分析工具可以找到原始利用链的完整通路,但对于某些链子(如
J2EEConnectionPool#reserveConnection和SimpleJDBCConnectionPool#reserveConnection方法)不存在有通路。 -
这些链子在最后达到sink点(如JNDI触发位置)时,并没有参数被污染,数据流不能够被传递。
Tabby的具体缺陷
-
虽然能够使用
apoc.algo.allSimplePaths这个procedure查到对应的两条链子,但不能检索到J2EEConnectionPool#reserveConnection中存在的JDBC attack。 -
根本原因:在生成调用关系图的过程中,没有处理连续调用的情况(如
getDataSource().getConnection()),这是一个检测上的缺陷。
总结
-
MethodProperty类提供了灵活的任意方法调用能力,通过不同的构造函数可以实现getter方法调用或任意方法调用。 -
TextFileProperty类存在潜在的文件读取风险,但在反序列化场景下的利用需要进一步验证。 -
J2EEConnectionPool类不仅可以通过JNDI注入利用,还可以通过JDBC攻击进行利用。 -
静态分析工具Tabby在处理某些特定调用模式(如连续方法调用)时存在检测缺陷,需要人工分析进行补充。
-
在实际漏洞挖掘中,需要结合工具分析和人工验证,才能全面发现潜在的利用链。