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:
commit
9f8a20c8be
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user