1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-12-15 02:35:54 +01:00

Land #685, Fix Java TCP server socket binding

Don't listen on IPv6 when 0.0.0.0 srvhost is requested
This commit is contained in:
Spencer McIntyre 2023-11-22 10:49:09 -05:00
commit 9f8a20c8be
No known key found for this signature in database
GPG Key ID: 58101BA0D0D9C987
5 changed files with 94 additions and 22 deletions

View File

@ -30,20 +30,27 @@ public class CommandManager {
try {
Class.forName("java.lang.StrictMath");
apiVersion = ExtensionLoader.V1_3;
Class.forName("java.lang.CharSequence");
apiVersion = ExtensionLoader.V1_4;
Class.forName("java.net.Proxy");
apiVersion = ExtensionLoader.V1_5;
Class.forName("java.util.ServiceLoader");
apiVersion = ExtensionLoader.V1_6;
Class.forName("java.util.Optional").getMethod("stream");
apiVersion = ExtensionLoader.V1_9;
Class<?> protocolFamilyCls = Class.forName("java.net.ProtocolFamily");
Class.forName("java.nio.channels.ServerSocketChannel").getMethod("open", protocolFamilyCls);
apiVersion = ExtensionLoader.V1_15;
} catch (Throwable ignored) {
}
String javaversion = System.getProperty("java.version");
if (javaversion != null && javaversion.length() > 2) {
int vmVersion = javaversion.charAt(2) - '2' + ExtensionLoader.V1_2;
if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion) {
apiVersion = vmVersion;
}
int vmVersion = getVersion();
if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion) {
apiVersion = vmVersion;
}
this.javaVersion = apiVersion;
@ -51,6 +58,21 @@ public class CommandManager {
new com.metasploit.meterpreter.core.Loader().load(this);
}
private static int getVersion() {
String version = System.getProperty("java.version");
// Java version string changed at Java 9 from 1.x.y to just x.y
if (version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if (dot != -1) {
version = version.substring(0, dot);
}
}
return Integer.parseInt(version) + ExtensionLoader.V1_base;
}
/**
* Register a command that can be executed on all Java versions (from 1.2 onward)
*
@ -95,7 +117,7 @@ public class CommandManager {
}
if (version != ExtensionLoader.V1_2) {
commandClass = commandClass.getClassLoader().loadClass(commandClass.getName() + "_V1_" + (version - 10));
commandClass = commandClass.getClassLoader().loadClass(commandClass.getName() + "_V1_" + (version - ExtensionLoader.V1_base));
}
Command cmd = (Command) commandClass.newInstance();

View File

@ -7,12 +7,14 @@ package com.metasploit.meterpreter;
*/
public interface ExtensionLoader {
public static final int V1_base = 10;
public static final int V1_2 = 12;
public static final int V1_3 = 13;
public static final int V1_4 = 14;
public static final int V1_5 = 15;
public static final int V1_6 = 16;
public static final int V1_9 = 19;
public static final int V1_15 = 25;
/**
* Load this extension.

View File

@ -40,7 +40,7 @@ public class Loader implements ExtensionLoader {
}
public void load(CommandManager mgr) throws Exception {
mgr.registerCommand(CommandId.CORE_CHANNEL_OPEN, stdapi_channel_open.class);
mgr.registerCommand(CommandId.CORE_CHANNEL_OPEN, stdapi_channel_open.class, V1_2, V1_15);
mgr.registerCommand(CommandId.STDAPI_FS_CHDIR, stdapi_fs_chdir.class);
mgr.registerCommand(CommandId.STDAPI_FS_DELETE_DIR, stdapi_fs_delete_dir.class);
mgr.registerCommand(CommandId.STDAPI_FS_DELETE_FILE, stdapi_fs_delete_file.class);

View File

@ -1,20 +1,22 @@
package com.metasploit.meterpreter.stdapi;
import java.net.ConnectException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import com.metasploit.meterpreter.Channel;
import com.metasploit.meterpreter.DatagramSocketChannel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.ServerSocketChannel;
import com.metasploit.meterpreter.SocketChannel;
import com.metasploit.meterpreter.Meterpreter;
import com.metasploit.meterpreter.TLVPacket;
import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
@ -81,20 +83,20 @@ public class stdapi_channel_open implements Command {
return ERROR_SUCCESS;
}
private int executeTcpServer(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
private int executeTcpServer(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws UnknownHostException, IOException {
String localHost = request.getStringValue(TLVType.TLV_TYPE_LOCAL_HOST);
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
ServerSocket ss;
if (localHost.equals("0.0.0.0")) {
ss = new ServerSocket(localPort);
} else {
ss = new ServerSocket(localPort, 50, InetAddress.getByName(localHost));
}
ServerSocket ss = getSocket(localHost, localPort);
Channel channel = new ServerSocketChannel(meterpreter, ss);
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
return ERROR_SUCCESS;
}
protected ServerSocket getSocket(String localHost, int localPort) throws UnknownHostException, IOException {
return new ServerSocket(localPort, 50, InetAddress.getByName(localHost));
}
private int executeTcpClient(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
String peerHost = request.getStringValue(TLVType.TLV_TYPE_PEER_HOST);
int peerPort = request.getIntValue(TLVType.TLV_TYPE_PEER_PORT);

View File

@ -0,0 +1,46 @@
package com.metasploit.meterpreter.stdapi;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.ConnectException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
public class stdapi_channel_open_V1_15 extends stdapi_channel_open {
// Constructing a ServerSocket directly for 0.0.0.0 will listen on both IPv4 and IPv6, which, if the operator has explicitly requested 0.0.0.0,
// may not be desirable. Java 15 and later support explicitly specifying IPv4 using ServerSocketChannel.open(StandardProtocolFamily.INET).
// To keep backwards-compatibility, we use reflection to call the newer version.
protected ServerSocket getSocket(String localHost, int localPort) throws UnknownHostException, IOException {
if (localHost.equals("0.0.0.0")) {
try {
Class<?> standardProtocolFamilyCls = Class.forName("java.net.StandardProtocolFamily");
Class<?> protocolFamilyCls = Class.forName("java.net.ProtocolFamily");
java.lang.reflect.Method getValueMethod = standardProtocolFamilyCls.getMethod("valueOf", String.class);
Object inet = getValueMethod.invoke(null, "INET");
Class<?> sscClazz = java.nio.channels.ServerSocketChannel.class;
java.lang.reflect.Method method = sscClazz.getMethod("open", protocolFamilyCls);
java.nio.channels.ServerSocketChannel server = (java.nio.channels.ServerSocketChannel)method.invoke(null, inet);
InetAddress addr = InetAddress.getByName(localHost);
InetSocketAddress sockAddr = new InetSocketAddress(addr, localPort);
java.lang.reflect.Method bindMethod = sscClazz.getMethod("bind", java.net.SocketAddress.class);
bindMethod.invoke(server, sockAddr);
ServerSocket ss = server.socket();
return ss;
}
// If reflection failed for some reason, fall back to the original implementation
catch (IllegalAccessException e) {}
catch (ClassNotFoundException e) {}
catch (NoSuchMethodException e) {}
catch (InvocationTargetException e) {}
}
return super.getSocket(localHost, localPort);
}
}