massive changes to the database api. Auxiliary::Report is now just a bunch of stubs into the main DBManager, most aux modules should just work, but they haven't all been tested. introduces a get_auth_info method for pulling credentials out of the db. other db api methods should be more standardized now. cross your fingers

git-svn-id: file:///home/svn/framework3/trunk@8028 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
James Lee 2009-12-29 23:48:45 +00:00
parent c3038d4027
commit 02eb7ab80d
15 changed files with 576 additions and 476 deletions

View File

@ -8,31 +8,6 @@ module Msf
module Auxiliary::Report module Auxiliary::Report
module HttpClients
IE = "MSIE"
FF = "Firefox"
SAFARI = "Safari"
OPERA = "Opera"
UNKNOWN = "Unknown"
end
module OperatingSystems
LINUX = "Linux"
MAC_OSX = "MacOSX"
WINDOWS = "Windows"
module WindowsVersions
XP = "XP"
TWOK = "2000"
TWOK3 = "2003"
VISTA = "Vista"
end
UNKNOWN = "Unknown"
end
# Shortcut method for detecting when the DB is active # Shortcut method for detecting when the DB is active
def db def db
framework.db.active framework.db.active
@ -48,22 +23,12 @@ module Auxiliary::Report
# #
def report_host(opts) def report_host(opts)
return if not db return if not db
addr = opts[:host] || return framework.db.report_host(opts)
framework.db.queue Proc.new {
framework.db.report_host_state(self, addr, Msf::HostState::Alive)
host = nil
opts.delete(:host)
if (opts.length > 0)
host = framework.db.report_host(self, addr, opts)
end
}
end end
def get_host(addr) def get_host(addr)
return nil if not db return if not db
framework.db.get_host(self, addr) framework.db.get_host(addr)
end end
# #
@ -78,17 +43,12 @@ module Auxiliary::Report
# #
def report_client(opts={}) def report_client(opts={})
return if not db return if not db
addr = opts.delete(:host) || return framework.db.report_client(opts)
framework.db.queue Proc.new {
framework.db.report_host_state(self, addr, Msf::HostState::Alive)
cli = framework.db.report_client(self, addr, opts)
}
end end
def get_client(addr, ua_string) def get_client(opts={})
return nil if not db return if not db
framework.db.get_client(self, addr, ua_string) framework.db.get_client(opts)
end end
# #
@ -96,114 +56,27 @@ module Auxiliary::Report
# #
def report_service(opts={}) def report_service(opts={})
return if not db return if not db
addr = opts[:host] || return framework.db.report_service(opts)
port = opts[:port] || return
proto = opts[:proto] || 'tcp'
name = opts[:name]
state = opts[:state] || 'open'
info = opts[:info]
hname = opts[:host_name]
maddr = opts[:host_mac]
framework.db.queue Proc.new {
framework.db.report_host_state(self, addr, Msf::HostState::Alive)
serv = framework.db.report_service_state(
self,
addr,
proto,
port,
state
)
changed = false
if(hname)
self.host.name = hname
changed = true
end
if(maddr)
self.host.mac = maddr
changed = true
end
serv.host.save! if changed
changed = false
if (name and name.length > 1)
serv.name = name.downcase
changed = true
end
if (info and info.length > 1)
serv.info = info
changed = true
end
serv.save! if changed
}
end end
def report_note(opts={}) def report_note(opts={})
return if not db return if not db
addr = opts[:host] || return framework.db.report_note(opts)
ntype = opts[:type] || return
data = opts[:data] || return
framework.db.queue Proc.new {
host = framework.db.report_host_state(self, addr, Msf::HostState::Alive)
note = framework.db.get_note(self, host, ntype, data)
}
end
def report_vuln_service(opts={})
return if not db
framework.db.queue Proc.new {
serv = report_service(opts)
return if not serv
vname = opts[:vname]
vdata = opts[:vdata] || ''
host = serv.host
vuln = framework.db.get_vuln(self, host, serv, vname, vdata)
framework.db.vuln_add_refs(self, vuln, opts[:refs])
}
end
def report_vuln_host(opts={})
return if not db
addr = opts[:host] || return
framework.db.queue Proc.new {
host = framework.db.report_host_state(self, addr, Msf::HostState::Alive)
vname = opts[:vname]
vdata = opts[:vdata] || ''
vuln = framework.db.get_vuln(self, host, nil, vname, vdata)
framework.db.vuln_add_refs(self, vuln, opts[:refs])
}
end end
def report_auth_info(opts={}) def report_auth_info(opts={})
return if not db return if not db
addr = opts[:host] || return framework.db.report_auth_info(opts)
data = opts[:proto] || return
opts[:type] = "auth_#{opts[:proto]}"
opts[:data] =
"AUTH #{ opts[:targ_host] || 'unknown' }:#{ opts[:targ_port] || 'unknown' } " +
"#{opts[:user] || "<NULL>"} #{opts[:pass] || "<NULL>" } #{opts[:extra]}"
print_status("Recording successful #{data} credentials for #{addr}")
report_note(opts)
end end
def find_note(host, ntype) def report_vuln_service(opts={})
return if not db return if not db
framework.db.find_note(host, ntype) framework.db.report_vuln_service(opts)
end
def report_vuln_host(opts={})
return if not db
framework.db.report_vuln_host(opts)
end end

View File

@ -46,6 +46,28 @@ RankingName =
ExcellentRanking => "excellent" ExcellentRanking => "excellent"
} }
module HttpClients
IE = "MSIE"
FF = "Firefox"
SAFARI = "Safari"
OPERA = "Opera"
UNKNOWN = "Unknown"
end
module OperatingSystems
LINUX = "Linux"
MAC_OSX = "MacOSX"
WINDOWS = "Windows"
module WindowsVersions
XP = "XP"
TWOK = "2000"
TWOK3 = "2003"
VISTA = "Vista"
end
UNKNOWN = "Unknown"
end
end end
# #
@ -65,4 +87,4 @@ LICENSES =
BSD_LICENSE, BSD_LICENSE,
ARTISTIC_LICENSE, ARTISTIC_LICENSE,
UNKNOWN_LICENSE UNKNOWN_LICENSE
] ]

View File

@ -50,47 +50,47 @@ module DatabaseEvent
# #
# Called when an existing host's state changes # Called when an existing host's state changes
# #
def on_db_host_state(context, host, ostate) def on_db_host_state(host, ostate)
end end
# #
# Called when an existing service's state changes # Called when an existing service's state changes
# #
def on_db_service_state(context, host, port, ostate) def on_db_service_state(host, port, ostate)
end end
# #
# Called when a new host is added to the database. The host parameter is # Called when a new host is added to the database. The host parameter is
# of type Host. # of type Host.
# #
def on_db_host(context, host) def on_db_host(host)
end end
# #
# Called when a new client is added to the database. The client # Called when a new client is added to the database. The client
# parameter is of type Client. # parameter is of type Client.
# #
def on_db_client(context, client) def on_db_client(client)
end end
# #
# Called when a new service is added to the database. The service # Called when a new service is added to the database. The service
# parameter is of type Service. # parameter is of type Service.
# #
def on_db_service(context, service) def on_db_service(service)
end end
# #
# Called when an applicable vulnerability is found for a service. The vuln # Called when an applicable vulnerability is found for a service. The vuln
# parameter is of type Vuln. # parameter is of type Vuln.
# #
def on_db_vuln(context, vuln) def on_db_vuln(vuln)
end end
# #
# Called when a new reference is created. # Called when a new reference is created.
# #
def on_db_ref(context, ref) def on_db_ref(ref)
end end
end end
@ -109,42 +109,52 @@ class DBManager
res = Host.find(:all) res = Host.find(:all)
end end
#
# Reports a host as being in a given state by address.
#
def report_host_state(mod, addr, state, context = nil)
# TODO: use the current thread's Comm to find the host def default_workspace
comm = '' Workspace.default
host = get_host(context, addr, comm) end
ostate = host.state def find_workspace(name)
host.state = state Workspace.find_by_name(name)
host.save
framework.events.on_db_host_state(context, host, ostate)
return host
end end
# #
# Report a host's attributes such as operating system and service pack # Creates a new workspace in the database
# #
# At the time of this writing, the opts parameter can contain: def add_workspace(name)
# :state -- one of the Msf::HostState constants Workspace.find_or_create_by_name(name)
# :os_name -- one of the Msf::Auxiliary::Report::OperatingSystems constants end
# :os_flavor -- something like "XP" or "Gentoo"
# :os_sp -- something like "SP2"
# :os_lang -- something like "English" or "French"
# :arch -- one of the ARCH_* constants
#
# See <MSF install dir>/data/sql/*.sql for more info
#
def report_host(mod, addr, opts = {}, context = nil)
report_host_state(mod, addr, opts[:state] || Msf::HostState::Alive) def workspaces
opts.delete(:state) Workspace.find(:all)
end
host = get_host(context, addr, '')
#
# Find a host. Performs no database writes.
#
def get_host(opts)
if opts.kind_of? Host
return opts
elsif opts.kind_of? String
address = opts
else
address = opts[:addr] || opts[:address] || opts[:host] || return
return address if address.kind_of? Host
end
host = workspace.hosts.find_by_address(address)
return host
end
def find_or_initialize_host(opts)
addr = opts.delete(:host) || return
return addr if addr.kind_of? Host
#if opts[:comm] and opts[:comm].length > 0
# host = workspace.hosts.find_or_initialize_by_address_and_comm(addr, opts[:comm])
#else
host = workspace.hosts.find_or_initialize_by_address(addr)
#end
opts.each { |k,v| opts.each { |k,v|
if (host.attribute_names.include?(k.to_s)) if (host.attribute_names.include?(k.to_s))
@ -153,67 +163,62 @@ class DBManager
dlog("Unknown attribute for Host: #{k}") dlog("Unknown attribute for Host: #{k}")
end end
} }
host.state = HostState::Unknown if not host.state
host.save host.comm = '' if not host.comm
host.workspace = workspace if not host.workspace
return host return host
end end
#
# Exactly like report_host but ensures that the returned Host has been
# written to the database. Returns nil on error.
# #
# Report a client running on a host. def find_or_create_host(opts)
# host = find_or_initialize_host(opts)
# opts must contain :ua_string
# opts can contain :ua_name and :ua_ver if (host and host.changed?)
# host.created = Time.now
def report_client(mod, addr, opts = {}, context = nil) task = framework.db.queue( Proc.new { host.save! } )
if opts[:ua_string].nil? task.wait
elog("report_client requires a ua_string", 'db', LEV_0, caller) if task.status != :done
return return nil
end
# TODO: use the current thread's Comm to find the host
comm = ''
host = get_host(context, addr, comm)
cli = get_client(context, host, opts[:ua_string])
opts.each { |k,v|
if (cli.attribute_names.include?(k.to_s))
cli[k] = v
else
dlog("Unknown attribute for Client: #{k}")
end end
}
cli.save
return cli
end
#
# This method reports a host's service state.
#
def report_service_state(mod, addr, proto, port, state, context = nil)
# TODO: use the current thread's Comm to find the host
comm = ''
host = get_host(context, addr, comm)
port = get_service(context, host, proto, port, state)
ostate = port.state
port.state = state
port.save
if (ostate != state)
framework.events.on_db_service_state(context, host, port, ostate)
end end
return host
return port
end
def workspaces
Workspace.find(:all)
end end
# #
# This method iterates the hosts table calling the supplied block with the # Report a host's attributes such as operating system and service pack
# host instance of each entry. #
# The opts parameter MUST contain
# :address -- the host's ip address
#
# The opts parameter can contain:
# :state -- one of the Msf::HostState constants
# :os_name -- one of the Msf::OperatingSystems constants
# :os_flavor -- something like "XP" or "Gentoo"
# :os_sp -- something like "SP2"
# :os_lang -- something like "English" or "French"
# :arch -- one of the ARCH_* constants
# :mac -- the host's MAC address
#
# Returns a Host that may not have been written to the database yet.
# If you need to be sure that the insert succeeded, use
# find_or_create_host.
#
def report_host(opts)
host = find_or_initialize_host(opts)
if (host.changed?)
host.created = Time.now
framework.db.queue( Proc.new { host.save! } )
end
return host
end
#
# Iterates over the hosts table calling the supplied block with the host
# instance of each entry.
# #
def each_host(&block) def each_host(&block)
workspace.hosts.each do |host| workspace.hosts.each do |host|
@ -222,7 +227,7 @@ class DBManager
end end
# #
# This methods returns a list of all hosts in the database # Returns a list of all hosts in the database
# #
def hosts(only_up = false, addresses = nil) def hosts(only_up = false, addresses = nil)
conditions = {} conditions = {}
@ -231,8 +236,63 @@ class DBManager
workspace.hosts.all(:conditions => conditions, :order => :address) workspace.hosts.all(:conditions => conditions, :order => :address)
end end
def find_or_initialize_service(opts)
addr = opts.delete(:host) || return
host = find_or_create_host({:host => addr})
service = host.services.find_or_initialize_by_port_and_proto(opts[:port], opts[:proto])
opts.each { |k,v|
if (service.attribute_names.include?(k.to_s))
service[k] = v
else
dlog("Unknown attribute for Service: #{k}")
end
}
return service
end
def find_or_create_service(opts)
service = find_or_initialize_service(opts)
if (service and service.changed?)
service.created = Time.now
task = framework.db.queue(Proc.new { service.save! })
task.wait
if task.status != :done
return nil
end
end
return service
end
#
# Record a service in the database.
# #
# This method iterates the services table calling the supplied block with the # opts must contain
# :port -- the port where this service listens
# :proto -- the protocol (e.g. tcp, udp...)
#
# Returns a Service. Not guaranteed to have been written to the db yet.
# If you need to be sure that the insert succeeded, use
# find_or_create_service.
#
def report_service(opts)
service = find_or_initialize_service(opts)
if (service and service.changed?)
service.created = Time.now
framework.db.queue(Proc.new { service.save! })
end
return service
end
def get_service(host, proto, port)
host = get_host(host)
return if not host
return host.services.find_by_proto_and_port(proto, port)
end
#
# Iterates over the services table calling the supplied block with the
# service instance of each entry. # service instance of each entry.
# #
def each_service(&block) def each_service(&block)
@ -242,7 +302,7 @@ class DBManager
end end
# #
# This methods returns a list of all services in the database # Returns a list of all services in the database
# #
def services(only_up = false, proto = nil, addresses = nil, ports = nil, names = nil) def services(only_up = false, proto = nil, addresses = nil, ports = nil, names = nil)
conditions = {} conditions = {}
@ -254,6 +314,66 @@ class DBManager
workspace.services.all(:include => :host, :conditions => conditions, :order => "hosts.address, port") workspace.services.all(:include => :host, :conditions => conditions, :order => "hosts.address, port")
end end
def get_client(opts)
host = get_host(:host => opts[:host]) || return
client = host.clients.find(:first, :conditions => {:ua_string => opts[:ua_string]})
return client
end
def find_or_initialize_client(opts)
host = find_or_create_host(:host => opts.delete(:host))
return if not host
client = host.clients.find_or_initialize_by_ua_string(opts[:ua_string])
opts.each { |k,v|
if (client.attribute_names.include?(k.to_s))
client[k] = v
else
dlog("Unknown attribute for Client: #{k}")
end
}
return client
end
def find_or_create_client(opts)
client = find_or_initialize_client(opts)
if (client and client.changed?)
client.created = Time.now
task = framework.db.queue(Proc.new { client.save! })
task.wait
if task.status != :done
return nil
end
end
return client
end
#
# Report a client running on a host.
#
# opts must contain
# :ua_string -- the value of the User-Agent header
#
# opts can contain
# :ua_name -- one of the Msf::HttpClients constants
# :ua_ver -- detected version of the given client
#
# Returns a Client. Not guaranteed to have been written to the database.
# If you need to be sure that the insert succeeded, use
# find_or_create_client.
#
def report_client(opts)
client = find_or_initialize_client(opts)
if (client and client.changed?)
client.created = Time.now
framework.db.queue(Proc.new { client.save! })
end
return client
end
# #
# This method iterates the vulns table calling the supplied block with the # This method iterates the vulns table calling the supplied block with the
# vuln instance of each entry. # vuln instance of each entry.
@ -282,12 +402,50 @@ class DBManager
end end
# #
# Find a note matching this host address and note type # Find or create a note matching this type/data
# #
def find_note(address, ntype) def find_or_create_note(opts)
host = workspace.hosts.find_by_address(address) note = find_or_initialize_note(opts)
return nil if host.nil? if (note.changed?)
host.notes.find_by_ntype(ntype) note.created = Time.now
task = framework.db.queue(Proc.new {note.save!})
task.wait
if (task.status != :done)
return nil
end
end
return note
end
def find_or_initialize_note(opts)
ntype = opts.delete(:type) || opts.delete(:ntype) || return
data = opts[:data] || return
note = workspace.notes.find_or_initialize_by_ntype_and_data(ntype, data.to_yaml)
p note
if opts[:host]
if opts[:host].kind_of? Host
host = opts[:host].dup
else
host = find_or_create_host({:host => opts[:host]})
end
note.host = host
end
if opts[:service] and opts[:service].kind_of? Service
note.service = service
end
return note
end
def report_note(opts)
note = find_or_initialize_note(opts)
if (note and note.changed?)
note.created = Time.now
task = framework.db.queue(Proc.new {note.save!})
end
return note
end end
# #
@ -297,141 +455,150 @@ class DBManager
workspace.notes workspace.notes
end end
def default_workspace ###
Workspace.default # Specific notes
end ###
def find_workspace(name)
Workspace.find_by_name(name)
end
# #
# Creates a new workspace in the database # opts must contain
# :data -- a hash containing the authentication info
#
# opts can contain
# :host -- an ip address or Host
# :service -- a Service
# :proto -- the protocol
# :port -- the port
# #
def add_workspace(context, name) def report_auth_info(opts={})
Workspace.find_or_create_by_name(name) return if not framework.db.active
host = opts.delete(:host)
service = opts.delete(:service)
proto = opts.delete(:proto) || "generic"
proto = proto.downcase
note = {
:ntype => "auth:#{proto}",
:host => host,
:service => service,
:data => opts
}
report_note(note)
end end
# def get_auth_info(opts={})
# Find or create a host matching this address/comm return if not framework.db.active
# condition = ""
def get_host(context, address, comm='') condition_values = []
if comm.length > 0 if opts[:host]
host = workspace.hosts.find_by_address_and_comm(address, comm) host = get_host(opts[:host])
condition = "host_id == ?"
condition_values = host.id
end
if opts[:proto]
if condition.length > 0
condition << " and "
end
condition << "ntype = ?"
condition_values << "auth:#{opts[:proto].downcase}"
else else
host = workspace.hosts.find_by_address(address) if condition.length > 0
condition << " and "
end
condition << "ntype LIKE ?"
condition_values << "auth:%"
end end
if (not host) conditions = [ condition ] + condition_values
host = workspace.hosts.create( info = framework.db.notes.find(:all, :conditions => conditions )
:address => address, return info.map{|i| i.data} if info
:comm => comm,
:state => HostState::Unknown,
:created => Time.now)
framework.events.on_db_host(context, host)
end
return host
end end
#
# Find or create a client on host that matches ua_string
#
def get_client(context, host, ua_string, comm='')
# Allow host to be an address to look up
if !host.kind_of? Host
host = get_host(context, host, comm)
end
return nil if host.nil?
rec = host.clients.find_by_ua_string(ua_string)
if (not rec)
rec = host.clients.create(
:ua_string => ua_string,
:created => Time.now
)
framework.events.on_db_client(context, rec)
end
return rec
end
# #
# Find or create a service matching this host/proto/port/state
# #
def get_service(context, host, proto, port, state=ServiceState::Up) #
rec = host.services.find_by_proto_and_port(proto, port) def find_or_initialize_vuln(opts)
if (not rec) host = find_or_create_host({:host => opts[:host]}) || return
rec = host.services.create( name = opts[:name] || return
:proto => proto, data = opts[:data]
:port => port,
:state => state, if data
:created => Time.now vuln = host.vulns.find_or_initialize_by_name_and_data(name, data)
) else
framework.events.on_db_service(context, rec) vuln = host.vulns.find_or_initialize_by_name(name)
end end
return rec p vuln
if opts[:service] and opts[:service].kind_of? Service
vuln.service = opts[:service]
end
return vuln
end end
# #
# Find or create a vuln matching this service/name # Find or create a vuln matching this service/name
# #
def get_vuln(context, host, service, name, data='') def find_or_create_vuln(opts)
vuln = nil vuln = find_or_initialize_vuln(opts)
if vuln and vuln.changed?
vuln.created = Time.now
task = framework.db.queue(Proc.new { vuln.save! })
task.wait
if task.status != :done
return nil
end
end
return vuln
end
#
#
#
def report_vuln(opts)
if vuln.changed?
vuln.created = Time.now
framework.db.queue(Proc.new { vuln.save! })
end
return vuln
end
def get_vuln(host, service, name, data='')
vuln = nil
if (service) if (service)
vuln = Vuln.find(:first, :conditions => [ "name = ? and service_id = ? and host_id = ?", name, service.id, host.id]) vuln = Vuln.find(:first, :conditions => [ "name = ? and service_id = ? and host_id = ?", name, service.id, host.id])
else else
vuln = Vuln.find(:first, :conditions => [ "name = ? and host_id = ?", name, host.id]) vuln = Vuln.find(:first, :conditions => [ "name = ? and host_id = ?", name, host.id])
end end
if (not vuln)
vuln = Vuln.create(
:service_id => service ? service.id : 0,
:host_id => host.id,
:name => name,
:data => data,
:created => Time.now
)
framework.events.on_db_vuln(context, vuln)
end
return vuln return vuln
end end
# #
# Find or create a reference matching this name # Find or create a reference matching this name
# #
def get_ref(context, name) def find_or_create_ref(opts)
ref = Ref.find_by_name(name) ref = Ref.find_or_initialize_by_name(opts[:name])
if (not ref) if ref and ref.changed?
ref = Ref.create( ref.created = Time.now
:name => name, task = framework.db.queue(Proc.new { ref.save! })
:created => Time.now task.wait
) if task.status != :done
framework.events.on_db_ref(context, ref) return nil
end
end end
return ref return ref
end end
def get_ref(name)
# Ref.find_by_name(name)
# Find or create a note matching this type/data
#
def get_note(context, host, ntype, data)
rec = host.notes.find_by_ntype_and_data(ntype, data)
if (not rec)
rec = host.notes.create(
:ntype => ntype,
:data => data,
:created => Time.now
)
framework.events.on_db_note(context, rec)
end
return rec
end end
# #
# Deletes a host and associated data matching this address/comm # Deletes a host and associated data matching this address/comm
# #
def del_host(context, address, comm='') def del_host(address, comm='')
host = workspace.hosts.find_by_address_and_comm(address, comm) host = workspace.hosts.find_by_address_and_comm(address, comm)
host.destroy if host host.destroy if host
end end
@ -439,8 +606,8 @@ class DBManager
# #
# Deletes a port and associated vulns matching this port # Deletes a port and associated vulns matching this port
# #
def del_service(context, address, proto, port, comm='') def del_service(address, proto, port, comm='')
host = get_host(context, address, comm) host = get_host(address, comm)
return unless host return unless host
host.services.find(:all, :conditions => { :proto => proto, :port => port}).destroy_all host.services.find(:all, :conditions => { :proto => proto, :port => port}).destroy_all
@ -467,9 +634,9 @@ class DBManager
workspace.hosts.find_by_address(addr) workspace.hosts.find_by_address(addr)
end end
def vuln_add_refs(context, vuln, refs) def vuln_add_refs(vuln, refs)
return vuln if not refs return vuln if not refs
rids = refs.map{|r| get_ref(context, "#{r[0]}-#{r[1]}") } rids = refs.map{|r| get_ref("#{r[0]}-#{r[1]}") }
vuln.refs << rids vuln.refs << rids
vuln vuln
end end
@ -669,7 +836,7 @@ class DBManager
:ssl => ssl, :ssl => ssl,
:selected => sel :selected => sel
) )
#framework.events.on_db_target(context, rec) #framework.events.on_db_target(rec)
end end
@ -690,10 +857,9 @@ class DBManager
:body => body, :body => body,
:respcode => respcode, :respcode => respcode,
:resphead => resphead, :resphead => resphead,
:response => response, :response => response
:created => Time.now
) )
#framework.events.on_db_request(context, rec) #framework.events.on_db_request(rec)
end end
# #

View File

@ -152,6 +152,7 @@ class DBManager
rescue ::Exception => e rescue ::Exception => e
self.error = e self.error = e
elog("DB.connect threw an exception: #{e}") elog("DB.connect threw an exception: #{e}")
dlog("Call stack: #{$@.join"\n"}", LEV_1)
return false return false
end end

View File

@ -10,8 +10,10 @@ class Host < ActiveRecord::Base
has_many :vulns, :dependent => :destroy has_many :vulns, :dependent => :destroy
has_many :notes, :dependent => :destroy has_many :notes, :dependent => :destroy
has_many :service_notes, :through => :services
validates_uniqueness_of :address, :scope => :workspace_id validates_uniqueness_of :address, :scope => :workspace_id
end end
end end
end end

View File

@ -3,8 +3,13 @@ class DBManager
class Note < ActiveRecord::Base class Note < ActiveRecord::Base
include DBSave include DBSave
belongs_to :workspace
belongs_to :host belongs_to :host
belongs_to :service
serialize :data
end end
end end
end end

View File

@ -4,8 +4,9 @@ class DBManager
class Service < ActiveRecord::Base class Service < ActiveRecord::Base
include DBSave include DBSave
has_many :vulns, :dependent => :destroy has_many :vulns, :dependent => :destroy
has_many :notes, :dependent => :destroy
belongs_to :host belongs_to :host
end end
end end
end end

View File

@ -7,11 +7,12 @@ class Workspace < ActiveRecord::Base
DEFAULT = "default" DEFAULT = "default"
has_many :hosts, :dependent => :destroy has_many :hosts, :dependent => :destroy
has_many :notes, :dependent => :destroy
has_many :services, :through => :hosts has_many :services, :through => :hosts
has_many :clients, :through => :hosts has_many :clients, :through => :hosts
has_many :vulns, :through => :hosts has_many :vulns, :through => :hosts
has_many :notes, :through => :hosts #has_many :notes, :through => :hosts
validates_uniqueness_of :name validates_uniqueness_of :name
validates_presence_of :name validates_presence_of :name
@ -26,4 +27,4 @@ class Workspace < ActiveRecord::Base
end end
end end
end end

View File

@ -319,16 +319,24 @@ class Db
end end
framework.db.each_note do |note| framework.db.each_note do |note|
next if(hosts and hosts.index(note.host.address) == nil) next if(hosts and (note.host == nil or hosts.index(note.host.address) == nil))
next if(types and types.index(note.ntype) == nil) next if(types and types.index(note.ntype) == nil)
print_status("Time: #{note.created} Note: host=#{note.host.address} type=#{note.ntype} data=#{note.data}") if (note.host and note.service)
print_status("Time: #{note.created} Note: host=#{note.host.address} service=#{note.service.name} type=#{note.ntype} data=#{note.data}")
elsif (note.host)
print_status("Time: #{note.created} Note: host=#{note.host.address} type=#{note.ntype} data=#{note.data}")
elsif (note.service)
print_status("Time: #{note.created} Note: service=#{note.service.name} type=#{note.ntype} data=#{note.data}")
else
print_status("Time: #{note.created} Note: type=#{note.ntype} data=#{note.data}")
end
end end
end end
def cmd_db_add_host(*args) def cmd_db_add_host(*args)
print_status("Adding #{args.length} hosts...") print_status("Adding #{args.length} hosts...")
args.each do |address| args.each do |address|
host = framework.db.get_host(nil, address) host = framework.db.find_or_create_host(address)
print_status("Time: #{host.created} Host: host=#{host.address}") print_status("Time: #{host.created} Host: host=#{host.address}")
end end
end end
@ -339,10 +347,10 @@ class Db
return return
end end
host = framework.db.get_host(nil, args[0]) host = framework.db.find_or_create_host(args[0])
return if not host return if not host
service = framework.db.get_service(nil, host, args[2].downcase, args[1].to_i) service = framework.db.get_service(host, args[2].downcase, args[1].to_i)
return if not service return if not service
print_status("Time: #{service.created} Service: host=#{service.host.address} port=#{service.port} proto=#{service.proto} state=#{service.state}") print_status("Time: #{service.created} Service: host=#{service.host.address} port=#{service.port} proto=#{service.proto} state=#{service.state}")
@ -369,10 +377,10 @@ class Db
ntype = args.shift ntype = args.shift
ndata = args.join(" ") ndata = args.join(" ")
host = framework.db.get_host(nil, naddr) host = framework.db.find_or_create_host(naddr)
return if not host return if not host
note = framework.db.get_note(nil, host, ntype, ndata) note = framework.db.find_or_create_note(host, ntype, ndata)
return if not note return if not note
print_status("Time: #{note.created} Note: host=#{note.host.address} type=#{note.ntype} data=#{note.data}") print_status("Time: #{note.created} Note: host=#{note.host.address} type=#{note.ntype} data=#{note.data}")
@ -819,14 +827,14 @@ class Db
p = port.match(/^([^\(]+)\((\d+)\/([^\)]+)\)/) p = port.match(/^([^\(]+)\((\d+)\/([^\)]+)\)/)
return if not p return if not p
host = framework.db.get_host(nil, addr) host = framework.db.find_or_create_host(addr)
return if not host return if not host
if host.state != Msf::HostState::Alive if host.state != Msf::HostState::Alive
framework.db.report_host_state(self, addr, Msf::HostState::Alive) framework.db.report_host_state(addr, Msf::HostState::Alive)
end end
service = framework.db.get_service(nil, host, p[3].downcase, p[2].to_i) service = framework.db.get_service(host, p[3].downcase, p[2].to_i)
name = p[1].strip name = p[1].strip
if name != "unknown" if name != "unknown"
service.name = name service.name = name
@ -860,11 +868,11 @@ class Db
nss = 'NSS-' + nasl.to_s nss = 'NSS-' + nasl.to_s
vuln = framework.db.get_vuln(nil, host, service, nss, data) vuln = framework.db.get_vuln(host, service, nss, data)
rids = [] rids = []
refs.keys.each do |r| refs.keys.each do |r|
rids << framework.db.get_ref(nil, r) rids << framework.db.get_ref(r)
end end
vuln.refs << (rids - vuln.refs) vuln.refs << (rids - vuln.refs)
@ -1007,26 +1015,32 @@ class Db
# Whenever the parser pulls a host out of the nmap results, store # Whenever the parser pulls a host out of the nmap results, store
# it, along with any associated services, in the database. # it, along with any associated services, in the database.
parser.on_found_host = Proc.new { |h| parser.on_found_host = Proc.new { |h|
data = {}
if (h["addrs"].has_key?("ipv4")) if (h["addrs"].has_key?("ipv4"))
addr = h["addrs"]["ipv4"] data[:host] = h["addrs"]["ipv4"]
elsif (h.has_key?("ipv6")) elsif (h["addrs"].has_key?("ipv6"))
addr = h["addrs"]["ipv6"] data[:host] = h["addrs"]["ipv6"]
else else
# Don't care about addresses other than IP # Can't report it if it doesn't have an IP
return return
end end
host = framework.db.get_host(nil, addr) if (h["addrs"].has_key?("mac"))
status = (h["status"] == "up" ? Msf::HostState::Alive : Msf::HostState::Dead) data[:mac] = h["addrs"]["mac"]
framework.db.report_host_state(self, addr, status) end
data[:state] = (h["status"] == "up" ? Msf::HostState::Alive : Msf::HostState::Dead)
host = framework.db.find_or_create_host(data)
# Put all the ports, regardless of state, into the db. # Put all the ports, regardless of state, into the db.
h["ports"].each { |p| h["ports"].each { |p|
service = framework.db.get_service(nil, host, p["protocol"].downcase, p["portid"].to_i) data = {}
service.state = p["state"] data[:proto] = p["protocol"].downcase
data[:port] = p["portid"].to_i
data[:state] = p["state"]
data[:host] = host
if p["name"] != "unknown" if p["name"] != "unknown"
service.name = p["name"] data[:name] = p["name"]
end end
service.save framework.db.report_service(data)
} }
} }
@ -1063,14 +1077,14 @@ class Db
next if status != "open" next if status != "open"
host = framework.db.get_host(nil, addr) host = framework.db.find_or_create_host(addr)
next if not host next if not host
if host.state != Msf::HostState::Alive if host.state != Msf::HostState::Alive
framework.db.report_host_state(self, addr, Msf::HostState::Alive) framework.db.report_host_state(addr, Msf::HostState::Alive)
end end
service = framework.db.get_service(nil, host, proto, port) service = framework.db.get_service(host, proto, port)
if not service.name and name != "unidentified" if not service.name and name != "unidentified"
service.name = name service.name = name
service.save service.save

View File

@ -10,11 +10,11 @@ module Exploitation
# Provides several javascript functions for determining the OS and browser versions of a client. # Provides several javascript functions for determining the OS and browser versions of a client.
# #
# getVersion(): returns an object with the following properties # getVersion(): returns an object with the following properties
# os_name - OS name, one of the Msf::Auxiliary::Report::OperatingSystems constants # os_name - OS name, one of the Msf::OperatingSystems constants
# os_flavor - OS flavor as a string (e.g.: "XP", "2000") # os_flavor - OS flavor as a string (e.g.: "XP", "2000")
# os_sp - OS service pack (e.g.: "SP2", will be empty on non-Windows) # os_sp - OS service pack (e.g.: "SP2", will be empty on non-Windows)
# os_lang - OS language (e.g.: "en-us") # os_lang - OS language (e.g.: "en-us")
# ua_name - Client name, one of the Msf::Auxiliary::Report::HttpClients constants # ua_name - Client name, one of the Msf::HttpClients constants
# ua_version - Client version as a string (e.g.: "3.5.1", "6.0;SP2") # ua_version - Client version as a string (e.g.: "3.5.1", "6.0;SP2")
# arch - Architecture, one of the ARCH_* constants # arch - Architecture, one of the ARCH_* constants
# #
@ -28,8 +28,8 @@ module Exploitation
class JavascriptOSDetect < ObfuscateJS class JavascriptOSDetect < ObfuscateJS
def initialize(custom_js = '', opts = {}) def initialize(custom_js = '', opts = {})
clients = ::Msf::Auxiliary::Report::HttpClients clients = ::Msf::HttpClients
oses = ::Msf::Auxiliary::Report::OperatingSystems oses = ::Msf::OperatingSystems
@js = custom_js @js = custom_js
@js = <<ENDJS + @js @js = <<ENDJS + @js
/** /**

View File

@ -132,6 +132,7 @@ class Metasploit3 < Msf::Auxiliary
addrs = "Addresses:(" + host[:addrs].map{|n| n[0]}.uniq.join(", ") + ")" addrs = "Addresses:(" + host[:addrs].map{|n| n[0]}.uniq.join(", ") + ")"
end end
report_host(:host => ip, :mac => host[:mac], :os_name => os)
print_status("#{ip} [#{host[:name]}] OS:#{os}#{user}#{names} #{addrs} Mac:#{host[:mac]}") print_status("#{ip} [#{host[:name]}] OS:#{os}#{user}#{names} #{addrs} Mac:#{host[:mac]}")
end end
end end

View File

@ -64,7 +64,13 @@ class Metasploit3 < Msf::Auxiliary
end end
print_status(info) print_status(info)
report_service(:host => ip, :port => info[0], :name => 'smb', :info => "#{res['os']} #{res['sp']} (language: #{res['lang']})") report_service({
:host => ip,
:port => info[0],
:proto => 'tcp',
:name => 'smb',
:info => "#{res['os']} #{res['sp']} (language: #{res['lang']})"
})
case res['os'] case res['os']
when /Windows/ when /Windows/
os = OperatingSystems::WINDOWS os = OperatingSystems::WINDOWS

View File

@ -336,7 +336,7 @@ class Metasploit3 < Msf::Auxiliary
# build the appropriate tests for it. # build the appropriate tests for it.
method = apo[:vuln_test].dup method = apo[:vuln_test].dup
apo[:vuln_test] = "" apo[:vuln_test] = ""
apo[:ua_name] = ::Msf::Auxiliary::Report::HttpClients::IE apo[:ua_name] = HttpClients::IE
if apo[:classid].kind_of?(Array) # then it's many classids if apo[:classid].kind_of?(Array) # then it's many classids
apo[:classid].each { |clsid| apo[:classid].each { |clsid|
apo[:vuln_test] << "if (testAXO('#{clsid}', '#{method}')) {\n" apo[:vuln_test] << "if (testAXO('#{clsid}', '#{method}')) {\n"
@ -477,7 +477,7 @@ class Metasploit3 < Msf::Auxiliary
end end
def build_noscript_response(cli, request) def build_noscript_response(cli, request)
client_info = get_client(cli.peerhost, request['User-Agent']) client_info = get_client(:host => cli.peerhost, :ua_string => request['User-Agent'])
response = create_response() response = create_response()
response['Expires'] = '0' response['Expires'] = '0'
@ -518,9 +518,9 @@ class Metasploit3 < Msf::Auxiliary
response['Expires'] = '0' response['Expires'] = '0'
response['Cache-Control'] = 'must-revalidate' response['Cache-Control'] = 'must-revalidate'
client_info = get_client(cli.peerhost, request['User-Agent'])
#print_status("Client info: #{client_info.inspect}") #print_status("Client info: #{client_info.inspect}")
host_info = get_host(cli.peerhost) host_info = get_host(cli.peerhost)
client_info = get_client(:host => host_info, :ua_string => request['User-Agent'])
js = ::Rex::Exploitation::ObfuscateJS.new js = ::Rex::Exploitation::ObfuscateJS.new
# If we didn't get a client from the database, then the detection # If we didn't get a client from the database, then the detection
@ -710,25 +710,25 @@ class Metasploit3 < Msf::Auxiliary
detected_version = Rex::Text.decode_base64(Rex::Text.uri_decode(detected_version)) detected_version = Rex::Text.decode_base64(Rex::Text.uri_decode(detected_version))
print_status("JavaScript Report: #{detected_version}") print_status("JavaScript Report: #{detected_version}")
(os_name, os_flavor, os_sp, os_lang, arch, ua_name, ua_ver) = detected_version.split(':') (os_name, os_flavor, os_sp, os_lang, arch, ua_name, ua_ver) = detected_version.split(':')
report_host( host = framework.db.find_or_create_host({
:host => cli.peerhost, :host => cli.peerhost,
:os_name => os_name, :os_name => os_name,
:os_flavor => os_flavor, :os_flavor => os_flavor,
:os_sp => os_sp, :os_sp => os_sp,
:os_lang => os_lang, :os_lang => os_lang,
:arch => arch :arch => arch
) })
report_client( report_client({
:host => cli.peerhost, :host => host,
:ua_string => request['User-Agent'], :ua_string => request['User-Agent'],
:ua_name => ua_name, :ua_name => ua_name,
:ua_ver => ua_ver :ua_ver => ua_ver
) })
report_note( report_note({
:host => cli.peerhost, :host => host,
:type => 'http_request', :type => 'http_request',
:data => "#{@myhost}:#{@myport} #{request.method} #{request.resource} #{os_name} #{ua_name} #{ua_ver}" :data => "#{@myhost}:#{@myport} #{request.method} #{request.resource} #{os_name} #{ua_name} #{ua_ver}"
) })
end end
end end
@ -736,9 +736,7 @@ class Metasploit3 < Msf::Auxiliary
# This is less reliable because we're not treating different user # This is less reliable because we're not treating different user
# agents from the same IP as different hosts. # agents from the same IP as different hosts.
if (framework.db.active) if (framework.db.active)
# There really ought to be a report_client, instead of having report_client(:host => cli.peerhost, :ua_string => request['User-Agent'])
# get_client create a new one if it can't find one.
get_client(cli.peerhost, request['User-Agent'])
else else
warn_no_database warn_no_database
@targetcache ||= {} @targetcache ||= {}
@ -768,8 +766,9 @@ class Metasploit3 < Msf::Auxiliary
# essentially creating an in-memory database. The upside is that it works # essentially creating an in-memory database. The upside is that it works
# if the database is broken. The downside of course is that querying from # if the database is broken. The downside of course is that querying from
# a hash is not as simple or efficient as a database. # a hash is not as simple or efficient as a database.
def get_client(host, ua) def get_client(opts)
return super(host, ua) || @targetcache[host] host = opts[:host]
return super || @targetcache[host]
end end
def build_iframe(resource) def build_iframe(resource)

View File

@ -23,9 +23,9 @@ class Plugin::CredCollect < Msf::Plugin
print_error("Database not connected") print_error("Database not connected")
return return
end end
framework.db.each_note do |note| framework.db.get_auth_info(:proto=>"smb").each do |info|
if note.ntype == "auth_HASH" if info.kind_of? Hash and info.has_key? :hash_string
print_line(note.data) print_line(info[:hash_string])
end end
end end
end end
@ -35,9 +35,9 @@ class Plugin::CredCollect < Msf::Plugin
print_error("Database not connected") print_error("Database not connected")
return return
end end
framework.db.each_note do |note| framework.db.get_auth_info(:proto=>"smb").each do |info|
if note.ntype == "auth_TOKEN" if info.kind_of? Hash and info.has_key? :token
print_line("#{note.host.address} - #{note.data}") print_line(info[:host] + " - " + info[:token])
end end
end end
end end
@ -60,28 +60,37 @@ class Plugin::CredCollect < Msf::Plugin
# Target infos for the db record # Target infos for the db record
addr = session.sock.peerhost addr = session.sock.peerhost
host = self.framework.db.report_host_state(self, addr, Msf::HostState::Alive) host = self.framework.db.find_or_create_host(
:host => addr,
:state => Msf::HostState::Alive
)
# Record hashes to the running db instance as auth_HASH type # Record hashes to the running db instance as auth_HASH type
hashes.each do |user| hashes.each do |hash|
data = {}
data[:host] = host
data[:targ_host] = host.address
data[:proto] = 'smb'
data[:user] = hash.user_name
data[:hash] = hash.lanman + ":" + hash.ntlm
data[:hash_string] = hash.hash_string
type = "auth_HASH" self.framework.db.report_auth_info(data)
data = user.to_s
# We'll make this look like an auth note anyway
self.framework.db.get_note(self, host, type, data)
end end
# Record user tokens # Record user tokens
tokens = session.incognito.incognito_list_tokens(0).values tokens = session.incognito.incognito_list_tokens(0).values
# Meh, tokens come to us as a formatted string # Meh, tokens come to us as a formatted string
tokens = tokens.to_s.strip!.split("\n") tokens = tokens.join.strip!.split("\n")
tokens.each do |token| tokens.each do |token|
type = "auth_TOKEN" data = {}
data = token data[:host] = host
data[:targ_host] = host.address
data[:proto] = 'smb'
data[:token] = token
self.framework.db.get_note(self, host, type, data) self.framework.db.report_auth_info(data)
end end
end end
end end

View File

@ -398,66 +398,62 @@ class Plugin::Nexpose < Msf::Plugin
end end
def process_nexpose_data_rxml(data) def process_nexpose_data_rxml(data)
doc = REXML::Document.new(data) doc = REXML::Document.new(data)
doc.elements.each('/NexposeReport/nodes/node') do |host| doc.elements.each('/NexposeReport/nodes/node') do |host|
addr = host.attributes['address'] addr = host.attributes['address']
xhost = addr xhost = addr
refs = {} refs = {}
# os based vuln # os based vuln
host.elements['tests'].elements.each('test') do |vuln| host.elements['tests'].elements.each('test') do |vuln|
if vuln.attributes['status'] == 'vulnerable-exploited' or vuln.attributes['status'] == 'vulnerable-version' if vuln.attributes['status'] == 'vulnerable-exploited' or vuln.attributes['status'] == 'vulnerable-version'
dhost = framework.db.get_host(nil, addr) dhost = framework.db.find_or_create_host(:host => addr)
next if not dhost next if not dhost
vid = vuln.attributes['id'].to_s vid = vuln.attributes['id'].to_s
nexpose_vuln_lookup(doc,vid,refs,dhost) nexpose_vuln_lookup(doc,vid,refs,dhost)
nexpose_vuln_lookup(doc,vid.upcase,refs,dhost) nexpose_vuln_lookup(doc,vid.upcase,refs,dhost)
end end
end end
# skip if no endpoints # skip if no endpoints
next unless host.elements['endpoints'] next unless host.elements['endpoints']
# parse the ports and add the vulns # parse the ports and add the vulns
host.elements['endpoints'].elements.each('endpoint') do |port| host.elements['endpoints'].elements.each('endpoint') do |port|
prot = port.attributes['protocol'] prot = port.attributes['protocol']
pnum = port.attributes['port'] pnum = port.attributes['port']
stat = port.attributes['status'] stat = port.attributes['status']
next if not port.elements['services'] next if not port.elements['services']
name = port.elements['services'].elements['service'].attributes['name'].downcase name = port.elements['services'].elements['service'].attributes['name'].downcase
next if not port.elements['services'].elements['service'].elements['fingerprints'] next if not port.elements['services'].elements['service'].elements['fingerprints']
prod = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['product'] prod = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['product']
vers = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['version'] vers = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['version']
vndr = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['vendor'] vndr = port.elements['services'].elements['service'].elements['fingerprints'].elements['fingerprint'].attributes['vendor']
next if stat != 'open' next if stat != 'open'
dhost = framework.db.get_host(nil, addr) dhost = framework.db.find_or_create_host(:host => addr, :state => Msf::HostState::Alive)
next if not dhost next if not dhost
if dhost.state != Msf::HostState::Alive if name != "unknown"
framework.db.report_host_state(self, addr, Msf::HostState::Alive) service = framework.db.find_or_create_service(:host => dhost, :proto => prot.downcase, :port => pnum.to_i, :name => name)
end else
service = framework.db.find_or_create_service(:host => dhost, :proto => prot.downcase, :port => pnum.to_i)
end
service = framework.db.get_service(nil, dhost, prot.downcase, pnum.to_i) port.elements['services'].elements['service'].elements['tests'].elements.each('test') do |vuln|
if name != "unknown" if vuln.attributes['status'] == 'vulnerable-exploited' or vuln.attributes['status'] == 'vulnerable-version'
service.name = name vid = vuln.attributes['id'].to_s
service.save # TODO, improve the vuln_lookup check so case of the vuln_id doesnt matter
end nexpose_vuln_lookup(doc,vid,refs,dhost,service)
nexpose_vuln_lookup(doc,vid.upcase,refs,dhost,service)
port.elements['services'].elements['service'].elements['tests'].elements.each('test') do |vuln| end
if vuln.attributes['status'] == 'vulnerable-exploited' or vuln.attributes['status'] == 'vulnerable-version' end
vid = vuln.attributes['id'].to_s end
# TODO, improve the vuln_lookup check so case of the vuln_id doesnt matter end
nexpose_vuln_lookup(doc,vid,refs,dhost,service) end
nexpose_vuln_lookup(doc,vid.upcase,refs,dhost,service)
end
end
end
end
end
# #
# NeXpose vuln lookup # NeXpose vuln lookup
@ -483,11 +479,15 @@ class Plugin::Nexpose < Msf::Plugin
refs[ 'NEXPOSE-' + vid.downcase ] = true refs[ 'NEXPOSE-' + vid.downcase ] = true
vuln = framework.db.get_vuln(nil, host, serv, 'NEXPOSE-' + vid.downcase, title) vuln = framework.db.find_or_create_vuln(
:host => host,
:service => serv,
:name => 'NEXPOSE-' + vid.downcase,
:data => title)
rids = [] rids = []
refs.keys.each do |r| refs.keys.each do |r|
rids << framework.db.get_ref(nil, r) rids << framework.db.find_or_create_ref(:name => r)
end end
vuln.refs << (rids - vuln.refs) vuln.refs << (rids - vuln.refs)
@ -503,21 +503,20 @@ class Plugin::Nexpose < Msf::Plugin
desc = fdesc.text.to_s.strip desc = fdesc.text.to_s.strip
end end
host = framework.db.get_host(nil, addr) host = framework.db.find_or_create_host(:host => addr, :state => Msf::HostState::Alive)
next if not host next if not host
if host.state != Msf::HostState::Alive
framework.db.report_host_state(self, addr, Msf::HostState::Alive)
end
# Load vulnerabilities not associated with a service # Load vulnerabilities not associated with a service
dev.elements.each('vulnerabilities/vulnerability') do |vuln| dev.elements.each('vulnerabilities/vulnerability') do |vuln|
vid = vuln.attributes['id'].to_s.downcase vid = vuln.attributes['id'].to_s.downcase
rids = [] rids = []
refs = process_nexpose_data_sxml_refs(vuln) refs = process_nexpose_data_sxml_refs(vuln)
next if not refs next if not refs
vuln = framework.db.get_vuln(nil, host, nil, 'NEXPOSE-' + vid, vid) vuln = framework.db.find_or_create_vuln(
refs.each { |r| rids << framework.db.get_ref(nil, r) } :host => host,
:name => 'NEXPOSE-' + vid
:data => vid)
refs.each { |r| rids << framework.db.find_or_create_ref(:name => r) }
vuln.refs << (rids - vuln.refs) vuln.refs << (rids - vuln.refs)
end end
@ -527,10 +526,11 @@ class Plugin::Nexpose < Msf::Plugin
sprot = svc.attributes['protocol'].to_s.downcase sprot = svc.attributes['protocol'].to_s.downcase
sport = svc.attributes['port'].to_s.to_i sport = svc.attributes['port'].to_s.to_i
serv = framework.db.get_service(nil, host, sprot, sport) name = sname.split('(')[0].strip
if(sname.downcase != '<unknown>') if(sname.downcase != '<unknown>')
serv.name = sname.split('(')[0].strip serv = framework.db.find_or_create_service(:host => host, :proto => sprot, :port => sport, :name => name)
serv.save else
serv = framework.db.find_or_create_service(:host => host, :proto => sprot, :port => sport)
end end
# Load vulnerabilities associated with this service # Load vulnerabilities associated with this service
@ -539,11 +539,11 @@ class Plugin::Nexpose < Msf::Plugin
rids = [] rids = []
refs = process_nexpose_data_sxml_refs(vuln) refs = process_nexpose_data_sxml_refs(vuln)
next if not refs next if not refs
vuln = framework.db.get_vuln(nil, host, serv, 'NEXPOSE-' + vid, vid) vuln = framework.db.find_or_create_vuln(:host => host, :service => serv, :name => 'NEXPOSE-' + vid, :data => vid)
refs.each { |r| rids << framework.db.get_ref(nil, r) } refs.each { |r| rids << framework.db.find_or_create_ref(:name => r) }
vuln.refs << (rids - vuln.refs) vuln.refs << (rids - vuln.refs)
end end
end end
end end
end end