mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
commit
4dd285c319
@ -445,28 +445,28 @@ module Exploit::Remote::HttpClient
|
||||
# destination host and port. This method falls back to using the old
|
||||
# service.info field to represent the HTTP Server header.
|
||||
#
|
||||
# Options:
|
||||
# @option opts [String] :uri An HTTP URI to request in order to generate a fingerprint
|
||||
# @option opts [String] :method An HTTP method to use in the fingerprint request
|
||||
#
|
||||
# @option opts [String] :uri ('/') An HTTP URI to request in order to generate
|
||||
# a fingerprint
|
||||
# @option opts [String] :method ('GET') An HTTP method to use in the fingerprint
|
||||
# request
|
||||
def lookup_http_fingerprints(opts={})
|
||||
uri = opts[:uri] || '/'
|
||||
method = opts[:method] || 'GET'
|
||||
fprints = []
|
||||
|
||||
|
||||
return fprints unless framework.db.active
|
||||
|
||||
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
wspace = datastore['WORKSPACE'] ?
|
||||
framework.db.find_workspace(datastore['WORKSPACE']) : framework.db.workspace
|
||||
|
||||
service = framework.db.get_service(wspace, rhost, 'tcp', rport)
|
||||
return fprints unless service
|
||||
|
||||
|
||||
# Order by note_id descending so the first value is the most recent
|
||||
service.notes.where(:ntype => 'http.fingerprint').order("notes.id DESC").each do |n|
|
||||
next unless n.data and n.data.kind_of?(::Hash)
|
||||
next unless n.data[:uri] == uri and n.data[:method] == method
|
||||
next unless n.data && n.data.kind_of?(::Hash)
|
||||
next unless n.data[:uri] == uri && n.data[:method] == method
|
||||
# Append additional fingerprints to the results as found
|
||||
fprints.unshift n.data.dup
|
||||
end
|
||||
@ -481,14 +481,18 @@ module Exploit::Remote::HttpClient
|
||||
# will use it directly, otherwise it will check the database for a previous
|
||||
# fingerprint. Failing that, it will make a request for /.
|
||||
#
|
||||
# Options:
|
||||
# :response an Http::Packet as returned from any of the send_* methods
|
||||
# :uri an HTTP URI to request in order to generate a fingerprint
|
||||
# :method an HTTP method to use in the fingerprint request
|
||||
# :full request the full HTTP fingerprint, not just the signature
|
||||
# Other options are passed directly to {#connect} if :response is not given
|
||||
#
|
||||
# Other options are passed directly to +connect+ if :response is not given
|
||||
# @option opts [Rex::Proto::Http::Packet] :response The return value from any
|
||||
# of the send_* methods
|
||||
# @option opts [String] :uri ('/') An HTTP URI to request in order to generate
|
||||
# a fingerprint
|
||||
# @option opts [String] :method ('GET') An HTTP method to use in the fingerprint
|
||||
# request
|
||||
# @option opts [Boolean] :full (false) Request the full HTTP fingerprint, not
|
||||
# just the signature
|
||||
#
|
||||
# @return [String]
|
||||
def http_fingerprint(opts={})
|
||||
res = nil
|
||||
uri = opts[:uri] || '/'
|
||||
@ -502,7 +506,7 @@ module Exploit::Remote::HttpClient
|
||||
fprints = lookup_http_fingerprints(opts)
|
||||
|
||||
if fprints.length > 0
|
||||
|
||||
|
||||
# Grab the most recent fingerprint available for this service, uri, and method
|
||||
fprint = fprints.last
|
||||
|
||||
@ -528,9 +532,9 @@ module Exploit::Remote::HttpClient
|
||||
# This section handles a few simple cases of pattern matching and service
|
||||
# classification. This logic should be deprecated in favor of Recog-based
|
||||
# fingerprint databases, but has been left in place for backward compat.
|
||||
|
||||
|
||||
extras = []
|
||||
|
||||
|
||||
if res.headers['Set-Cookie'] =~ /^vmware_soap_session/
|
||||
extras << "VMWare Web Services"
|
||||
end
|
||||
@ -601,8 +605,8 @@ module Exploit::Remote::HttpClient
|
||||
info << " ( #{extras.join(", ")} )" if extras.length > 0
|
||||
|
||||
# Create a new fingerprint structure to track this response
|
||||
fprint = {
|
||||
:uri => uri, :method => method,
|
||||
fprint = {
|
||||
:uri => uri, :method => method,
|
||||
:code => res.code.to_s, :message => res.message.to_s,
|
||||
:signature => info
|
||||
}
|
||||
@ -614,7 +618,7 @@ module Exploit::Remote::HttpClient
|
||||
# Set-Cookie > :header_set_cookie => JSESSIONID=AAASD23423452
|
||||
# Server > :header_server => Apache/1.3.37
|
||||
# WWW-Authenticate > :header_www_authenticate => basic realm='www'
|
||||
|
||||
|
||||
fprint["header_#{hname}".intern] = v
|
||||
end
|
||||
|
||||
@ -623,22 +627,22 @@ module Exploit::Remote::HttpClient
|
||||
|
||||
# Report a new http.fingerprint note
|
||||
report_note(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:ntype => 'http.fingerprint',
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:ntype => 'http.fingerprint',
|
||||
:data => fprint,
|
||||
# Limit reporting to one stored note per host/service combination
|
||||
# Limit reporting to one stored note per host/service combination
|
||||
:update => :unique
|
||||
)
|
||||
|
||||
# Report here even if info is empty since the fact that we didn't
|
||||
# return early means we at least got a connection and the service is up
|
||||
report_web_site(:host => rhost, :port => rport, :ssl => ssl, :vhost => vhost, :info => info.dup)
|
||||
|
||||
|
||||
# Return the full HTTP fingerprint if requested by the caller
|
||||
return fprint if opts[:full]
|
||||
|
||||
|
||||
# Otherwise just return the signature string for compatibility
|
||||
fprint[:signature]
|
||||
end
|
||||
|
@ -362,7 +362,7 @@ module Msf
|
||||
<%= js_os_detect %>
|
||||
<%= js_ajax_post %>
|
||||
<%= js_misc_addons_detect %>
|
||||
<%= js_ie_addons_detect if os.match(/^Windows/) and client == HttpClients::IE %>
|
||||
<%= js_ie_addons_detect if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %>
|
||||
|
||||
function objToQuery(obj) {
|
||||
var q = [];
|
||||
@ -388,7 +388,7 @@ module Msf
|
||||
"<%=REQUIREMENT_KEY_SET[:flash]%>" : window.misc_addons_detect.getFlashVersion()
|
||||
};
|
||||
|
||||
<% if os.match(/^Windows/) and client == HttpClients::IE %>
|
||||
<% if os.match(OperatingSystems::Match::WINDOWS) and client == HttpClients::IE %>
|
||||
d['<%=REQUIREMENT_KEY_SET[:office]%>'] = window.ie_addons_detect.getMsOfficeVersion();
|
||||
d['<%=REQUIREMENT_KEY_SET[:mshtml_build]%>'] = ScriptEngineBuildVersion().toString();
|
||||
<%
|
||||
|
@ -34,6 +34,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
|
||||
deregister_options('RPORT')
|
||||
deregister_options('SMBDIRECT')
|
||||
@smb_port = 445
|
||||
end
|
||||
|
||||
@ -42,7 +43,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def smb_direct
|
||||
@smbdirect || datastore['SMBDirect']
|
||||
(@smb_port == 445)
|
||||
end
|
||||
|
||||
# Fingerprint a single host
|
||||
@ -55,10 +56,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
begin
|
||||
res = smb_fingerprint()
|
||||
|
||||
|
||||
#
|
||||
# Create the note hash for smb.fingerprint
|
||||
#
|
||||
#
|
||||
conf = {
|
||||
:native_os => res['native_os'],
|
||||
:native_lm => res['native_lm']
|
||||
@ -82,7 +83,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
match_conf['os.edition'] = res['edition']
|
||||
end
|
||||
|
||||
if res['sp'].to_s.length > 0
|
||||
if res['sp'].to_s.length > 0
|
||||
desc << " #{res['sp'].downcase.gsub('service pack ', 'SP')}"
|
||||
conf[:os_sp] = res['sp']
|
||||
match_conf['os.version'] = res['sp']
|
||||
@ -95,7 +96,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if res['lang'].to_s.length > 0 and res['lang'] != 'Unknown'
|
||||
desc << " (language:#{res['lang']}"
|
||||
desc << " (language:#{res['lang']})"
|
||||
conf[:os_lang] = res['lang']
|
||||
match_conf['os.language'] = conf[:os_lang]
|
||||
end
|
||||
@ -130,7 +131,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
:port => rport,
|
||||
:proto => 'tcp',
|
||||
:ntype => 'fingerprint.match',
|
||||
:data => match_conf
|
||||
:data => match_conf
|
||||
)
|
||||
else
|
||||
desc = "#{res['native_os']} (#{res['native_lm']})"
|
||||
|
@ -66,11 +66,11 @@ class Metasploit3 < Msf::Post
|
||||
|
||||
# Results table holds raw string data
|
||||
results_table = Rex::Ui::Text::Table.new(
|
||||
'Header' => "Domain Computers",
|
||||
'Indent' => 1,
|
||||
'SortIndex' => -1,
|
||||
'Columns' => fields
|
||||
)
|
||||
'Header' => "Domain Computers",
|
||||
'Indent' => 1,
|
||||
'SortIndex' => -1,
|
||||
'Columns' => fields
|
||||
)
|
||||
|
||||
# Hostnames holds DNS Names to Resolve
|
||||
hostnames = []
|
||||
@ -81,40 +81,37 @@ class Metasploit3 < Msf::Post
|
||||
|
||||
report = {}
|
||||
0.upto(fields.length-1) do |i|
|
||||
if result[i].nil?
|
||||
field = ""
|
||||
else
|
||||
field = result[i]
|
||||
field = result[i] || ""
|
||||
|
||||
# Only perform these actions if the database is connected and we want
|
||||
# to store in the DB.
|
||||
if db and datastore['STORE_DB']
|
||||
case fields[i]
|
||||
when 'dNSHostName'
|
||||
dns = field
|
||||
report[:name] = dns
|
||||
hostnames << dns
|
||||
when 'operatingSystem'
|
||||
report[:os_name] = os
|
||||
when 'distinguishedName'
|
||||
if field =~ /Domain Controllers/i
|
||||
# TODO: Find another way to mark a host as being a domain controller
|
||||
# The 'purpose' field should be server, client, device, printer, etc
|
||||
# report[:purpose] = "DC"
|
||||
end
|
||||
when 'operatingSystemServicePack'
|
||||
# XXX: Does this take into account the leading 'SP' string?
|
||||
|
||||
if field.to_i > 0
|
||||
report[:os_sp] = 'SP' + field
|
||||
end
|
||||
if field =~ /(Service Pack|SP)\s?(\d+)/
|
||||
report[:os_sp] = 'SP' + $2
|
||||
end
|
||||
|
||||
when 'description'
|
||||
report[:info] = field
|
||||
# Only perform these actions if the database is connected and we want
|
||||
# to store in the DB.
|
||||
if db && datastore['STORE_DB']
|
||||
case fields[i]
|
||||
when 'dNSHostName'
|
||||
dns = field
|
||||
report[:name] = dns
|
||||
hostnames << dns
|
||||
when 'operatingSystem'
|
||||
report[:os_name] = field
|
||||
when 'distinguishedName'
|
||||
if field =~ /Domain Controllers/i
|
||||
# TODO: Find another way to mark a host as being a domain controller
|
||||
# The 'purpose' field should be server, client, device, printer, etc
|
||||
#report[:purpose] = "DC"
|
||||
report[:purpose] = "server"
|
||||
end
|
||||
when 'operatingSystemServicePack'
|
||||
# XXX: Does this take into account the leading 'SP' string?
|
||||
|
||||
if field.to_i > 0
|
||||
report[:os_sp] = 'SP' + field
|
||||
end
|
||||
if field =~ /(Service Pack|SP)\s?(\d+)/
|
||||
report[:os_sp] = 'SP' + $2
|
||||
end
|
||||
|
||||
when 'description'
|
||||
report[:info] = field
|
||||
end
|
||||
end
|
||||
|
||||
@ -125,7 +122,7 @@ class Metasploit3 < Msf::Post
|
||||
results_table << row
|
||||
end
|
||||
|
||||
if db and datastore['STORE_DB']
|
||||
if db && datastore['STORE_DB']
|
||||
print_status("Resolving IP addresses...")
|
||||
ip_results = client.net.resolve.resolve_hosts(hostnames, AF_INET)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user