mirror of
https://github.com/rapid7/metasploit-payloads
synced 2025-03-18 15:14:10 +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 {
|
try {
|
||||||
Class.forName("java.lang.StrictMath");
|
Class.forName("java.lang.StrictMath");
|
||||||
apiVersion = ExtensionLoader.V1_3;
|
apiVersion = ExtensionLoader.V1_3;
|
||||||
|
|
||||||
Class.forName("java.lang.CharSequence");
|
Class.forName("java.lang.CharSequence");
|
||||||
apiVersion = ExtensionLoader.V1_4;
|
apiVersion = ExtensionLoader.V1_4;
|
||||||
|
|
||||||
Class.forName("java.net.Proxy");
|
Class.forName("java.net.Proxy");
|
||||||
apiVersion = ExtensionLoader.V1_5;
|
apiVersion = ExtensionLoader.V1_5;
|
||||||
|
|
||||||
Class.forName("java.util.ServiceLoader");
|
Class.forName("java.util.ServiceLoader");
|
||||||
apiVersion = ExtensionLoader.V1_6;
|
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) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
String javaversion = System.getProperty("java.version");
|
int vmVersion = getVersion();
|
||||||
if (javaversion != null && javaversion.length() > 2) {
|
if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion) {
|
||||||
int vmVersion = javaversion.charAt(2) - '2' + ExtensionLoader.V1_2;
|
apiVersion = vmVersion;
|
||||||
if (vmVersion >= ExtensionLoader.V1_2 && vmVersion < apiVersion) {
|
|
||||||
apiVersion = vmVersion;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.javaVersion = apiVersion;
|
this.javaVersion = apiVersion;
|
||||||
|
|
||||||
@ -51,6 +58,21 @@ public class CommandManager {
|
|||||||
new com.metasploit.meterpreter.core.Loader().load(this);
|
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)
|
* 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) {
|
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();
|
Command cmd = (Command) commandClass.newInstance();
|
||||||
|
@ -7,12 +7,14 @@ package com.metasploit.meterpreter;
|
|||||||
*/
|
*/
|
||||||
public interface ExtensionLoader {
|
public interface ExtensionLoader {
|
||||||
|
|
||||||
|
public static final int V1_base = 10;
|
||||||
public static final int V1_2 = 12;
|
public static final int V1_2 = 12;
|
||||||
public static final int V1_3 = 13;
|
public static final int V1_3 = 13;
|
||||||
public static final int V1_4 = 14;
|
public static final int V1_4 = 14;
|
||||||
public static final int V1_5 = 15;
|
public static final int V1_5 = 15;
|
||||||
public static final int V1_6 = 16;
|
public static final int V1_6 = 16;
|
||||||
public static final int V1_9 = 19;
|
public static final int V1_9 = 19;
|
||||||
|
public static final int V1_15 = 25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load this extension.
|
* Load this extension.
|
||||||
|
@ -40,7 +40,7 @@ public class Loader implements ExtensionLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void load(CommandManager mgr) throws Exception {
|
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_CHDIR, stdapi_fs_chdir.class);
|
||||||
mgr.registerCommand(CommandId.STDAPI_FS_DELETE_DIR, stdapi_fs_delete_dir.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);
|
mgr.registerCommand(CommandId.STDAPI_FS_DELETE_FILE, stdapi_fs_delete_file.class);
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
package com.metasploit.meterpreter.stdapi;
|
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.ByteArrayInputStream;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
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.Channel;
|
||||||
import com.metasploit.meterpreter.DatagramSocketChannel;
|
import com.metasploit.meterpreter.DatagramSocketChannel;
|
||||||
|
import com.metasploit.meterpreter.Meterpreter;
|
||||||
import com.metasploit.meterpreter.ServerSocketChannel;
|
import com.metasploit.meterpreter.ServerSocketChannel;
|
||||||
import com.metasploit.meterpreter.SocketChannel;
|
import com.metasploit.meterpreter.SocketChannel;
|
||||||
import com.metasploit.meterpreter.Meterpreter;
|
|
||||||
import com.metasploit.meterpreter.TLVPacket;
|
import com.metasploit.meterpreter.TLVPacket;
|
||||||
import com.metasploit.meterpreter.TLVType;
|
import com.metasploit.meterpreter.TLVType;
|
||||||
import com.metasploit.meterpreter.command.Command;
|
import com.metasploit.meterpreter.command.Command;
|
||||||
@ -81,20 +83,20 @@ public class stdapi_channel_open implements Command {
|
|||||||
return ERROR_SUCCESS;
|
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);
|
String localHost = request.getStringValue(TLVType.TLV_TYPE_LOCAL_HOST);
|
||||||
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
|
int localPort = request.getIntValue(TLVType.TLV_TYPE_LOCAL_PORT);
|
||||||
ServerSocket ss;
|
ServerSocket ss = getSocket(localHost, localPort);
|
||||||
if (localHost.equals("0.0.0.0")) {
|
|
||||||
ss = new ServerSocket(localPort);
|
|
||||||
} else {
|
|
||||||
ss = new ServerSocket(localPort, 50, InetAddress.getByName(localHost));
|
|
||||||
}
|
|
||||||
Channel channel = new ServerSocketChannel(meterpreter, ss);
|
Channel channel = new ServerSocketChannel(meterpreter, ss);
|
||||||
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
|
response.add(TLVType.TLV_TYPE_CHANNEL_ID, channel.getID());
|
||||||
return ERROR_SUCCESS;
|
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 {
|
private int executeTcpClient(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
|
||||||
String peerHost = request.getStringValue(TLVType.TLV_TYPE_PEER_HOST);
|
String peerHost = request.getStringValue(TLVType.TLV_TYPE_PEER_HOST);
|
||||||
int peerPort = request.getIntValue(TLVType.TLV_TYPE_PEER_PORT);
|
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…
x
Reference in New Issue
Block a user