1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-05 14:57:30 +01:00

Merge pull request #4 from jlee-r7/feature/recog

Feature/recog
This commit is contained in:
HD Moore 2014-10-01 16:43:18 -05:00
commit 4dd285c319
4 changed files with 76 additions and 74 deletions

View File

@ -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

View File

@ -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();
<%

View File

@ -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']})"

View File

@ -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)