Skip to content

Commit b60398b

Browse files
committed
Merge branch 'upstream/master' into clipboard_monitor
Conflicts: lib/rex/post/meterpreter/extensions/extapi/tlv.rb
2 parents ad1dce3 + 10ac7a2 commit b60398b

File tree

296 files changed

+2076
-969
lines changed

Some content is hidden

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

296 files changed

+2076
-969
lines changed

lib/msf/base/sessions/meterpreter.rb

Lines changed: 62 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -303,52 +303,20 @@ def load_session_info()
303303
safe_info.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"_")
304304
self.info = safe_info
305305

306-
# Enumerate network interfaces to detect IP
307-
ifaces = self.net.config.get_interfaces().flatten rescue []
308-
routes = self.net.config.get_routes().flatten rescue []
309-
shost = self.session_host
310-
311-
# Try to match our visible IP to a real interface
312-
# TODO: Deal with IPv6 addresses
313-
found = !!(ifaces.find {|i| i.addrs.find {|a| a == shost } })
314-
nhost = nil
315-
hobj = nil
316-
317-
if Rex::Socket.is_ipv4?(shost) and not found
318-
319-
# Try to find an interface with a default route
320-
default_routes = routes.select{ |r| r.subnet == "0.0.0.0" || r.subnet == "::" }
321-
default_routes.each do |r|
322-
ifaces.each do |i|
323-
bits = Rex::Socket.net2bitmask( i.netmask ) rescue 32
324-
rang = Rex::Socket::RangeWalker.new( "#{i.ip}/#{bits}" ) rescue nil
325-
if rang and rang.include?( r.gateway )
326-
nhost = i.ip
327-
break
328-
end
329-
end
330-
break if nhost
331-
end
306+
hobj = nil
332307

333-
# Find the first non-loopback address
334-
if not nhost
335-
iface = ifaces.select{|i| i.ip != "127.0.0.1" and i.ip != "::1" }
336-
if iface.length > 0
337-
nhost = iface.first.ip
338-
end
339-
end
340-
end
308+
nhost = find_internet_connected_address
341309

310+
original_session_host = self.session_host
342311
# If we found a better IP address for this session, change it up
343312
# only handle cases where the DB is not connected here
344-
if not (framework.db and framework.db.active)
313+
if !(framework.db && framework.db.active)
345314
self.session_host = nhost
346315
end
347316

348-
349317
# The rest of this requires a database, so bail if it's not
350318
# there
351-
return if not (framework.db and framework.db.active)
319+
return if !(framework.db && framework.db.active)
352320

353321
::ActiveRecord::Base.connection_pool.with_connection {
354322
wspace = framework.db.find_workspace(workspace)
@@ -384,18 +352,18 @@ def load_session_info()
384352
if nhost
385353
framework.db.report_note({
386354
:type => "host.nat.server",
387-
:host => shost,
355+
:host => original_session_host,
388356
:workspace => wspace,
389357
:data => { :info => "This device is acting as a NAT gateway for #{nhost}", :client => nhost },
390358
:update => :unique_data
391359
})
392-
framework.db.report_host(:host => shost, :purpose => 'firewall' )
360+
framework.db.report_host(:host => original_session_host, :purpose => 'firewall' )
393361

394362
framework.db.report_note({
395363
:type => "host.nat.client",
396364
:host => nhost,
397365
:workspace => wspace,
398-
:data => { :info => "This device is traversing NAT gateway #{shost}", :server => shost },
366+
:data => { :info => "This device is traversing NAT gateway #{original_session_host}", :server => original_session_host },
399367
:update => :unique_data
400368
})
401369
framework.db.report_host(:host => nhost, :purpose => 'client' )
@@ -470,6 +438,60 @@ def create(param)
470438

471439
attr_accessor :rstream # :nodoc:
472440

441+
# Rummage through this host's routes and interfaces looking for an
442+
# address that it uses to talk to the internet.
443+
#
444+
# @see Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config#get_interfaces
445+
# @see Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config#get_routes
446+
# @return [String] The address from which this host reaches the
447+
# internet, as ASCII. e.g.: "192.168.100.156"
448+
def find_internet_connected_address
449+
450+
ifaces = self.net.config.get_interfaces().flatten rescue []
451+
routes = self.net.config.get_routes().flatten rescue []
452+
453+
# Try to match our visible IP to a real interface
454+
found = !!(ifaces.find { |i| i.addrs.find { |a| a == session_host } })
455+
nhost = nil
456+
457+
# If the host has no address that matches what we see, then one of
458+
# us is behind NAT so we have to look harder.
459+
if !found
460+
# Grab all routes to the internet
461+
default_routes = routes.select { |r| r.subnet == "0.0.0.0" || r.subnet == "::" }
462+
463+
default_routes.each do |route|
464+
# Now try to find an interface whose network includes this
465+
# Route's gateway, which means it's the one the host uses to get
466+
# to the interweb.
467+
ifaces.each do |i|
468+
# Try all the addresses this interface has configured
469+
addr_and_mask = i.addrs.zip(i.netmasks).find do |addr, netmask|
470+
bits = Rex::Socket.net2bitmask( netmask )
471+
range = Rex::Socket::RangeWalker.new("#{addr}/#{bits}") rescue nil
472+
473+
!!(range && range.valid? && range.include?(route.gateway))
474+
end
475+
if addr_and_mask
476+
nhost = addr_and_mask[0]
477+
break
478+
end
479+
end
480+
break if nhost
481+
end
482+
483+
if !nhost
484+
# Find the first non-loopback address
485+
non_loopback = ifaces.find { |i| i.ip != "127.0.0.1" && i.ip != "::1" }
486+
if non_loopback
487+
nhost = non_loopback.ip
488+
end
489+
end
490+
end
491+
492+
nhost
493+
end
494+
473495
end
474496

475497
end

lib/msf/core/db.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5631,19 +5631,19 @@ def find_qualys_asset_vuln_refs(doc)
56315631

56325632
# Pull out vulnerabilities that have at least one matching
56335633
# ref -- many "vulns" are not vulns, just audit information.
5634-
def find_qualys_asset_vulns(host,wspace,hobj,vuln_refs,&block)
5634+
def find_qualys_asset_vulns(host,wspace,hobj,vuln_refs,task_id,&block)
56355635
host.elements.each("VULN_INFO_LIST/VULN_INFO") do |vi|
56365636
next unless vi.elements["QID"]
56375637
vi.elements.each("QID") do |qid|
56385638
next if vuln_refs[qid.text].nil? || vuln_refs[qid.text].empty?
5639-
handle_qualys(wspace, hobj, nil, nil, qid.text, nil, vuln_refs[qid.text], nil,nil, args[:task])
5639+
handle_qualys(wspace, hobj, nil, nil, qid.text, nil, vuln_refs[qid.text], nil, nil, task_id)
56405640
end
56415641
end
56425642
end
56435643

56445644
# Takes QID numbers and finds the discovered services in
56455645
# a qualys_asset_xml.
5646-
def find_qualys_asset_ports(i,host,wspace,hobj)
5646+
def find_qualys_asset_ports(i,host,wspace,hobj,task_id)
56475647
return unless (i == 82023 || i == 82004)
56485648
proto = i == 82023 ? 'tcp' : 'udp'
56495649
qid = host.elements["VULN_INFO_LIST/VULN_INFO/QID[@id='qid_#{i}']"]
@@ -5656,7 +5656,7 @@ def find_qualys_asset_ports(i,host,wspace,hobj)
56565656
else
56575657
name = match[2].strip
56585658
end
5659-
handle_qualys(wspace, hobj, match[0].to_s, proto, 0, nil, nil, name, nil, args[:task])
5659+
handle_qualys(wspace, hobj, match[0].to_s, proto, 0, nil, nil, name, nil, task_id)
56605660
end
56615661
end
56625662
end
@@ -5700,11 +5700,11 @@ def import_qualys_asset_xml(args={}, &block)
57005700
end
57015701

57025702
# Report open ports.
5703-
find_qualys_asset_ports(82023,host,wspace,hobj) # TCP
5704-
find_qualys_asset_ports(82004,host,wspace,hobj) # UDP
5703+
find_qualys_asset_ports(82023,host,wspace,hobj, args[:task]) # TCP
5704+
find_qualys_asset_ports(82004,host,wspace,hobj, args[:task]) # UDP
57055705

57065706
# Report vulns
5707-
find_qualys_asset_vulns(host,wspace,hobj,vuln_refs,&block)
5707+
find_qualys_asset_vulns(host,wspace,hobj,vuln_refs, args[:task],&block)
57085708

57095709
end # host
57105710

lib/msf/core/exploit.rb

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,33 +65,41 @@ module CompatDefaults
6565
##
6666
#
6767
# The various check codes that can be returned from the ``check'' routine.
68+
# Please read the following wiki to learn how these codes are used:
69+
# https://github.com/rapid7/metasploit-framework/wiki/How-to-write-a-check()-method
6870
#
6971
##
7072
module CheckCode
7173

7274
#
73-
# Can't tell if the target is exploitable or not.
75+
# Can't tell if the target is exploitable or not. This is recommended if the module fails to
76+
# retrieve enough information from the target machine, such as due to a timeout.
7477
#
7578
Unknown = [ 'unknown', "Cannot reliably check exploitability."]
7679

7780
#
78-
# The target is safe and is therefore not exploitable.
81+
# The target is safe and is therefore not exploitable. This is recommended after the check
82+
# fails to trigger the vulnerability, or even detect the service.
7983
#
8084
Safe = [ 'safe', "The target is not exploitable." ]
8185

8286
#
83-
# The target is running the service in question but may not be
84-
# exploitable.
87+
# The target is running the service in question, but the check fails to determine whether
88+
# the target is vulnerable or not.
8589
#
8690
Detected = [ 'detected', "The target service is running, but could not be validated." ]
8791

8892
#
89-
# The target appears to be vulnerable.
93+
# The target appears to be vulnerable. This is recommended if the vulnerability is determined
94+
# based on passive reconnaissance. For example: version, banner grabbing, or having the resource
95+
# that's known to be vulnerable.
9096
#
9197
Appears = [ 'appears', "The target appears to be vulnerable." ]
9298

9399
#
94-
# The target is vulnerable.
100+
# The target is vulnerable. Only used if the check is able to actually take advantage of the
101+
# bug, and obtain hard evidence. For example: executing a command on the target machine, and
102+
# retrieve the output.
95103
#
96104
Vulnerable = [ 'vulnerable', "The target is vulnerable." ]
97105

lib/msf/core/exploit/http/client.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,14 @@ def connect(opts={})
187187
'uri_fake_end' => datastore['HTTP::uri_fake_end'],
188188
'uri_fake_params_start' => datastore['HTTP::uri_fake_params_start'],
189189
'header_folding' => datastore['HTTP::header_folding'],
190-
'usentlm2_session' => datastore['NTLM::UseNTLM2_session'],
191-
'use_ntlmv2' => datastore['NTLM::UseNTLMv2'],
192-
'send_lm' => datastore['NTLM::SendLM'],
193-
'send_ntlm' => datastore['NTLM::SendNTLM'],
194-
'SendSPN' => datastore['NTLM::SendSPN'],
195-
'UseLMKey' => datastore['NTLM::UseLMKey'],
196-
'domain' => datastore['DOMAIN'],
197-
'DigestAuthIIS' => datastore['DigestAuthIIS']
190+
'usentlm2_session' => datastore['NTLM::UseNTLM2_session'],
191+
'use_ntlmv2' => datastore['NTLM::UseNTLMv2'],
192+
'send_lm' => datastore['NTLM::SendLM'],
193+
'send_ntlm' => datastore['NTLM::SendNTLM'],
194+
'SendSPN' => datastore['NTLM::SendSPN'],
195+
'UseLMKey' => datastore['NTLM::UseLMKey'],
196+
'domain' => datastore['DOMAIN'],
197+
'DigestAuthIIS' => datastore['DigestAuthIIS']
198198
)
199199

200200
# If this connection is global, persist it

lib/msf/core/exploit/http/server.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ def start_service(opts = {})
181181
'MsfExploit' => self,
182182
},
183183
opts['Comm'],
184-
datastore['SSLCert']
184+
datastore['SSLCert'],
185+
datastore['SSLCompression']
185186
)
186187

187188
self.service.server_name = datastore['HTTP::server_name']
@@ -200,6 +201,13 @@ def start_service(opts = {})
200201

201202
proto = (datastore["SSL"] ? "https" : "http")
202203

204+
# SSLCompression may or may not actually be available. For example, on
205+
# Ubuntu, it's disabled by default, unless the correct environment
206+
# variable is set. See https://github.com/rapid7/metasploit-framework/pull/2666
207+
if proto == "https" and datastore['SSLCompression']
208+
print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!")
209+
end
210+
203211
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
204212

205213
if (opts['ServerHost'] == '0.0.0.0')

lib/msf/core/exploit/tcp.rb

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,15 @@ def connect(global = true, opts={})
9898
end
9999

100100
nsock = Rex::Socket::Tcp.create(
101-
'PeerHost' => opts['RHOST'] || rhost,
102-
'PeerPort' => (opts['RPORT'] || rport).to_i,
103-
'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
104-
'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
105-
'SSL' => dossl,
106-
'SSLVersion'=> opts['SSLVersion'] || ssl_version,
107-
'Proxies' => proxies,
108-
'Timeout' => (opts['ConnectTimeout'] || connect_timeout || 10).to_i,
109-
'Context' =>
101+
'PeerHost' => opts['RHOST'] || rhost,
102+
'PeerPort' => (opts['RPORT'] || rport).to_i,
103+
'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
104+
'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
105+
'SSL' => dossl,
106+
'SSLVersion' => opts['SSLVersion'] || ssl_version,
107+
'Proxies' => proxies,
108+
'Timeout' => (opts['ConnectTimeout'] || connect_timeout || 10).to_i,
109+
'Context' =>
110110
{
111111
'Msf' => framework,
112112
'MsfExploit' => self,
@@ -300,6 +300,7 @@ def initialize(info = {})
300300
register_advanced_options(
301301
[
302302
OptString.new('ListenerComm', [ false, 'The specific communication channel to use for this service']),
303+
OptBool.new('SSLCompression', [ false, 'Enable SSL/TLS-level compression', false ])
303304
], Msf::Exploit::Remote::TcpServer)
304305

305306
register_evasion_options(
@@ -379,6 +380,7 @@ def start_service(*args)
379380
'LocalPort' => srvport,
380381
'SSL' => ssl,
381382
'SSLCert' => ssl_cert,
383+
'SSLCompression' => opts['SSLCompression'] || ssl_compression,
382384
'Comm' => comm,
383385
'Context' =>
384386
{
@@ -464,6 +466,11 @@ def ssl_cert
464466
datastore['SSLCert']
465467
end
466468

469+
# @return [Bool] enable SSL/TLS-level compression
470+
def ssl_compression
471+
datastore['SSLCompression']
472+
end
473+
467474
#
468475
# Re-generates the payload, substituting the current RHOST and RPORT with
469476
# the supplied client host and port from the socket.

lib/msf/core/post/windows.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
module Msf::Post::Windows
33
require 'msf/core/post/windows/error'
4+
require 'msf/core/post/windows/extapi'
45
require 'msf/core/post/windows/accounts'
56
require 'msf/core/post/windows/cli_parse'
67
require 'msf/core/post/windows/eventlog'
@@ -13,4 +14,5 @@ module Msf::Post::Windows
1314
require 'msf/core/post/windows/services'
1415
require 'msf/core/post/windows/shadowcopy'
1516
require 'msf/core/post/windows/user_profiles'
17+
require 'msf/core/post/windows/ldap'
1618
end
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: binary -*-
2+
3+
module Msf
4+
class Post
5+
module Windows
6+
7+
module ExtAPI
8+
9+
def load_extapi
10+
if session.extapi
11+
return true
12+
else
13+
begin
14+
return session.core.use("extapi")
15+
rescue Errno::ENOENT
16+
print_error("Unable to load Extended API.")
17+
return false
18+
end
19+
end
20+
end
21+
22+
end # ExtAPI
23+
end # Windows
24+
end # Post
25+
end # Msf

0 commit comments

Comments
 (0)