Skip to content

Commit 2c6cfab

Browse files
committed
Land rapid7#8948, allow configuring payload HTTP headers for domain fronting
2 parents 78e4b2b + 8645a51 commit 2c6cfab

File tree

93 files changed

+580
-314
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+580
-314
lines changed

Gemfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ PATH
1717
metasploit-concern
1818
metasploit-credential
1919
metasploit-model
20-
metasploit-payloads (= 1.3.14)
20+
metasploit-payloads (= 1.3.15)
2121
metasploit_data_models
22-
metasploit_payloads-mettle (= 0.2.5)
22+
metasploit_payloads-mettle (= 0.2.8)
2323
msgpack
2424
nessus_rest
2525
net-ssh
@@ -178,7 +178,7 @@ GEM
178178
activemodel (~> 4.2.6)
179179
activesupport (~> 4.2.6)
180180
railties (~> 4.2.6)
181-
metasploit-payloads (1.3.14)
181+
metasploit-payloads (1.3.15)
182182
metasploit_data_models (2.0.15)
183183
activerecord (~> 4.2.6)
184184
activesupport (~> 4.2.6)
@@ -189,7 +189,7 @@ GEM
189189
postgres_ext
190190
railties (~> 4.2.6)
191191
recog (~> 2.0)
192-
metasploit_payloads-mettle (0.2.5)
192+
metasploit_payloads-mettle (0.2.8)
193193
method_source (0.9.0)
194194
mini_portile2 (2.3.0)
195195
minitest (5.10.3)

lib/msf/base/sessions/mettle_config.rb

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ def generate_uri(opts={})
2727
generate_uri_uuid_mode(:init_connect, uri_req_len, uuid: opts[:uuid])
2828
end
2929

30+
def generate_uri_option(opts, opt)
31+
opts[opt] ? "--#{opt} '#{opts[opt].gsub(/'/, "\\'")}' " : ''
32+
end
33+
3034
def generate_http_uri(opts)
3135
if Rex::Socket.is_ipv6?(opts[:lhost])
3236
target_uri = "#{opts[:scheme]}://[#{opts[:lhost]}]"
@@ -38,7 +42,15 @@ def generate_http_uri(opts)
3842
target_uri << opts[:lport].to_s
3943
target_uri << luri
4044
target_uri << generate_uri(opts)
41-
target_uri
45+
target_uri << '|'
46+
target_uri << generate_uri_option(opts, :ua)
47+
target_uri << generate_uri_option(opts, :host)
48+
target_uri << generate_uri_option(opts, :referer)
49+
if opts[:cookie]
50+
opts[:header] = "Cookie: #{opts[:cookie]}"
51+
target_uri << generate_uri_option(opts, :header)
52+
end
53+
target_uri.strip
4254
end
4355

4456
def generate_tcp_uri(opts)
@@ -57,14 +69,11 @@ def generate_config(opts={})
5769

5870
case opts[:scheme]
5971
when 'http'
60-
transport = transport_config_reverse_http(opts)
61-
opts[:uri] = generate_http_uri(transport)
72+
opts[:uri] = generate_http_uri(transport_config_reverse_http(opts))
6273
when 'https'
63-
transport = transport_config_reverse_https(opts)
64-
opts[:uri] = generate_http_uri(transport)
74+
opts[:uri] = generate_http_uri(transport_config_reverse_https(opts))
6575
when 'tcp'
66-
transport = transport_config_reverse_tcp(opts)
67-
opts[:uri] = generate_tcp_uri(transport)
76+
opts[:uri] = generate_tcp_uri(transport_config_reverse_tcp(opts))
6877
else
6978
raise ArgumentError, "Unknown scheme: #{opts[:scheme]}"
7079
end
@@ -74,7 +83,7 @@ def generate_config(opts={})
7483
unless opts[:stageless] == true
7584
guid = [SecureRandom.uuid.gsub(/-/, '')].pack('H*')
7685
end
77-
opts[:session_guid] = Base64.encode64(guid)
86+
opts[:session_guid] = Base64.encode64(guid).strip
7887

7988
opts.slice(:uuid, :session_guid, :uri, :debug, :log_file)
8089
end

lib/msf/core/handler/reverse_http.rb

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,38 @@ def initialize(info = {})
5252

5353
register_advanced_options(
5454
[
55-
56-
OptString.new('MeterpreterUserAgent', [false, 'The user-agent that the payload should use for communication', Rex::UserAgent.shortest]),
57-
OptString.new('MeterpreterServerName', [false, 'The server header that the handler will send in response to requests', 'Apache']),
58-
OptAddress.new('ReverseListenerBindAddress', [false, 'The specific IP address to bind to on the local system']),
59-
OptBool.new('OverrideRequestHost', [false, 'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT', false]),
60-
OptString.new('OverrideLHOST', [false, 'When OverrideRequestHost is set, use this value as the host name for secondary requests']),
61-
OptPort.new('OverrideLPORT', [false, 'When OverrideRequestHost is set, use this value as the port number for secondary requests']),
62-
OptString.new('OverrideScheme', [false, 'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https']),
63-
OptString.new('HttpUnknownRequestResponse', [false, 'The returned HTML response body when the handler receives a request that is not from a payload', '<html><body><h1>It works!</h1></body></html>']),
64-
OptBool.new('IgnoreUnknownPayloads', [false, 'Whether to drop connections from payloads using unknown UUIDs', false])
55+
OptAddress.new('ReverseListenerBindAddress',
56+
'The specific IP address to bind to on the local system'
57+
),
58+
OptBool.new('OverrideRequestHost',
59+
'Forces a specific host and port instead of using what the client requests, defaults to LHOST:LPORT',
60+
),
61+
OptString.new('OverrideLHOST',
62+
'When OverrideRequestHost is set, use this value as the host name for secondary requests'
63+
),
64+
OptPort.new('OverrideLPORT',
65+
'When OverrideRequestHost is set, use this value as the port number for secondary requests'
66+
),
67+
OptString.new('OverrideScheme',
68+
'When OverrideRequestHost is set, use this value as the scheme for secondary requests, e.g http or https'
69+
),
70+
OptString.new('HttpUserAgent',
71+
'The user-agent that the payload should use for communication',
72+
default: Rex::UserAgent.shortest,
73+
aliases: ['MeterpreterUserAgent']
74+
),
75+
OptString.new('HttpServerName',
76+
'The server header that the handler will send in response to requests',
77+
default: 'Apache',
78+
aliases: ['MeterpreterServerName']
79+
),
80+
OptString.new('HttpUnknownRequestResponse',
81+
'The returned HTML response body when the handler receives a request that is not from a payload',
82+
default: '<html><body><h1>It works!</h1></body></html>'
83+
),
84+
OptBool.new('IgnoreUnknownPayloads',
85+
'Whether to drop connections from payloads using unknown UUIDs'
86+
)
6587
], Msf::Handler::ReverseHttp)
6688
end
6789

@@ -204,7 +226,7 @@ def setup_handler
204226

205227
raise ex if (ex)
206228

207-
self.service.server_name = datastore['MeterpreterServerName']
229+
self.service.server_name = datastore['HttpServerName']
208230

209231
# Add the new resource
210232
service.add_resource((luri + "/").gsub("//", "/"),
@@ -245,14 +267,14 @@ def lookup_proxy_settings
245267
info = {}
246268
return @proxy_settings if @proxy_settings
247269

248-
if datastore['PayloadProxyHost'].to_s == ''
270+
if datastore['HttpProxyHost'].to_s == ''
249271
@proxy_settings = info
250272
return @proxy_settings
251273
end
252274

253-
info[:host] = datastore['PayloadProxyHost'].to_s
254-
info[:port] = (datastore['PayloadProxyPort'] || 8080).to_i
255-
info[:type] = datastore['PayloadProxyType'].to_s
275+
info[:host] = datastore['HttpProxyHost'].to_s
276+
info[:port] = (datastore['HttpProxyPort'] || 8080).to_i
277+
info[:type] = datastore['HttpProxyType'].to_s
256278

257279
uri_host = info[:host]
258280

@@ -266,11 +288,11 @@ def lookup_proxy_settings
266288
info[:info] = "socks=#{info[:info]}"
267289
else
268290
info[:info] = "http://#{info[:info]}"
269-
if datastore['PayloadProxyUser'].to_s != ''
270-
info[:username] = datastore['PayloadProxyUser'].to_s
291+
if datastore['HttpProxyUser'].to_s != ''
292+
info[:username] = datastore['HttpProxyUser'].to_s
271293
end
272-
if datastore['PayloadProxyPass'].to_s != ''
273-
info[:password] = datastore['PayloadProxyPass'].to_s
294+
if datastore['HttpProxyPass'].to_s != ''
295+
info[:password] = datastore['HttpProxyPass'].to_s
274296
end
275297
end
276298

@@ -347,8 +369,6 @@ def on_request(cli, req)
347369
blob = self.generate_stage(
348370
url: url,
349371
uuid: uuid,
350-
lhost: uri.host,
351-
lport: uri.port,
352372
uri: conn_id
353373
)
354374

lib/msf/core/handler/reverse_https_proxy.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,11 @@ def initialize(info = {})
3838

3939
register_options(
4040
[
41-
OptAddressLocal.new('LHOST', [ true, "The local listener hostname" ,"127.0.0.1"]),
42-
OptPort.new('LPORT', [ true, "The local listener port", 8443 ]),
43-
OptString.new('PayloadProxyHost', [true, "The proxy server's IP address", "127.0.0.1"]),
44-
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ]),
45-
OptEnum.new('PayloadProxyType', [true, 'The proxy type, HTTP or SOCKS', 'HTTP', ['HTTP', 'SOCKS']]),
46-
OptString.new('PayloadProxyUser', [ false, "An optional username for HTTP proxy authentication"]),
47-
OptString.new('PayloadProxyPass', [ false, "An optional password for HTTP proxy authentication"])
48-
], Msf::Handler::ReverseHttpsProxy)
41+
OptAddressLocal.new('LHOST', "The local listener hostname", default: "127.0.0.1"),
42+
OptPort.new('LPORT', "The local listener port", default: 8443)
43+
] +
44+
Msf::Opt::http_proxy_options,
45+
Msf::Handler::ReverseHttpsProxy)
4946

5047
register_advanced_options(
5148
[

lib/msf/core/handler/reverse_tcp.rb

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,6 @@ def initialize(info = {})
4545
# XXX: Not supported by all modules
4646
register_advanced_options(
4747
[
48-
OptInt.new(
49-
'StagerRetryCount',
50-
[ true, 'The number of connection attempts to try before exiting the process', 10 ],
51-
aliases: ['ReverseConnectRetries']
52-
),
53-
OptFloat.new(
54-
'StagerRetryWait',
55-
[ false, 'Number of seconds to wait for the stager between reconnect attempts', 5.0 ]
56-
),
5748
OptAddress.new(
5849
'ReverseListenerBindAddress',
5950
[ false, 'The specific IP address to bind to on the local system' ]
@@ -62,7 +53,8 @@ def initialize(info = {})
6253
'ReverseListenerThreaded',
6354
[ true, 'Handle every connection in a new thread (experimental)', false ]
6455
)
65-
],
56+
] +
57+
Msf::Opt::stager_retry_options,
6658
Msf::Handler::ReverseTcp
6759
)
6860

lib/msf/core/opt.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,49 @@ def self.SSLVersion
6565
)
6666
end
6767

68+
def self.stager_retry_options
69+
[
70+
OptInt.new('StagerRetryCount',
71+
'The number of times the stager should retry if the first connect fails',
72+
default: 10,
73+
aliases: ['ReverseConnectRetries']
74+
),
75+
OptInt.new('StagerRetryWait',
76+
'Number of seconds to wait for the stager between reconnect attempts',
77+
default: 5
78+
)
79+
]
80+
end
81+
82+
def self.http_proxy_options
83+
[
84+
OptString.new('HttpProxyHost', 'An optional proxy server IP address or hostname',
85+
aliases: ['PayloadProxyHost']
86+
),
87+
OptPort.new('HttpProxyPort', 'An optional proxy server port',
88+
aliases: ['PayloadProxyPort']
89+
),
90+
OptString.new('HttpProxyUser', 'An optional proxy server username',
91+
aliases: ['PayloadProxyUser']
92+
),
93+
OptString.new('HttpProxyPass', 'An optional proxy server password',
94+
aliases: ['PayloadProxyPass']
95+
),
96+
OptEnum.new('HttpProxyType', 'The type of HTTP proxy',
97+
enums: ['HTTP', 'SOCKS'],
98+
aliases: ['PayloadProxyType']
99+
)
100+
]
101+
end
102+
103+
def self.http_header_options
104+
[
105+
OptString.new('HttpHostHeader', 'An optional value to use for the Host HTTP header'),
106+
OptString.new('HttpCookie', 'An optional value to use for the Cookie HTTP header'),
107+
OptString.new('HttpReferer', 'An optional value to use for the Referer HTTP header')
108+
]
109+
end
110+
68111
CHOST = CHOST()
69112
CPORT = CPORT()
70113
LHOST = LHOST()

lib/msf/core/payload/android/reverse_http.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ module Payload::Android::ReverseHttp
1818
include Msf::Payload::Android
1919
include Msf::Payload::UUID::Options
2020

21+
#
22+
# Register reverse_http specific options
23+
#
24+
def initialize(*args)
25+
super
26+
register_advanced_options(Msf::Opt::http_header_options)
27+
end
28+
2129
#
2230
# Generate the transport-specific configuration
2331
#

lib/msf/core/payload/java/reverse_http.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ module Payload::Java::ReverseHttp
2323
#
2424
def initialize(*args)
2525
super
26-
register_advanced_options([
27-
Msf::OptInt.new('Spawn', [true, 'Number of subprocesses to spawn', 2]),
28-
Msf::OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)'])
29-
])
26+
register_advanced_options(
27+
[
28+
OptInt.new('Spawn', [true, 'Number of subprocesses to spawn', 2]),
29+
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
30+
] +
31+
Msf::Opt::http_header_options
32+
)
3033
end
3134

3235
#
@@ -64,6 +67,10 @@ def stager_config(opts={})
6467

6568
c = ''
6669
c << "Spawn=#{ds["Spawn"] || 2}\n"
70+
c << "HeaderUser-Agent=#{ds["HttpUserAgent"]}\n" if ds["HttpUserAgent"]
71+
c << "HeaderHost=#{ds["HttpHostHeader"]}\n" if ds["HttpHostHeader"]
72+
c << "HeaderReferer=#{ds["HttpReferer"]}\n" if ds["HttpReferer"]
73+
c << "HeaderCookie=#{ds["HttpCookie"]}\n" if ds["HttpCookie"]
6774
c << "URL=#{scheme}://#{ds['LHOST']}"
6875
c << ":#{ds['LPORT']}" if ds['LPORT']
6976
c << luri

lib/msf/core/payload/multi/reverse_http.rb

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,12 @@ module Payload::Multi::ReverseHttp
2222
#
2323
def initialize(*args)
2424
super
25-
register_advanced_options([
26-
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
27-
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10],
28-
aliases: ['ReverseConnectRetries']),
29-
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']),
30-
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
31-
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
32-
OptString.new('PayloadProxyPass', [false, 'An optional proxy server password']),
33-
OptEnum.new('PayloadProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']])
34-
])
25+
register_advanced_options(
26+
[ OptInt.new('StagerURILength', 'The URI length for the stager (at least 5 bytes)') ] +
27+
Msf::Opt::stager_retry_options +
28+
Msf::Opt::http_header_options +
29+
Msf::Opt::http_proxy_options
30+
)
3531
end
3632

3733
#
@@ -67,4 +63,3 @@ def wfs_delay
6763
end
6864

6965
end
70-

0 commit comments

Comments
 (0)