More recon hackery
git-svn-id: file:///home/svn/incoming/trunk@3585 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
3aa45638df
commit
b4189e521d
|
@ -20,3 +20,10 @@ create table services (
|
|||
'name' VARCHAR(255),
|
||||
'desc' VARCHAR(1024)
|
||||
);
|
||||
|
||||
create table vulns (
|
||||
'id' INTEGER PRIMARY KEY NOT NULL,
|
||||
'service_id' INTEGER,
|
||||
'name' VARCHAR(255),
|
||||
'data' TEXT
|
||||
);
|
||||
|
|
Binary file not shown.
|
@ -54,6 +54,26 @@ class ReadableText
|
|||
tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
#
|
||||
# Dumps an auxiliary's actions
|
||||
#
|
||||
def self.dump_auxiliary_actions(mod, indent = '', h = nil)
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Indent' => indent.length,
|
||||
'Header' => h,
|
||||
'Columns' =>
|
||||
[
|
||||
'Name',
|
||||
'Description'
|
||||
])
|
||||
|
||||
mod.actions.each_with_index { |target, idx|
|
||||
tbl << [ target.name || 'All' ]
|
||||
}
|
||||
|
||||
tbl.to_s + "\n"
|
||||
end
|
||||
|
||||
#
|
||||
# Dumps the table of payloads that are compatible with the supplied
|
||||
# exploit.
|
||||
|
|
|
@ -16,8 +16,10 @@ class Auxiliary < Msf::Module
|
|||
#
|
||||
# Auxiliary mixins
|
||||
#
|
||||
require 'msf/core/auxiliary/recon'
|
||||
require 'msf/core/auxiliary/tcp'
|
||||
|
||||
require 'msf/core/auxiliary/udp'
|
||||
|
||||
#
|
||||
# Returns MODULE_AUX to indicate that this is an auxiliary module.
|
||||
#
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for establish a connection to a remote host and
|
||||
# communicating with it.
|
||||
#
|
||||
###
|
||||
|
||||
module Auxiliary::Recon
|
||||
|
||||
def report_host(host)
|
||||
p host
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,15 +1,14 @@
|
|||
#module Msf
|
||||
#
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for establish a connection to a remote host and
|
||||
# communicating with it.
|
||||
#
|
||||
###
|
||||
#module Auxiliary::Remote::Tcp
|
||||
#
|
||||
# include Exploit::Remote::Tcp
|
||||
#
|
||||
#end
|
||||
#end
|
||||
|
||||
module Auxiliary::Tcp
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This module provides methods for establish a connection to a remote host and
|
||||
# communicating with it.
|
||||
#
|
||||
###
|
||||
|
||||
module Auxiliary::Udp
|
||||
include Exploit::Remote::Udp
|
||||
|
||||
end
|
||||
end
|
|
@ -99,22 +99,38 @@ class DBManager
|
|||
|
||||
#
|
||||
# This method iterates the services table calling the supplied block with the
|
||||
# host and service instances of each entry.
|
||||
# TODO: use the find() block syntax instead
|
||||
# service instance of each entry.
|
||||
#
|
||||
def each_service(&block)
|
||||
services.each do |service|
|
||||
block.call(service)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This methods returns a list of all services in the database
|
||||
#
|
||||
def services
|
||||
Service.find(:all)
|
||||
end
|
||||
|
||||
#
|
||||
# This method iterates the vulns table calling the supplied block with the
|
||||
# vuln instance of each entry.
|
||||
#
|
||||
def each_vuln(&block)
|
||||
vulns.each do |vulns|
|
||||
block.call(vulns)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This methods returns a list of all vulnerabilities in the database
|
||||
#
|
||||
def vulns
|
||||
Vuln.find(:all)
|
||||
end
|
||||
|
||||
def get_host(context, address, comm='')
|
||||
host = Host.find(:first, :conditions => [ "address = ? and comm = ?", address, comm])
|
||||
if (not host)
|
||||
|
@ -125,21 +141,38 @@ class DBManager
|
|||
return host
|
||||
end
|
||||
|
||||
|
||||
def get_service(host, proto, port)
|
||||
port = Service.find(:first, :conditions => [ "host_id = ? and proto = ? and port = ?", host.id, proto, port])
|
||||
if (not port)
|
||||
port = Service.create(
|
||||
:host => host,
|
||||
def get_service(context, host, proto, port)
|
||||
rec = Service.find(:first, :conditions => [ "host_id = ? and proto = ? and port = ?", host.id, proto, port])
|
||||
if (not rec)
|
||||
rec = Service.create(
|
||||
:host_id => host.id,
|
||||
:proto => proto,
|
||||
:port => port,
|
||||
:state => ServiceState::Unknown
|
||||
:state => ServiceState::Up
|
||||
)
|
||||
framework.events.on_db_service(context, host, port)
|
||||
framework.events.on_db_service(context, rec)
|
||||
end
|
||||
return port
|
||||
return rec
|
||||
end
|
||||
|
||||
def get_vuln(context, service, name, data='')
|
||||
vuln = Vuln.find(:first, :conditions => [ "name = ? and service_id = ?", name, service.id])
|
||||
if (not vuln)
|
||||
vuln= Vuln.create(
|
||||
:service_id => service.id,
|
||||
:name => name,
|
||||
:data => data
|
||||
)
|
||||
framework.events.on_db_vuln(context, vuln)
|
||||
end
|
||||
|
||||
return vuln
|
||||
end
|
||||
|
||||
def has_host?(addr)
|
||||
Host.find(:first, :conditions => [ "address = ?", addr])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -26,15 +26,20 @@ class DBManager
|
|||
@usable = false
|
||||
@active = false
|
||||
|
||||
begin
|
||||
require 'rubygems'
|
||||
require_gem 'activerecord'
|
||||
|
||||
# This double-rescue is required to detect active record when
|
||||
# it has been installed outside of gems
|
||||
begin
|
||||
begin
|
||||
require 'rubygems'
|
||||
require_gem 'activerecord'
|
||||
@usable = true
|
||||
rescue LoadError
|
||||
require 'activerecord'
|
||||
@usable = true
|
||||
end
|
||||
require 'msf/core/db_objects'
|
||||
|
||||
@usable = true
|
||||
rescue ::Exception => e
|
||||
elog("DBManager is not enabled due to load error: #{e.to_s}")
|
||||
elog("DB is not enabled due to load error: #{e.to_s}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -16,6 +16,20 @@ end
|
|||
|
||||
# Service object definition
|
||||
class Service < ActiveRecord::Base
|
||||
def host
|
||||
Host.find(:first, :conditions => [ "id = ?", host_id ])
|
||||
end
|
||||
end
|
||||
|
||||
# Vuln object definition
|
||||
class Vuln < ActiveRecord::Base
|
||||
def service
|
||||
Service.find(:first, :conditions => [ "id = ?", service_id ])
|
||||
end
|
||||
|
||||
def host
|
||||
Host.find(:first, :conditions => [ "id = ?", service.host_id ])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -253,5 +253,24 @@ class NoNopsSucceededError < RuntimeError
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Plugin exceptions
|
||||
#
|
||||
##
|
||||
|
||||
class PluginLoadError < RuntimeError
|
||||
include Exception
|
||||
attr_accessor :reason
|
||||
|
||||
def initialize(reason='')
|
||||
self.reason = reason
|
||||
super
|
||||
end
|
||||
|
||||
def to_s
|
||||
"This plugin failed to load: #{reason.to_s}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -798,6 +798,12 @@ class Core
|
|||
else
|
||||
print_error("No exploit module selected.")
|
||||
end
|
||||
when "actions"
|
||||
if (mod and mod.auxiliary?)
|
||||
show_actions(mod)
|
||||
else
|
||||
print_error("No auxiliary module selected.")
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
@ -808,7 +814,7 @@ class Core
|
|||
def cmd_show_tabs(str, words)
|
||||
res = %w{all encoders nops exploits payloads aux plugins}
|
||||
if (active_module)
|
||||
res.concat(%w{ options advanced evasion targets })
|
||||
res.concat(%w{ options advanced evasion targets actions })
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
@ -1073,13 +1079,22 @@ class Core
|
|||
when 'Msf::OptAddress'
|
||||
case o.name
|
||||
when 'RHOST'
|
||||
res << option_values_last_target()
|
||||
option_values_target_addrs().each do |addr|
|
||||
res << addr
|
||||
end
|
||||
when 'LHOST'
|
||||
res << Rex::Socket.source_address()
|
||||
else
|
||||
end
|
||||
|
||||
when 'Msf::OptPort'
|
||||
case o.name
|
||||
when 'RPORT'
|
||||
option_values_target_ports().each do |port|
|
||||
res << port
|
||||
end
|
||||
end
|
||||
|
||||
if (res.empty?)
|
||||
res << (rand(65534)+1).to_s
|
||||
end
|
||||
|
@ -1133,13 +1148,39 @@ class Core
|
|||
end
|
||||
|
||||
#
|
||||
# Provide the last target address
|
||||
# Provide the target addresses
|
||||
#
|
||||
def option_values_last_target
|
||||
# Replace this once we start tracking these things...
|
||||
return Rex::Socket.source_address()
|
||||
def option_values_target_addrs
|
||||
res = [ ]
|
||||
res << Rex::Socket.source_address()
|
||||
return res if not framework.db.active
|
||||
|
||||
framework.db.each_host do |host|
|
||||
res << host.address
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Provide the target ports
|
||||
#
|
||||
def option_values_target_ports
|
||||
res = [ ]
|
||||
return res if not framework.db.active
|
||||
return res if not self.active_module.datastore['RHOST']
|
||||
host = framework.db.has_host?(self.active_module.datastore['RHOST'])
|
||||
return res if not host
|
||||
|
||||
framework.db.each_service do |service|
|
||||
if (service.host_id == host.id)
|
||||
res << service.port.to_s
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
|
@ -1205,7 +1246,12 @@ protected
|
|||
mod_targs = Serializer::ReadableText.dump_exploit_targets(mod, ' ')
|
||||
print("\nExploit targets:\n\n#{mod_targs}\n") if (mod_targs and mod_targs.length > 0)
|
||||
end
|
||||
|
||||
|
||||
def show_actions(mod) # :nodoc:
|
||||
mod_actions = Serializer::ReadableText.dump_auxiliary_actions(mod, ' ')
|
||||
print("\nAuxiliary actions:\n\n#{mod_actions}\n") if (mod_actions and mod_actions.length > 0)
|
||||
end
|
||||
|
||||
def show_advanced_options(mod) # :nodoc:
|
||||
mod_opt = Serializer::ReadableText.dump_advanced_options(mod, ' ')
|
||||
print("\nModule advanced options:\n\n#{mod_opt}\n") if (mod_opt and mod_opt.length > 0)
|
||||
|
|
|
@ -177,7 +177,6 @@ class Driver < Msf::Ui::Driver
|
|||
rcfd.write(data)
|
||||
rcfd.close
|
||||
rescue ::Exception => e
|
||||
#
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ module Msf
|
|||
|
||||
class Plugin::DBSQLite3 < Msf::Plugin
|
||||
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements an event handler for db events
|
||||
|
@ -22,6 +20,14 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
def on_db_host(context, host)
|
||||
puts "New host event: #{host.address}"
|
||||
end
|
||||
|
||||
def on_db_service(context, service)
|
||||
puts "New service event: host=#{service.host.address} port=#{service.port} proto=#{service.proto} state=#{service.state}"
|
||||
end
|
||||
|
||||
def on_db_vuln(context, vuln)
|
||||
puts "New vuln event: host=#{vuln.host.address} port=#{vuln.service.port} proto=#{vuln.service.proto} name=#{vuln.name}"
|
||||
end
|
||||
end
|
||||
|
||||
###
|
||||
|
@ -36,7 +42,7 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
# The dispatcher's name.
|
||||
#
|
||||
def name
|
||||
"DBDispatcher"
|
||||
"Database Backend"
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -44,10 +50,13 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
#
|
||||
def commands
|
||||
{
|
||||
"db_hosts" => "List all hosts in the database db",
|
||||
"db_services" => "List all services in the database db",
|
||||
"db_insert" => "Insert a new host into the db",
|
||||
"db_test" => "Test",
|
||||
"db_hosts" => "List all hosts in the database",
|
||||
"db_services" => "List all services in the database",
|
||||
"db_vulns" => "List all vulnerabilities in the database",
|
||||
"db_add_host" => "Add one or more hosts to the database",
|
||||
"db_add_port" => "Add a port to host",
|
||||
"db_import_nessus_nbe" => "Import a Nessus scan result file (NBE)",
|
||||
# "db_import_nmap_xml" => "Import a Nmap scan results file (-oX)",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -56,31 +65,79 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
print_status("Host: #{host.address}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def cmd_db_services(*args)
|
||||
framework.db.each_service do |host, service|
|
||||
print_status("Service: host=#{host.address} port=#{service.port} port=#{service.proto}")
|
||||
framework.db.each_service do |service|
|
||||
print_status("Service: host=#{service.host.address} port=#{service.port} proto=#{service.proto} state=#{service.state}")
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_db_insert(*args)
|
||||
print_status("Inserting #{args.length.to_s} hosts...")
|
||||
|
||||
def cmd_db_vulns(*args)
|
||||
framework.db.each_vuln do |vuln|
|
||||
puts "Vuln: host=#{vuln.host.address} port=#{vuln.service.port} proto=#{vuln.service.proto} name=#{vuln.name}"
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_db_add_host(*args)
|
||||
print_status("Adding #{args.length.to_s} hosts...")
|
||||
args.each do |address|
|
||||
framework.db.get_host(nil, address)
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_db_test(*args)
|
||||
framework.db.get_host(nil, "1.2.3.4")
|
||||
framework.db.get_host(nil, "1.2.3.5")
|
||||
framework.db.get_host(nil, "1.2.3.6")
|
||||
framework.db.each_host do |host|
|
||||
print_status("Host: #{host.address}")
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_db_add_port(*args)
|
||||
if (not args or args.length < 3)
|
||||
print_status("Usage: db_add_port [host] [port] [proto]")
|
||||
return
|
||||
end
|
||||
|
||||
host = framework.db.get_host(nil, args[0])
|
||||
return if not host
|
||||
|
||||
service = framework.db.get_service(nil, host, args[2].downcase, args[1].to_i)
|
||||
return if not service
|
||||
|
||||
print_status("Service: host=#{service.host.address} port=#{service.port} proto=#{service.proto} state=#{service.state}")
|
||||
end
|
||||
|
||||
def cmd_db_import_nessus_nbe(*args)
|
||||
if (not (args and args.length == 1))
|
||||
print_status("Usage: db_import_nessus [nessus.nbe]")
|
||||
return
|
||||
end
|
||||
|
||||
if (not File.readable?(args[0]))
|
||||
print_status("Could not read the NBE file")
|
||||
return
|
||||
end
|
||||
|
||||
fd = File.open(args[0], 'r')
|
||||
fd.each_line do |line|
|
||||
r = line.split('|')
|
||||
next if r[0] != 'results'
|
||||
addr = r[2]
|
||||
nasl = r[4]
|
||||
hole = r[5]
|
||||
data = r[6]
|
||||
|
||||
m = r[3].match(/^([^\(]+)\((\d+)\/([^\)]+)\)/)
|
||||
next if not m
|
||||
|
||||
host = framework.db.get_host(nil, addr)
|
||||
next if not host
|
||||
|
||||
service = framework.db.get_service(nil, host, m[3].downcase, m[2].to_i)
|
||||
service.name = m[1]
|
||||
service.save
|
||||
|
||||
vuln = framework.db.get_vuln(nil, service, "NSS-#{nasl.to_s}", data)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
def initialize(framework, opts)
|
||||
super
|
||||
|
||||
|
@ -94,8 +151,8 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
FileUtils.copy(odb, ndb)
|
||||
|
||||
if (not framework.db.connect("adapter" => "sqlite3", "dbfile" => ndb))
|
||||
print_status("Failed to connect to the database :(")
|
||||
return
|
||||
File.unlink(ndb)
|
||||
raise PluginLoadError.new("Failed to connect to the database")
|
||||
end
|
||||
|
||||
@dbh = DBEventHandler.new
|
||||
|
@ -107,7 +164,7 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
|
||||
def cleanup
|
||||
framework.events.remove_db_subscriber(@dbh)
|
||||
remove_console_dispatcher('DBDispatcher')
|
||||
remove_console_dispatcher('Database Backend')
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -122,7 +179,7 @@ class Plugin::DBSQLite3 < Msf::Plugin
|
|||
# more than 60 characters, but there are no hard limits.
|
||||
#
|
||||
def desc
|
||||
"Loads a new SQLite3 db and intializes it"
|
||||
"Loads a new sqlite3 database backend"
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This class hooks all socket calls and updates the database with
|
||||
# data gathered from the connection parameters
|
||||
#
|
||||
###
|
||||
|
||||
class Plugin::DB_Tracer < Msf::Plugin
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements a socket communication tracker
|
||||
#
|
||||
###
|
||||
class DBTracerEventHandler
|
||||
include Rex::Socket::Comm::Events
|
||||
|
||||
def on_before_socket_create(comm, param)
|
||||
end
|
||||
|
||||
def on_socket_created(comm, sock, param)
|
||||
# Ignore local listening sockets
|
||||
return if not sock.peerhost
|
||||
|
||||
if (sock.peerhost != '0.0.0.0' and sock.peerport)
|
||||
|
||||
host = param.context['Msf'].db.get_host(param.context, sock.peerhost)
|
||||
return if not host
|
||||
|
||||
port = param.context['Msf'].db.get_service(param.context, host, param.proto, sock.peerport)
|
||||
return if not port
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(framework, opts)
|
||||
super
|
||||
|
||||
if(not framework.db.active)
|
||||
raise PluginLoadError.new("The database backend has not been initialized")
|
||||
end
|
||||
|
||||
@eh = DBTracerEventHandler.new
|
||||
Rex::Socket::Comm::Local.register_event_handler(@eh)
|
||||
end
|
||||
|
||||
def cleanup
|
||||
Rex::Socket::Comm::Local.deregister_event_handler(@eh)
|
||||
end
|
||||
|
||||
def name
|
||||
"db_tracker"
|
||||
end
|
||||
|
||||
def desc
|
||||
"Monitors socket calls and updates the database backend"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue