2006-03-21 04:37:48 +00:00
|
|
|
module Msf
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# The states that a host can be in.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module HostState
|
|
|
|
#
|
|
|
|
# The host is alive.
|
|
|
|
#
|
|
|
|
Alive = "alive"
|
|
|
|
#
|
|
|
|
# The host is dead.
|
|
|
|
#
|
|
|
|
Dead = "down"
|
|
|
|
#
|
|
|
|
# The host state is unknown.
|
|
|
|
#
|
|
|
|
Unknown = "unknown"
|
|
|
|
end
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# The states that a service can be in.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module ServiceState
|
|
|
|
#
|
|
|
|
# The service is alive.
|
|
|
|
#
|
|
|
|
Up = "up"
|
|
|
|
#
|
|
|
|
# The service is dead.
|
|
|
|
#
|
|
|
|
Dead = "down"
|
|
|
|
#
|
|
|
|
# The service state is unknown.
|
|
|
|
#
|
|
|
|
Unknown = "unknown"
|
|
|
|
end
|
|
|
|
|
2007-02-25 21:25:41 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# Events that can occur in the host/service database.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
module DatabaseEvent
|
|
|
|
|
|
|
|
#
|
|
|
|
# Called when an existing host's state changes
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_host_state(host, ostate)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Called when an existing service's state changes
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_service_state(host, port, ostate)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Called when a new host is added to the database. The host parameter is
|
|
|
|
# of type Host.
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_host(host)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
2009-07-22 20:14:35 +00:00
|
|
|
#
|
|
|
|
# Called when a new client is added to the database. The client
|
|
|
|
# parameter is of type Client.
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_client(client)
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
|
|
|
|
2007-02-25 21:25:41 +00:00
|
|
|
#
|
|
|
|
# Called when a new service is added to the database. The service
|
|
|
|
# parameter is of type Service.
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_service(service)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Called when an applicable vulnerability is found for a service. The vuln
|
|
|
|
# parameter is of type Vuln.
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_vuln(vuln)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Called when a new reference is created.
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def on_db_ref(ref)
|
2007-02-25 21:25:41 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2006-03-21 04:37:48 +00:00
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# The DB module ActiveRecord definitions for the DBManager
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class DBManager
|
|
|
|
|
2006-09-16 06:45:06 +00:00
|
|
|
#
|
|
|
|
# Determines if the database is functional
|
|
|
|
#
|
|
|
|
def check
|
|
|
|
res = Host.find(:all)
|
|
|
|
end
|
|
|
|
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def default_workspace
|
|
|
|
Workspace.default
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_workspace(name)
|
|
|
|
Workspace.find_by_name(name)
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Creates a new workspace in the database
|
2008-07-22 07:28:05 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def add_workspace(name)
|
|
|
|
Workspace.find_or_create_by_name(name)
|
|
|
|
end
|
|
|
|
|
|
|
|
def workspaces
|
|
|
|
Workspace.find(:all)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2010-01-02 23:14:37 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Find a host. Performs no database writes.
|
2008-07-22 07:28:05 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
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
|
2008-07-22 07:28:05 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_initialize_host(opts)
|
|
|
|
addr = opts.delete(:host) || return
|
|
|
|
return addr if addr.kind_of? Host
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
#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
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
opts.each { |k,v|
|
|
|
|
if (host.attribute_names.include?(k.to_s))
|
|
|
|
host[k] = v
|
2009-07-22 20:14:35 +00:00
|
|
|
else
|
|
|
|
dlog("Unknown attribute for Host: #{k}")
|
2008-07-22 07:28:05 +00:00
|
|
|
end
|
|
|
|
}
|
2009-12-29 23:48:45 +00:00
|
|
|
host.state = HostState::Unknown if not host.state
|
|
|
|
host.comm = '' if not host.comm
|
|
|
|
host.workspace = workspace if not host.workspace
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-07-22 07:28:05 +00:00
|
|
|
return host
|
|
|
|
end
|
|
|
|
|
2010-01-02 23:14:37 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Exactly like report_host but ensures that the returned Host has been
|
|
|
|
# written to the database. Returns nil on error.
|
2009-07-22 20:14:35 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_create_host(opts)
|
|
|
|
host = find_or_initialize_host(opts)
|
2010-01-02 23:14:37 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
if (host and host.changed?)
|
|
|
|
host.created = Time.now
|
|
|
|
task = framework.db.queue( Proc.new { host.save! } )
|
|
|
|
task.wait
|
|
|
|
if task.status != :done
|
|
|
|
return nil
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
end
|
|
|
|
return host
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
|
|
|
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Report a host's attributes such as operating system and service pack
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# 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! } )
|
2006-04-03 04:33:30 +00:00
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
return host
|
2009-12-14 22:52:34 +00:00
|
|
|
end
|
2006-03-21 04:37:48 +00:00
|
|
|
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Iterates over the hosts table calling the supplied block with the host
|
|
|
|
# instance of each entry.
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
|
|
|
def each_host(&block)
|
2009-12-14 22:52:34 +00:00
|
|
|
workspace.hosts.each do |host|
|
2006-03-21 04:37:48 +00:00
|
|
|
block.call(host)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Returns a list of all hosts in the database
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-21 16:46:11 +00:00
|
|
|
def hosts(only_up = false, addresses = nil)
|
|
|
|
conditions = {}
|
|
|
|
conditions[:state] = [Msf::HostState::Alive, Msf::HostState::Unknown] if only_up
|
|
|
|
conditions[:address] = addresses if addresses
|
|
|
|
workspace.hosts.all(:conditions => conditions, :order => :address)
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
def find_or_initialize_service(opts)
|
|
|
|
addr = opts.delete(:host) || return
|
|
|
|
host = find_or_create_host({:host => addr})
|
2009-12-30 17:43:47 +00:00
|
|
|
proto = opts[:proto] || 'tcp'
|
|
|
|
service = host.services.find_or_initialize_by_port_and_proto(opts[:port], proto)
|
2009-12-29 23:48:45 +00:00
|
|
|
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
|
|
|
|
|
2010-01-02 23:14:37 +00:00
|
|
|
#
|
|
|
|
# Record a service in the database.
|
2009-12-29 23:48:45 +00:00
|
|
|
#
|
|
|
|
# opts must contain
|
2009-12-31 01:27:04 +00:00
|
|
|
# :host -- the host where this service is running
|
2009-12-29 23:48:45 +00:00
|
|
|
# :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
|
|
|
|
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Iterates over the services table calling the supplied block with the
|
2006-04-02 22:33:34 +00:00
|
|
|
# service instance of each entry.
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
|
|
|
def each_service(&block)
|
2009-12-21 16:46:11 +00:00
|
|
|
services.each do |service|
|
2006-03-21 04:37:48 +00:00
|
|
|
block.call(service)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Returns a list of all services in the database
|
2006-03-21 04:37:48 +00:00
|
|
|
#
|
2009-12-21 16:46:11 +00:00
|
|
|
def services(only_up = false, proto = nil, addresses = nil, ports = nil, names = nil)
|
|
|
|
conditions = {}
|
2009-12-26 22:08:49 +00:00
|
|
|
conditions[:state] = ['open'] if only_up
|
2009-12-21 16:46:11 +00:00
|
|
|
conditions[:proto] = proto if proto
|
|
|
|
conditions["hosts.address"] = addresses if addresses
|
|
|
|
conditions[:port] = ports if ports
|
|
|
|
conditions[:name] = names if names
|
|
|
|
workspace.services.all(:include => :host, :conditions => conditions, :order => "hosts.address, port")
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
2006-04-02 22:33:34 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
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)
|
2010-01-02 23:14:37 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
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.
|
|
|
|
#
|
2010-01-02 23:14:37 +00:00
|
|
|
# opts must contain
|
2009-12-29 23:48:45 +00:00
|
|
|
# :ua_string -- the value of the User-Agent header
|
|
|
|
#
|
2010-01-02 23:14:37 +00:00
|
|
|
# opts can contain
|
2009-12-29 23:48:45 +00:00
|
|
|
# :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
|
|
|
|
|
2006-04-02 22:33:34 +00:00
|
|
|
#
|
|
|
|
# This method iterates the vulns table calling the supplied block with the
|
|
|
|
# vuln instance of each entry.
|
|
|
|
#
|
|
|
|
def each_vuln(&block)
|
2009-12-21 16:46:11 +00:00
|
|
|
workspace.vulns.each do |vulns|
|
2006-04-02 22:33:34 +00:00
|
|
|
block.call(vulns)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2006-04-02 22:33:34 +00:00
|
|
|
#
|
|
|
|
# This methods returns a list of all vulnerabilities in the database
|
|
|
|
#
|
|
|
|
def vulns
|
2009-12-21 16:46:11 +00:00
|
|
|
workspace.vulns
|
2006-04-02 22:33:34 +00:00
|
|
|
end
|
2008-03-02 04:46:13 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# This method iterates the notes table calling the supplied block with the
|
|
|
|
# note instance of each entry.
|
|
|
|
#
|
|
|
|
def each_note(&block)
|
2009-12-21 16:46:11 +00:00
|
|
|
workspace.notes.each do |note|
|
2008-03-02 04:46:13 +00:00
|
|
|
block.call(note)
|
|
|
|
end
|
|
|
|
end
|
2009-06-23 03:49:25 +00:00
|
|
|
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Find or create a note matching this type/data
|
2009-06-23 03:49:25 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_create_note(opts)
|
|
|
|
note = find_or_initialize_note(opts)
|
|
|
|
if (note.changed?)
|
|
|
|
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
|
|
|
|
|
2010-01-01 00:19:15 +00:00
|
|
|
method = "find_or_initialize_by_ntype_and_data"
|
|
|
|
args = [ ntype, data.to_yaml ]
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
if opts[:host]
|
|
|
|
if opts[:host].kind_of? Host
|
|
|
|
host = opts[:host].dup
|
|
|
|
else
|
|
|
|
host = find_or_create_host({:host => opts[:host]})
|
|
|
|
end
|
2010-01-01 00:19:15 +00:00
|
|
|
method << "_and_host_id"
|
|
|
|
args.push(host.id)
|
2009-12-29 23:48:45 +00:00
|
|
|
end
|
|
|
|
if opts[:service] and opts[:service].kind_of? Service
|
2010-01-01 00:19:15 +00:00
|
|
|
method << "_and_service_id"
|
|
|
|
args.push(opts[:service].id)
|
2009-12-29 23:48:45 +00:00
|
|
|
end
|
2010-01-01 00:19:15 +00:00
|
|
|
note = workspace.notes.send(method, *args)
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
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
|
2009-06-23 03:49:25 +00:00
|
|
|
end
|
|
|
|
|
2008-03-02 04:46:13 +00:00
|
|
|
#
|
|
|
|
# This methods returns a list of all notes in the database
|
|
|
|
#
|
|
|
|
def notes
|
2009-12-21 16:46:11 +00:00
|
|
|
workspace.notes
|
2008-03-02 04:46:13 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
###
|
|
|
|
# Specific notes
|
|
|
|
###
|
|
|
|
|
|
|
|
#
|
|
|
|
# opts must contain
|
|
|
|
# :data -- a hash containing the authentication info
|
2010-01-02 23:14:37 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# opts can contain
|
|
|
|
# :host -- an ip address or Host
|
|
|
|
# :service -- a Service
|
|
|
|
# :proto -- the protocol
|
|
|
|
# :port -- the port
|
|
|
|
#
|
|
|
|
def report_auth_info(opts={})
|
|
|
|
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
|
|
|
|
}
|
2009-12-14 22:52:34 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
report_note(note)
|
2009-12-14 22:52:34 +00:00
|
|
|
end
|
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def get_auth_info(opts={})
|
|
|
|
return if not framework.db.active
|
|
|
|
condition = ""
|
|
|
|
condition_values = []
|
|
|
|
if opts[:host]
|
|
|
|
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
|
|
|
|
if condition.length > 0
|
|
|
|
condition << " and "
|
|
|
|
end
|
|
|
|
condition << "ntype LIKE ?"
|
|
|
|
condition_values << "auth:%"
|
|
|
|
end
|
|
|
|
conditions = [ condition ] + condition_values
|
|
|
|
info = framework.db.notes.find(:all, :conditions => conditions )
|
|
|
|
return info.map{|i| i.data} if info
|
2009-12-14 22:52:34 +00:00
|
|
|
end
|
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
#
|
2006-09-16 20:08:13 +00:00
|
|
|
#
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_initialize_vuln(opts)
|
|
|
|
host = find_or_create_host({:host => opts[:host]}) || return
|
|
|
|
name = opts[:name] || return
|
|
|
|
data = opts[:data]
|
|
|
|
|
|
|
|
if data
|
|
|
|
vuln = host.vulns.find_or_initialize_by_name_and_data(name, data)
|
2009-07-22 20:14:35 +00:00
|
|
|
else
|
2009-12-29 23:48:45 +00:00
|
|
|
vuln = host.vulns.find_or_initialize_by_name(name)
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
|
|
|
|
if opts[:service] and opts[:service].kind_of? Service
|
|
|
|
vuln.service = opts[:service]
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
return vuln
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
2006-09-16 20:08:13 +00:00
|
|
|
|
2009-07-22 20:14:35 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
# Find or create a vuln matching this service/name
|
2009-12-13 05:24:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_create_vuln(opts)
|
|
|
|
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
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
return vuln
|
2009-07-22 20:14:35 +00:00
|
|
|
end
|
|
|
|
|
2006-09-16 20:08:13 +00:00
|
|
|
#
|
2009-12-13 05:24:48 +00:00
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
#
|
|
|
|
def report_vuln(opts)
|
2010-01-01 00:19:15 +00:00
|
|
|
vuln = find_or_initialize_vuln(opts)
|
2009-12-29 23:48:45 +00:00
|
|
|
if vuln.changed?
|
|
|
|
vuln.created = Time.now
|
|
|
|
framework.db.queue(Proc.new { vuln.save! })
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
return vuln
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def get_vuln(host, service, name, data='')
|
2009-07-22 13:37:14 +00:00
|
|
|
vuln = nil
|
2009-12-21 16:46:11 +00:00
|
|
|
if (service)
|
2009-07-22 13:37:14 +00:00
|
|
|
vuln = Vuln.find(:first, :conditions => [ "name = ? and service_id = ? and host_id = ?", name, service.id, host.id])
|
|
|
|
else
|
|
|
|
vuln = Vuln.find(:first, :conditions => [ "name = ? and host_id = ?", name, host.id])
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2006-04-02 22:33:34 +00:00
|
|
|
return vuln
|
|
|
|
end
|
2006-09-16 20:08:13 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Find or create a reference matching this name
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def find_or_create_ref(opts)
|
|
|
|
ref = Ref.find_or_initialize_by_name(opts[:name])
|
|
|
|
if ref and ref.changed?
|
|
|
|
ref.created = Time.now
|
|
|
|
task = framework.db.queue(Proc.new { ref.save! })
|
|
|
|
task.wait
|
|
|
|
if task.status != :done
|
|
|
|
return nil
|
|
|
|
end
|
2006-09-16 20:08:13 +00:00
|
|
|
end
|
|
|
|
return ref
|
|
|
|
end
|
2009-12-29 23:48:45 +00:00
|
|
|
def get_ref(name)
|
|
|
|
Ref.find_by_name(name)
|
2008-03-02 04:46:13 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
|
2008-12-22 03:19:39 +00:00
|
|
|
#
|
|
|
|
# Deletes a host and associated data matching this address/comm
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def del_host(address, comm='')
|
2009-12-21 16:46:11 +00:00
|
|
|
host = workspace.hosts.find_by_address_and_comm(address, comm)
|
2009-12-14 22:52:34 +00:00
|
|
|
host.destroy if host
|
2008-12-22 03:19:39 +00:00
|
|
|
end
|
2009-10-16 18:27:18 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Deletes a port and associated vulns matching this port
|
|
|
|
#
|
2009-12-29 23:48:45 +00:00
|
|
|
def del_service(address, proto, port, comm='')
|
2010-01-02 23:14:37 +00:00
|
|
|
host = get_host(address)
|
2009-10-16 18:27:18 +00:00
|
|
|
return unless host
|
|
|
|
|
2009-12-14 22:52:34 +00:00
|
|
|
host.services.find(:all, :conditions => { :proto => proto, :port => port}).destroy_all
|
2009-10-16 18:27:18 +00:00
|
|
|
end
|
2008-12-22 03:19:39 +00:00
|
|
|
|
2006-09-16 20:08:13 +00:00
|
|
|
#
|
|
|
|
# Find a reference matching this name
|
|
|
|
#
|
|
|
|
def has_ref?(name)
|
2009-12-07 17:03:21 +00:00
|
|
|
Ref.find_by_name(name)
|
2006-09-16 20:08:13 +00:00
|
|
|
end
|
2006-09-17 00:39:23 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Find a vulnerability matching this name
|
|
|
|
#
|
|
|
|
def has_vuln?(name)
|
2009-12-07 17:03:21 +00:00
|
|
|
Vuln.find_by_name(name)
|
2006-09-17 00:39:23 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2006-09-16 20:08:13 +00:00
|
|
|
#
|
|
|
|
# Look for an address across all comms
|
2009-12-13 05:24:48 +00:00
|
|
|
#
|
2006-04-02 22:33:34 +00:00
|
|
|
def has_host?(addr)
|
2009-12-14 22:52:34 +00:00
|
|
|
workspace.hosts.find_by_address(addr)
|
2006-04-02 22:33:34 +00:00
|
|
|
end
|
2006-09-17 00:39:23 +00:00
|
|
|
|
2009-12-29 23:48:45 +00:00
|
|
|
def vuln_add_refs(vuln, refs)
|
2009-12-13 06:56:01 +00:00
|
|
|
return vuln if not refs
|
2009-12-29 23:48:45 +00:00
|
|
|
rids = refs.map{|r| get_ref("#{r[0]}-#{r[1]}") }
|
2009-12-13 06:56:01 +00:00
|
|
|
vuln.refs << rids
|
|
|
|
vuln
|
|
|
|
end
|
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Support methods
|
|
|
|
#
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Selected host
|
|
|
|
#
|
|
|
|
def selected_host
|
2009-12-13 05:24:48 +00:00
|
|
|
selhost = WmapTarget.find(:first, :conditions => ["selected != 0"] )
|
2008-10-12 03:46:49 +00:00
|
|
|
if selhost
|
|
|
|
return selhost.host
|
|
|
|
else
|
|
|
|
return
|
2009-12-13 05:24:48 +00:00
|
|
|
end
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Selected port
|
|
|
|
#
|
|
|
|
def selected_port
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapTarget.find(:first, :conditions => ["selected != 0"] ).port
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Selected ssl
|
|
|
|
#
|
|
|
|
def selected_ssl
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapTarget.find(:first, :conditions => ["selected != 0"] ).ssl
|
|
|
|
end
|
|
|
|
|
2008-10-19 20:32:14 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Selected id
|
|
|
|
#
|
|
|
|
def selected_id
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapTarget.find(:first, :conditions => ["selected != 0"] ).object_id
|
2008-10-19 20:32:14 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table identifiying possible targets
|
|
|
|
# This method wiil be remove on second phase of db merging.
|
|
|
|
#
|
|
|
|
def each_distinct_target(&block)
|
|
|
|
request_distinct_targets.each do |target|
|
|
|
|
block.call(target)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method returns a list of all possible targets available in requests
|
|
|
|
# This method wiil be remove on second phase of db merging.
|
|
|
|
#
|
|
|
|
def request_distinct_targets
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapRequest.find(:all, :select => 'DISTINCT host,address,port,ssl')
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table returning a list of all requests of a specific target
|
|
|
|
#
|
|
|
|
def each_request_target_with_path(&block)
|
2009-12-13 05:24:48 +00:00
|
|
|
target_requests('AND wmap_requests.path IS NOT NULL').each do |req|
|
2008-10-12 03:46:49 +00:00
|
|
|
block.call(req)
|
|
|
|
end
|
|
|
|
end
|
2008-11-10 04:38:05 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table returning a list of all requests of a specific target
|
|
|
|
#
|
|
|
|
def each_request_target_with_query(&block)
|
2009-12-13 05:24:48 +00:00
|
|
|
target_requests('AND wmap_requests.query IS NOT NULL').each do |req|
|
2008-11-10 04:38:05 +00:00
|
|
|
block.call(req)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table returning a list of all requests of a specific target
|
|
|
|
#
|
|
|
|
def each_request_target_with_body(&block)
|
2009-12-13 05:24:48 +00:00
|
|
|
target_requests('AND wmap_requests.body IS NOT NULL').each do |req|
|
2008-10-12 03:46:49 +00:00
|
|
|
block.call(req)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table returning a list of all requests of a specific target
|
|
|
|
#
|
|
|
|
def each_request_target_with_headers(&block)
|
2009-12-13 05:24:48 +00:00
|
|
|
target_requests('AND wmap_requests.headers IS NOT NULL').each do |req|
|
2008-10-12 03:46:49 +00:00
|
|
|
block.call(req)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table returning a list of all requests of a specific target
|
|
|
|
#
|
|
|
|
def each_request_target(&block)
|
|
|
|
target_requests('').each do |req|
|
|
|
|
block.call(req)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method returns a list of all requests from target
|
|
|
|
#
|
|
|
|
def target_requests(extra_condition)
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapRequest.find(:all, :conditions => ["wmap_requests.host = ? AND wmap_requests.port = ? #{extra_condition}",selected_host,selected_port])
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the requests table calling the supplied block with the
|
|
|
|
# request instance of each entry.
|
|
|
|
#
|
|
|
|
def each_request(&block)
|
|
|
|
requests.each do |request|
|
|
|
|
block.call(request)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-12-04 03:42:43 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method allows to query directly the requests table. To be used mainly by modules
|
|
|
|
#
|
|
|
|
def request_sql(host,port,extra_condition)
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapRequest.find(:all, :conditions => ["wmap_requests.host = ? AND wmap_requests.port = ? #{extra_condition}",host,port])
|
2008-12-04 03:42:43 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This methods returns a list of all targets in the database
|
|
|
|
#
|
|
|
|
def requests
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapRequest.find(:all)
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This method iterates the targets table calling the supplied block with the
|
|
|
|
# target instance of each entry.
|
|
|
|
#
|
|
|
|
def each_target(&block)
|
|
|
|
targets.each do |target|
|
|
|
|
block.call(target)
|
|
|
|
end
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This methods returns a list of all targets in the database
|
|
|
|
#
|
|
|
|
def targets
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapTarget.find(:all)
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2006-09-17 00:39:23 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# This methods deletes all targets from targets table in the database
|
|
|
|
#
|
|
|
|
def delete_all_targets
|
2009-12-13 05:24:48 +00:00
|
|
|
WmapTarget.delete_all
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
|
|
|
# Find a target matching this id
|
|
|
|
#
|
|
|
|
def get_target(id)
|
2009-12-13 05:24:48 +00:00
|
|
|
target = WmapTarget.find(:first, :conditions => [ "id = ?", id])
|
2008-10-12 03:46:49 +00:00
|
|
|
return target
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
2009-12-13 05:24:48 +00:00
|
|
|
# Create a target
|
2008-10-12 03:46:49 +00:00
|
|
|
#
|
|
|
|
def create_target(host,port,ssl,sel)
|
2009-12-13 05:24:48 +00:00
|
|
|
tar = WmapTarget.create(
|
|
|
|
:host => host,
|
|
|
|
:address => host,
|
|
|
|
:port => port,
|
|
|
|
:ssl => ssl,
|
2008-10-12 03:46:49 +00:00
|
|
|
:selected => sel
|
|
|
|
)
|
2009-12-29 23:48:45 +00:00
|
|
|
#framework.events.on_db_target(rec)
|
2008-10-12 03:46:49 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
|
|
|
|
2008-11-30 22:41:09 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
2009-12-13 05:24:48 +00:00
|
|
|
# Create a request (by hand)
|
2008-11-30 22:41:09 +00:00
|
|
|
#
|
|
|
|
def create_request(host,port,ssl,meth,path,headers,query,body,respcode,resphead,response)
|
2009-12-13 05:24:48 +00:00
|
|
|
req = WmapRequest.create(
|
|
|
|
:host => host,
|
|
|
|
:address => host,
|
|
|
|
:port => port,
|
|
|
|
:ssl => ssl,
|
2008-11-30 22:41:09 +00:00
|
|
|
:meth => meth,
|
|
|
|
:path => path,
|
|
|
|
:headers => headers,
|
|
|
|
:query => query,
|
|
|
|
:body => body,
|
|
|
|
:respcode => respcode,
|
|
|
|
:resphead => resphead,
|
2009-12-29 23:48:45 +00:00
|
|
|
:response => response
|
2008-11-30 22:41:09 +00:00
|
|
|
)
|
2009-12-29 23:48:45 +00:00
|
|
|
#framework.events.on_db_request(rec)
|
2008-11-30 22:41:09 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2009-05-28 03:26:27 +00:00
|
|
|
#
|
|
|
|
# WMAP
|
2009-12-13 05:24:48 +00:00
|
|
|
# Quick way to query the database (used by wmap_sql)
|
2009-05-28 03:26:27 +00:00
|
|
|
#
|
|
|
|
def sql_query(sqlquery)
|
|
|
|
ActiveRecord::Base.connection.select_all(sqlquery)
|
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|
2006-03-21 04:37:48 +00:00
|
|
|
end
|
|
|
|
|
2008-10-23 04:23:54 +00:00
|
|
|
end
|
2009-12-13 05:24:48 +00:00
|
|
|
|