Merge branch '4.3-schema'

This commit is contained in:
HD Moore
2011-12-05 15:04:35 -06:00
29 changed files with 146 additions and 2753 deletions
+13
View File
@@ -0,0 +1,13 @@
class InetColumns < ActiveRecord::Migration
def self.up
change_column :hosts, :address, 'INET using address::INET'
remove_column :hosts, :address6
end
def self.down
change_column :hosts, :address, :text
add_column :hosts, :address6, :text
end
end
+17
View File
@@ -0,0 +1,17 @@
class MoreInetColumns < ActiveRecord::Migration
def self.up
change_column :wmap_requests, :address, 'INET using address::INET'
remove_column :wmap_requests, :address6
change_column :wmap_targets, :address, 'INET using address::INET'
remove_column :wmap_targets, :address6
end
def self.down
change_column :wmap_requests, :address, :string, :limit => 16
add_column :wmap_requests, :address6, :string, :limit => 255
change_column :wmap_targets, :address, :string, :limit => 16
add_column :wmap_targets, :address6, :string, :limit => 255
end
end
+2 -2
View File
@@ -51,7 +51,7 @@ module Auxiliary::JohnTheRipper
end
when /x86_64-linux/
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
data = `#{cpuinfo_base}/cpuinfo.ia64.bin` rescue nil
case data
when /mmx/
@@ -61,7 +61,7 @@ module Auxiliary::JohnTheRipper
end
when /i[\d]86-linux/
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
data = `#{cpuinfo_base}/cpuinfo.ia32.bin` rescue nil
case data
when /sse2/
+18 -10
View File
@@ -130,7 +130,7 @@ class DBManager
ip_x = ip.to_x
ip_i = ip.to_i
when "String"
if ipv4_validator(ip)
if ipv46_validator(ip)
ip_x = ip
ip_i = Rex::Socket.addr_atoi(ip)
else
@@ -154,9 +154,17 @@ class DBManager
return false
end
def ipv46_validator(addr)
ipv4_validator(addr) or ipv6_validator(addr)
end
def ipv4_validator(addr)
return false unless addr.kind_of? String
addr =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
Rex::Socket.is_ipv4?(addr)
end
def ipv6_validator(addr)
Rex::Socket.is_ipv6?(addr)
end
# Takes a space-delimited set of ips and ranges, and subjects
@@ -164,7 +172,7 @@ class DBManager
def validate_ips(ips)
ret = true
begin
ips.split(' ').each {|ip|
ips.split(/\s+/).each {|ip|
unless Rex::Socket::RangeWalker.new(ip).ranges
ret = false
break
@@ -267,7 +275,7 @@ class DBManager
if not addr.kind_of? Host
addr = normalize_host(addr)
unless ipv4_validator(addr)
unless ipv46_validator(addr)
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"
end
@@ -2215,7 +2223,7 @@ class DBManager
# then it's an amap log
@import_filedata[:type] = "Amap Log"
return :amap_log
elsif (firstline =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
elsif ipv46_validator(firstline)
# then its an IP list
@import_filedata[:type] = "IP Address List"
return :ip_list
@@ -2539,7 +2547,7 @@ class DBManager
end
next unless [addr,port,user,pass].compact.size == 4
next unless ipv4_validator(addr) # Skip Malformed addrs
next unless ipv46_validator(addr) # Skip Malformed addrs
next unless port[/^[0-9]+$/] # Skip malformed ports
if bl.include? addr
next
@@ -4302,7 +4310,7 @@ class DBManager
data = r[6]
# If there's no resolution, or if it's malformed, skip it.
next unless ipv4_validator(addr)
next unless ipv46_validator(addr)
if bl.include? addr
next
@@ -4407,7 +4415,7 @@ class DBManager
hname = host.elements['HostName'].text
end
addr ||= host.elements['HostName'].text
next unless ipv4_validator(addr) # Skip resolved names and SCAN-ERROR.
next unless ipv46_validator(addr) # Skip resolved names and SCAN-ERROR.
if bl.include? addr
next
else
@@ -4477,7 +4485,7 @@ class DBManager
hobj = nil
addr = host['addr'] || host['hname']
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
if bl.include? addr
next
@@ -4791,7 +4799,7 @@ class DBManager
hobj = nil
addr = host['addr'] || host['hname']
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
if bl.include? addr
next
+9 -1
View File
@@ -601,7 +601,15 @@ class Module
def debugging?
(datastore['DEBUG'] || '') =~ /^(1|t|y)/i
end
#
# Indicates whether the module supports IPv6. This is true by default,
# but certain modules require additional work to be compatible or are
# hardcoded in terms of application support and should be skipped.
#
def support_ipv6?
true
end
#
# This provides a standard set of search filters for every module.
-37
View File
@@ -1,37 +0,0 @@
module Msf
module RPC
class Auth < Base
def login(user,pass)
# handle authentication here
fail = true
@users.each do |u|
if(u[0] == user and u[1] == pass)
fail = false
break
end
end
if fail
# Introduce a random delay in the response to annoy brute forcers
delay = [ ( rand(3000) / 1000.0 ), 0.50 ].max
::IO.select(nil, nil, nil, delay)
# Send back a 401 denied error
raise ::XMLRPC::FaultException.new(401, "authentication error")
end
token = Rex::Text.rand_text_alphanumeric(32)
@tokens[token] = [user, Time.now.to_i, Time.now.to_i]
{ "result" => "success", "token" => token }
end
def logout(token)
@tokens.delete(token)
{ "result" => "success" }
end
end
end
end
-38
View File
@@ -1,38 +0,0 @@
module Msf
module RPC
class Base
def initialize(framework,tokens,users)
@framework = framework
@tokens = tokens
@users = users
end
private
def authenticate(token)
stale = []
# Force the encoding to ASCII-8BIT
token = token.unpack("C*").pack("C*")
@tokens.each_key do |t|
user,ctime,mtime,perm = @tokens[t]
if ! perm and mtime + 300 < Time.now.to_i
stale << t
end
end
stale.each { |t| @tokens.delete(t) }
if not @tokens[token]
raise ::XMLRPC::FaultException.new(401, "authentication error")
end
@tokens[token][2] = Time.now.to_i
end
end
end
end
-76
View File
@@ -1,76 +0,0 @@
require "xmlrpc/client"
require "rex"
module Msf
module RPC
# Loosely based on the XMLRPC::ClientS class
# Reimplemented for Metasploit
class Client < ::XMLRPC::Client
attr_accessor :sock, :token
# Use a TCP socket to do RPC
def initialize(info={})
@buff = ""
self.sock = Rex::Socket::Tcp.create(
'PeerHost' => info[:host],
'PeerPort' => info[:port],
'SSL' => info[:ssl]
)
end
# This override hooks into the RPCXML library
def do_rpc(request,async)
begin
self.sock.put(request + "\x00")
while(not @buff.index("\x00"))
if ::IO.select([self.sock], nil, nil, 30)
resp = self.sock.sysread(32768)
@buff << resp if resp
end
end
rescue ::Exception => e
self.close
raise EOFError, "XMLRPC connection closed"
end
mesg,left = @buff.split("\x00", 2)
@buff = left.to_s
mesg
end
def login(user,pass)
res = self.call("auth.login", user, pass)
if(not (res and res['result'] == "success"))
raise RuntimeError, "authentication failed"
end
self.token = res['token']
true
end
# Prepend the authentication token as the first parameter
# of every call except auth.login. Requires the
def call(meth, *args)
if(meth != "auth.login")
if(not self.token)
raise RuntimeError, "client not authenticated"
end
args.unshift(self.token)
end
super(meth, *args)
end
def close
self.sock.close rescue nil
self.sock = nil
end
end
end
end
-87
View File
@@ -1,87 +0,0 @@
require 'pp'
require 'rex'
require 'msf/ui/web/driver'
module Msf
module RPC
class Console < Base
def initialize(framework,tokens,users)
super(framework, tokens, users)
@console_driver = Msf::Ui::Web::Driver.new(:framework => framework)
end
def create(token)
authenticate(token)
cid = @console_driver.create_console
{
'id' => cid,
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
'busy' => @console_driver.consoles[cid].busy || false,
'encoding' => "base64"
}
end
def list(token)
authenticate(token)
ret = []
@console_driver.consoles.each_key do |cid|
ret << {
'id' => cid,
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
'busy' => @console_driver.consoles[cid].busy || false,
'encoding' => "base64"
}
end
{'consoles' => ret}
end
def destroy(token, cid)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
res = @console_driver.destroy_console(cid)
{ 'result' => res ? 'success' : 'failure' }
end
def read(token, cid)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
{
"data" => Rex::Text.encode_base64(@console_driver.read_console(cid) || ''),
"prompt" => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
"busy" => @console_driver.consoles[cid].busy || false,
"encoding" => "base64"
}
end
def write(token, cid, data)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
{ "wrote" => @console_driver.write_console(cid, Rex::Text.decode_base64(data || '')) }
end
def tabs(token, cid, line)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
{ "tabs" => @console_driver.consoles[cid].tab_complete(line) }
end
def session_kill(token, cid)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
@console_driver.consoles[cid].session_kill
{ 'result' => 'success' }
end
def session_detach(token, cid)
authenticate(token)
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
@console_driver.consoles[cid].session_detach
{ 'result' => 'success' }
end
end
end
end
-27
View File
@@ -1,27 +0,0 @@
module Msf
module RPC
class Core < Base
def initialize(framework, tokens, users, server=nil)
@server = server
super(framework, tokens, users)
end
def version(token)
authenticate(token)
{ "version" => ::Msf::Framework::Version, "ruby" => "#{RUBY_VERSION} #{RUBY_PLATFORM} #{RUBY_RELEASE_DATE}" }
end
#
# Stop the RPC server. This method will never return a value to the client
# because the socket for communicating with it will be closed.
#
def stop(token)
authenticate(token)
@server.stop_rpc if @server
nil
end
end
end
end
-1352
View File
@@ -1,1352 +0,0 @@
module Msf
module RPC
class Db < Base
private
def db
@framework.db.active
end
def workspace(wspace = nil)
if(wspace and wspace != "")
return @framework.db.find_workspace(wspace)
end
@framework.db.workspace
end
def fix_options(opts)
newopts = {}
opts.each do |k,v|
newopts[k.to_sym] = v
end
newopts
end
def opts_to_hosts(opts)
wspace = workspace(opts[:workspace])
hosts = []
if opts[:host] or opts[:address]
host = opts[:host] || opts[:address]
hent = wspace.hosts.find_by_address(host)
return hosts if hent == nil
hosts << hent if hent.class == Msf::DBManager::Host
hosts |= hent if hent.class == Array
elsif opts[:addresses]
return hosts if opts[:addresses].class != Array
conditions = {}
conditions[:address] = opts[:addresses]
hent = wspace.hosts.all(:conditions => conditions)
hosts |= hent if hent.class == Array
end
return hosts
end
def opts_to_services(hosts,opts)
wspace = workspace(opts[:workspace])
services = []
if opts[:host] or opts[:address] or opts[:addresses]
return services if hosts.count < 1
hosts.each do |h|
if opts[:port] or opts[:proto]
conditions = {}
conditions[:port] = opts[:port] if opts[:port]
conditions[:proto] = opts[:proto] if opts[:proto]
sret = h.services.all(:conditions => conditions)
next if sret == nil
services |= sret if sret.class == Array
services << sret if sret.class == Msf::DBManager::Service
else
services |= h.services
end
end
elsif opts[:port] or opts[:proto]
conditions = {}
conditions[:port] = opts[:port] if opts[:port]
conditions[:proto] = opts[:proto] if opts[:proto]
sret = wspace.services.all(:conditions => conditions)
services |= sret if sret.class == Array
services << sret if sret.class == Msf::DBManager::Service
end
return services
end
def clean_nils(obj)
return '' if obj == nil
if obj.is_a? Hash
obj.each_key do |key|
obj[key] = clean_nils(obj[key])
end
elsif obj.is_a? Array
obj.each_with_index do |ob, i|
obj[i] = clean_nils(ob)
end
end
obj
end
public
def hosts(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
conditions = {}
conditions[:state] = [Msf::HostState::Alive, Msf::HostState::Unknown] if opts[:only_up]
conditions[:address] = opts[:addresses] if opts[:addresses]
wspace = workspace(opts[:workspace])
ret = {}
ret[:hosts] = []
wspace.hosts.all(:conditions => conditions, :order => :address).each do |h|
host = {}
host[:created_at] = h.created_at.to_i
host[:address] = h.address.to_s
host[:address6] = h.address6.to_s
host[:mac] = h.mac.to_s
host[:name] = h.name.to_s
host[:state] = h.state.to_s
host[:os_name] = h.os_name.to_s
host[:os_flavor] = h.os_flavor.to_s
host[:os_sp] = h.os_sp.to_s
host[:os_lang] = h.os_lang.to_s
host[:updated_at] = h.updated_at.to_i
host[:purpose] = h.purpose.to_s
host[:info] = h.info.to_s
ret[:hosts] << host
end
ret
end
def services(token, xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
opts[:workspace] = wspace if opts[:workspace]
hosts = []
if opts[:addresses]
conditions = {}
conditions[:address] = opts[:addresses] if opts[:addresses]
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
elsif opts[:host] || opts[:address]
host = @framework.db.get_host(opts)
hosts << host
end
ret = {}
ret[:services] = []
a = @framework.db.get_host(opts)
services = []
if opts[:host] || opts[:address] || opts[:addresses]
hosts.each do |host|
sret = nil
if(opts[:proto] && opts[:port])
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
else
sret = host.services
end
next if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
end
else
services = wspace.services
end
return ret if (not services)
services.each do |s|
service = {}
host = s.host
service[:host] = host.address || host.address6 || "unknown"
service[:created_at] = s[:created_at].to_i
service[:updated_at] = s[:updated_at].to_i
service[:port] = s[:port]
service[:proto] = s[:proto].to_s
service[:state] = s[:state].to_s
service[:name] = s[:name].to_s
service[:info] = s[:info].to_s
ret[:services] << service
end
ret
end
def vulns(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
opts[:workspace] = wspace if opts[:workspace]
ret = {}
ret[:vulns] = []
hosts = []
services = []
vulns = []
# Get Matching Hosts
if opts[:addresses]
conditions = {}
conditions[:address] = opts[:addresses] if opts[:addresses]
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
elsif opts[:host] || opts[:address]
host = @framework.db.get_host(opts)
hosts << host
end
#Get Matching Services
if opts[:host] || opts[:address] || opts[:addresses]
hosts.each do |host|
sret = nil
if(opts[:proto] && opts[:port])
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
else
sret = host.services
end
next if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
end
elsif opts[:port] && opts[:proto]
sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port])
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
end
#get list of vulns
if services.count > 0
services.each do |s|
if opts[:name]
nret = s.vulns.find_by_name(opts[:name])
else
nret = s.vulns
end
next if nret == nil
vulns << nret if nret.class == Msf::DBManager::Vuln
vulns |= nret if nret.class == Array
end
elsif hosts.count > 0
hosts.each do |h|
if opts[:name]
nret = h.vulns.find_by_name(opts[:name])
else
nret = h.vulns
end
next if nret == nil
vulns << nret if nret.class == Msf::DBManager::Vuln
vulns |= nret if nret.class == Array
end
else
nret = wspace.vulns
vulns << nret if nret.class == Msf::DBManager::Vuln
vulns |= nret if nret.class == Array
end
vulns.each do |v|
vuln = {}
reflist = v.refs.map { |r| r.name }
if(v.service)
vuln[:port] = v.service.port
vuln[:proto] = v.service.proto
else
vuln[:port] = nil
vuln[:proto] = nil
end
vuln[:time] = v.created_at.to_i
vuln[:host] = v.host.address || v.host.address6 || nil
vuln[:name] = v.name
vuln[:refs] = reflist.join(',')
ret[:vulns] << vuln
end
clean_nils(ret)
end
def workspaces(token)
authenticate(token)
if(not db)
raise ::XMLRPC::FaultException.new(404, "database not loaded")
end
res = {}
res[:workspaces] = []
@framework.db.workspaces.each do |j|
ws = {}
ws[:name] = j.name
ws[:created_at] = j.created_at.to_i
ws[:updated_at] = j.updated_at.to_i
res[:workspaces] << ws
end
res
end
def current_workspace(token)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
{ "workspace" => @framework.db.workspace.name }
end
def get_workspace(token,wspace)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
wspace = workspace(wspace)
ret = {}
ret[:workspace] = []
if(wspace)
w = {}
w[:name] = wspace.name
w[:created_at] = wspace.created_at.to_i
w[:modified_at] = wspace.modified_at.to_i
ret[:workspace] << w
end
ret
end
def set_workspace(token,wspace)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
workspace = @framework.db.find_workspace(wspace)
if(workspace)
@framework.db.workspace = workspace
return { 'result' => "success" }
end
{ 'result' => 'failed' }
end
def del_workspace(token,wspace)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
# Delete workspace
workspace = @framework.db.find_workspace(wspace)
if workspace.nil?
raise ::XMLRPC::FaultException.new(404, "Workspace not found: #{wspace}")
elsif workspace.default?
workspace.destroy
workspace = @framework.db.add_workspace(workspace.name)
else
# switch to the default workspace if we're about to delete the current one
@framework.db.workspace = @framework.db.default_workspace if @framework.db.workspace.name == workspace.name
# now destroy the named workspace
workspace.destroy
end
{ 'result' => "success" }
end
def add_workspace(token,wspace)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
wspace = @framework.db.add_workspace(wspace)
return { 'result' => 'success' } if(wspace)
{ 'result' => 'failed' }
end
def get_host(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
ret = {}
ret[:host] = []
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
h = @framework.db.get_host(opts)
if(h)
host = {}
host[:created_at] = h.created_at.to_i
host[:address] = h.address.to_s
host[:address6] = h.address6.to_s
host[:mac] = h.mac.to_s
host[:name] = h.name.to_s
host[:state] = h.state.to_s
host[:os_name] = h.os_name.to_s
host[:os_flavor] = h.os_flavor.to_s
host[:os_sp] = h.os_sp.to_s
host[:os_lang] = h.os_lang.to_s
host[:updated_at] = h.updated_at.to_i
host[:purpose] = h.purpose.to_s
host[:info] = h.info.to_s
ret[:host] << host
end
ret
end
def report_host(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_host(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
def report_service(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_service(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
def get_service(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
opts[:workspace] = wspace if opts[:workspace]
ret = {}
ret[:service] = []
host = @framework.db.get_host(opts)
services = []
sret = nil
if(host && opts[:proto] && opts[:port])
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
elsif(opts[:proto] && opts[:port])
conditions = {}
conditions[:state] = [ServiceState::Open] if opts[:up]
conditions[:proto] = opts[:proto] if opts[:proto]
conditions[:port] = opts[:port] if opts[:port]
conditions[:name] = opts[:names] if opts[:names]
sret = wspace.services.all(:conditions => conditions, :order => "hosts.address, port")
else
sret = host.services
end
return ret if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
services.each do |s|
service = {}
host = s.host
service[:host] = host.address || host.address6 || "unknown"
service[:created_at] = s[:created_at].to_i
service[:updated_at] = s[:updated_at].to_i
service[:port] = s[:port]
service[:proto] = s[:proto].to_s
service[:state] = s[:state].to_s
service[:name] = s[:name].to_s
service[:info] = s[:info].to_s
ret[:service] << service
end
ret
end
def get_note(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
ret = {}
ret[:note] = []
host = @framework.db.get_host(opts)
return ret if( not host)
notes = []
if(opts[:proto] && opts[:port])
services = []
nret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
return ret if nret == nil
services << nret if nret.class == Msf::DBManager::Service
services |= nret if nret.class == Array
services.each do |s|
nret = nil
if opts[:ntype]
nret = s.notes.find_by_ntype(opts[:ntype])
else
nret = s.notes
end
next if nret == nil
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
else
notes = host.notes
end
notes.each do |n|
note = {}
host = n.host
note[:host] = host.address || host.address6 || "unknown"
if n.service
note[:port] = n.service.port
note[:proto] = n.service.proto
end
note[:created_at] = n[:created_at].to_i
note[:updated_at] = n[:updated_at].to_i
note[:ntype] = n[:ntype].to_s
note[:data] = n[:data]
note[:critical] = n[:critical].to_s
note[:seen] = n[:seen].to_s
ret[:note] << note
end
ret
end
def get_client(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
ret = {}
ret[:client] = []
c = @framework.db.get_client(opts)
if(c)
client = {}
host = c.host
client[:host] = host.address
client[:created_at] = c.created_at.to_i
client[:updated_at] = c.updated_at.to_i
client[:ua_string] = c.ua_string.to_s
client[:ua_name] = c.ua_name.to_s
client[:ua_ver] = c.ua_ver.to_s
ret[:client] << client
end
ret
end
def report_client(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_client(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
#DOC NOTE: :data and :ntype are REQUIRED
def report_note(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
if (opts[:host] or opts[:address]) and opts[:port] and opts[:proto]
addr = opts[:host] || opts[:address]
wspace = opts[:workspace] || @framework.db.workspace
host = wspace.hosts.find_by_address(addr)
service = host.services.find_by_proto_and_port(opts[:proto],opts[:port]) if host.services.count > 0
opts[:service] = service if service
end
res = @framework.db.report_note(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
def notes(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace]) if opts[:workspace]
opts[:workspace] = wspace
ret = {}
ret[:notes] = []
hosts = []
services = []
notes = []
# Get Matching Hosts
if opts[:addresses]
conditions = {}
conditions[:address] = opts[:addresses] if opts[:addresses]
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
elsif opts[:host] || opts[:address]
host = @framework.db.get_host(opts)
hosts << host
end
#Get Matching Services
if opts[:host] || opts[:address] || opts[:addresses]
hosts.each do |host|
sret = nil
if(opts[:proto] && opts[:port])
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
else
sret = host.services
end
next if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
end
elsif opts[:port] && opts[:proto]
sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port])
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
end
#get list of notes
if services.count > 0
services.each do |s|
if opts[:ntype]
nret = s.notes.find_by_ntype(opts[:ntype])
else
nret = s.notes
end
next if nret == nil
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
elsif hosts.count > 0
hosts.each do |h|
if opts[:ntype]
nret = h.notes.find_by_ntype(opts[:ntype])
else
nret = h.notes
end
next if nret == nil
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
else
nret = wspace.notes
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
notes.each do |n|
note = {}
note[:time] = n.created_at.to_i
note[:host] = ""
note[:service] = ""
note[:host] = n.host.address || n.host.address6 if(n.host)
note[:service] = n.service.name || n.service.port if(n.service)
note[:type ] = n.ntype.to_s
note[:data] = n.data.inspect
ret[:notes] << note
end
ret
end
def report_auth_info(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_auth_info(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
def get_auth_info(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
ret = {}
ret[:auth_info] = []
ai = @framework.db.get_auth_info(opts)
ai.each do |i|
info = {}
i.each do |k,v|
info[k.to_sym] = v
end
ret[:auth_info] << info
end
ret
end
def get_ref(token,name)
authenticate(token)
return @framework.db.get_ref(name)
end
def del_vuln(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
services = []
vulns = []
if opts[:host] or opts[:address] or opts[:addresses]
hosts = opts_to_hosts(opts)
end
if opts[:port] or opts[:proto]
if opts[:host] or opts[:address] or opts[:addresses]
services = opts_to_services(hosts,opts)
else
services = opts_to_services([],opts)
end
end
if opts[:port] or opts[:proto]
services.each do |s|
vret = nil
if opts[:name]
vret = s.vulns.find_by_name(opts[:name])
else
vret = s.vulns
end
next if vret == nil
vulns << vret if vret.class == Msf::DBManager::Vuln
vulns |= vret if vret.class == Array
end
elsif opts[:address] or opts[:host] or opts[:addresses]
hosts.each do |h|
vret = nil
if opts[:name]
vret = h.vulns.find_by_name(opts[:name])
else
vret = h.vulns
end
next if vret == nil
vulns << vret if vret.class == Msf::DBManager::Vuln
vulns |= vret if vret.class == Array
end
else
vret = nil
if opts[:name]
vret = wspace.vulns.find_by_name(opts[:name])
else
vret = wspace.vulns
end
vulns << vret if vret.class == Msf::DBManager::Vuln
vulns |= vret if vret.class == Array
end
deleted = []
vulns.each do |v|
dent = {}
dent[:address] = v.host.address.to_s if v.host
dent[:port] = v.service.port if v.service
dent[:proto] = v.service.proto if v.service
dent[:name] = v.name
deleted << dent
v.destroy
end
return { :result => 'success', :deleted => deleted }
end
def del_note(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
services = []
notes = []
if opts[:host] or opts[:address] or opts[:addresses]
hosts = opts_to_hosts(opts)
end
if opts[:port] or opts[:proto]
if opts[:host] or opts[:address] or opts[:addresses]
services = opts_to_services(hosts,opts)
else
services = opts_to_services([],opts)
end
end
if opts[:port] or opts[:proto]
services.each do |s|
nret = nil
if opts[:ntype]
nret = s.notes.find_by_ntype(opts[:ntype])
else
nret = s.notes
end
next if nret == nil
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
elsif opts[:address] or opts[:host] or opts[:addresses]
hosts.each do |h|
nret = nil
if opts[:ntype]
nret = h.notes.find_by_ntype(opts[:ntype])
else
nret = h.notes
end
next if nret == nil
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
else
nret = nil
if opts[:ntype]
nret = wspace.notes.find_by_ntype(opts[:ntype])
else
nret = wspace.notes
end
notes << nret if nret.class == Msf::DBManager::Note
notes |= nret if nret.class == Array
end
deleted = []
notes.each do |n|
dent = {}
dent[:address] = n.host.address.to_s if n.host
dent[:port] = n.service.port if n.service
dent[:proto] = n.service.proto if n.service
dent[:ntype] = n.ntype
deleted << dent
n.destroy
end
return { :result => 'success', :deleted => deleted }
end
def del_service(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
services = []
if opts[:host] or opts[:address]
host = opts[:host] || opts[:address]
hent = wspace.hosts.find_by_address(host)
return { :result => 'failed' } if hent == nil or hent.class != Msf::DBManager::Host
hosts << hent
elsif opts[:addresses]
return { :result => 'failed' } if opts[:addresses].class != Array
conditions = { :address => opts[:addresses] }
hent = wspace.hosts.all(:conditions => conditions)
return { :result => 'failed' } if hent == nil
hosts |= hent if hent.class == Array
hosts << hent if hent.class == Msf::DBManager::Host
end
if opts[:addresses] or opts[:address] or opts[:host]
hosts.each do |h|
sret = nil
if opts[:port] or opts[:proto]
conditions = {}
conditions[:port] = opts[:port] if opts[:port]
conditions[:proto] = opts[:proto] if opts[:proto]
sret = h.services.all(:conditions => conditions)
next if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
else
services |= h.services
end
end
elsif opts[:port] or opts[:proto]
conditions = {}
conditions[:port] = opts[:port] if opts[:port]
conditions[:proto] = opts[:proto] if opts[:proto]
sret = wspace.services.all(:conditions => conditions)
services << sret if sret and sret.class == Msf::DBManager::Service
services |= sret if sret and sret.class == Array
end
deleted = []
services.each do |s|
dent = {}
dent[:address] = s.host.address.to_s
dent[:port] = s.port
dent[:proto] = s.proto
deleted << dent
s.destroy
end
return { :result => 'success', :deleted => deleted }
end
def del_host(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
if opts[:host] or opts[:address]
host = opts[:host] || opts[:address]
hent = wspace.hosts.find_by_address(host)
return { :result => 'failed' } if hent == nil or hent.class != Msf::DBManager::Host
hosts << hent
elsif opts[:addresses]
return { :result => 'failed' } if opts[:addresses].class != Array
conditions = { :address => opts[:addresses] }
hent = wspace.hosts.all(:conditions => conditions)
return { :result => 'failed' } if hent == nil
hosts |= hent if hent.class == Array
hosts << hent if hent.class == Msf::DBManager::Host
end
deleted = []
hosts.each do |h|
deleted << h.address.to_s
h.destroy
end
return { :result => 'success', :deleted => deleted }
end
def report_vuln(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_vuln(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
def events(token,wspace = nil)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
wspace = workspace(wspace)
raise ::XMLRPC::FaultException.new(404, "unknown workspace") if(not wspace)
ret = {}
ret[:events] = []
@framework.db.events(wspace).each do |e|
event = {}
event[:host] = e.host.address || e.host.address6 if(e.host)
event[:created_at] = e.created_at.to_i
event[:updated_at] = e.updated_at.to_i
event[:name] = e.name
event[:critical] = e.critical if(e.critical)
event[:username] = e.username if(e.username)
event[:info] = e.info
ret[:events] << event
end
clean_nils(ret)
end
def report_event(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
res = @framework.db.report_event(opts)
return { :result => 'success' } if(res)
end
#NOTE Path is required
#NOTE To match a service need host, port, proto
def report_loot(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
if opts[:host] && opts[:port] && opts[:proto]
opts[:service] = @framework.db.find_or_create_service(opts)
end
res = @framework.db.report_loot(opts)
return { :result => 'success' } if(res)
end
def loots(token,wspace=nil)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
wspace = workspace(wspace)
raise ::XMLRPC::FaultException.new(404, "unknown workspace") if(not wspace)
ret = {}
ret[:loots] = []
@framework.db.loots(wspace).each do |l|
loot = {}
loot[:host] = l.host.address || l.host.address6 if(l.host)
loot[:service] = l.service.name || l.service.port if(l.service)
loot[:ltype] = l.ltype
loot[:content_type] = l.content_type
loot[:data] = l.data if (l.data)
loot[:created_at] = l.created_at.to_i
loot[:updated_at] = l.updated_at.to_i
loot[:name] = l.name if (l.name)
loot[:info] = l.info if (l.info)
loot[:path] = l.path
ret[:loots] << loot
end
ret
end
# requires host, port, user, pass, ptype, and active
def report_cred(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
res = framework.db.find_or_create_cred(opts)
return { :result => 'success' } if(res)
{ :result => 'failed' }
end
#right now workspace is the only option supported
def creds(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
ret = {}
ret[:creds] = []
@framework.db.creds(wspace).each do |c|
cred = {}
cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host)
cred[:time] = c.updated_at
cred[:port] = c.service.port
cred[:proto] = c.service.proto
cred[:sname] = c.service.name
cred[:type] = c.ptype
cred[:user] = c.user
cred[:pass] = c.pass
cred[:active] = c.active
ret[:creds] << cred
end
ret
end
def import_data(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_msfe_xml(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nexpose_simplexml(args={})
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nexpose_rawxml(args={})
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nmap_xml(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nessus_nbe(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nessus_xml(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_nessus_xml_v2(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_qualys_xml(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_ip_list(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_amap_log(args={})
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def import_amap_mlog(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
opts[:data] = Rex::Text.decode_base64(opts[:data])
@framework.db.import(opts)
return { :result => 'success' }
end
def get_vuln(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
ret = {}
ret[:vuln] = []
host = @framework.db.get_host(opts)
return ret if( not host)
vulns = []
if(opts[:proto] && opts[:port])
services = []
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
return ret if sret == nil
services << sret if sret.class == Msf::DBManager::Service
services |= sret if sret.class == Array
services.each do |s|
vulns |= s.vulns
end
else
vulns = host.vulns
end
return ret if (not vulns)
vulns.each do |v|
vuln= {}
host= v.host
vuln[:host] = host.address || host.address6 || "unknown"
if v.service
vuln[:port] = v.service.port
vuln[:proto] = v.service.proto
end
vuln[:created_at] = v[:created_at].to_i
vuln[:updated_at] = v[:updated_at].to_i
vuln[:name] = v[:name].to_s
vuln[:info] = v[:info].to_s
vuln[:refs] = []
v.refs.each do |r|
vuln[:refs] << r.name
end
ret[:vuln] << vuln
end
ret
end
def clients(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
clients = []
ret = {}
ret[:clients] = []
if opts[:host] or opts[:address] or opts[:addresses]
hosts = opts_to_hosts(opts)
else
hosts = wspace.hosts
end
hosts.each do |h|
cret = nil
if opts[:ua_name] or opts[:ua_ver]
conditions = {}
conditions[:ua_name] = opts[:ua_name] if opts[:ua_name]
conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver]
cret = h.clients.all(:conditions => conditions)
else
cret = h.clients
end
next if cret == nil
clients << cret if cret.class == Msf::DBManager::Client
clients |= cret if cret.class == Array
end
clients.each do |c|
client = {}
client[:host] = c.host.address.to_s if c.host
client[:ua_string] = c.ua_string
client[:ua_name] = c.ua_name
client[:ua_ver] = c.ua_ver
client[:created_at] = c.created_at.to_i
client[:updated_at] = c.updated_at.to_i
ret[:clients] << client
end
clean_nils(ret)
end
def del_client(token,xopts)
authenticate(token)
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
opts = fix_options(xopts)
wspace = workspace(opts[:workspace])
hosts = []
clients = []
if opts[:host] or opts[:address] or opts[:addresses]
hosts = opts_to_hosts(opts)
else
hosts = wspace.hosts
end
hosts.each do |h|
cret = nil
if opts[:ua_name] or opts[:ua_ver]
conditions = {}
conditions[:ua_name] = opts[:ua_name] if opts[:ua_name]
conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver]
cret = h.clients.all(:conditions => conditions)
else
cret = h.clients
end
next if cret == nil
clients << cret if cret.class == Msf::DBManager::Client
clients |= cret if cret.class == Array
end
deleted = []
clients.each do |c|
dent = {}
dent[:address] = c.host.address.to_s
dent[:ua_string] = c.ua_string
deleted << dent
c.destroy
end
return { :result => 'success', :deleted => deleted }
end
def driver(token,xopts)
authenticate(token)
opts = fix_options(xopts)
if opts[:driver]
if @framework.db.drivers.include?(opts[:driver])
@framework.db.driver = opts[:driver]
return { :result => 'success' }
else
return { :result => 'failed' }
end
else
return { :driver => @framework.db.driver.to_s }
end
return { :result => 'failed' }
end
def connect(token,xopts)
authenticate(token)
opts = fix_options(xopts)
if(not @framework.db.driver and not opts[:driver])
return { :result => 'failed' }
end
if opts[:driver]
if @framework.db.drivers.include?(opts[:driver])
@framework.db.driver = opts[:driver]
else
return { :result => 'failed' }
end
end
driver = @framework.db.driver
case driver
when 'postgresql'
opts['adapter'] = 'postgresql'
else
return { :result => 'failed' }
end
if (not @framework.db.connect(opts))
return { :result => 'failed' }
end
return { :result => 'success' }
end
def status(token)
authenticate(token)
if (not @framework.db.driver)
return {:driver => 'None' }
end
cdb = ""
if ActiveRecord::Base.connected? and ActiveRecord::Base.connection.active?
if ActiveRecord::Base.connection.respond_to? :current_database
cdb = ActiveRecord::Base.connection.current_database
else
cdb = ActiveRecord::Base.connection.instance_variable_get(:@config)[:database]
end
return {:driver => @framework.db.driver.to_s , :db => cdb }
else
return {:driver => @framework.db.driver.to_s}
end
return {:driver => 'None' }
end
def disconnect(token)
authenticate(token)
if (@framework.db)
@framework.db.disconnect()
return { :result => 'success' }
else
return { :result => 'failed' }
end
end
end
end
end
-49
View File
@@ -1,49 +0,0 @@
module Msf
module RPC
class Job < Base
def list(token)
authenticate(token)
res = {}
res['jobs'] = {}
@framework.jobs.each do |j|
res['jobs'][j[0]] = j[1].name
end
res
end
def stop(token,jid)
authenticate(token)
obj = @framework.jobs[jid.to_s]
if(not obj)
raise ::XMLRPC::FaultException.new(404, "no such job")
else
obj.stop
{ "result" => "success" }
end
end
def info(token,jid)
authenticate(token)
obj = @framework.jobs[jid.to_s]
if(not obj)
raise ::XMLRPC::FaultException.new(404, "no such job")
else
info = {
"jid" => obj.jid,
"name" => obj.name,
"start_time" => obj.start_time.to_i
}
if obj.ctx && obj.ctx[0]
if obj.ctx[0].respond_to?(:get_resource)
info['uripath'] = obj.ctx[0].get_resource
end
if obj.ctx[0].respond_to?(:datastore)
info['datastore'] = obj.ctx[0].datastore
end
end
{ "result" => "success" , "info" => info}
end
end
end
end
end
-333
View File
@@ -1,333 +0,0 @@
##
# $Id$
##
module Msf
module RPC
class Module < Base
def exploits(token)
authenticate(token)
{ "modules" => @framework.exploits.keys }
end
def auxiliary(token)
authenticate(token)
{ "modules" => @framework.auxiliary.keys }
end
def payloads(token)
authenticate(token)
{ "modules" => @framework.payloads.keys }
end
def encoders(token)
authenticate(token)
{ "modules" => @framework.encoders.keys }
end
def nops(token)
authenticate(token)
{ "modules" => @framework.nops.keys }
end
def post(token)
authenticate(token)
{ "modules" => @framework.post.keys }
end
def info(token, mtype, mname)
authenticate(token)
m = _find_module(mtype,mname)
res = {}
res['name'] = m.name
res['description'] = m.description
res['license'] = m.license
res['filepath'] = m.file_path
res['version'] = m.version
res['rank'] = m.rank.to_i
res['references'] = []
m.references.each do |r|
res['references'] << [r.ctx_id, r.ctx_val]
end
res['authors'] = []
m.each_author do |a|
res['authors'] << a.to_s
end
if(m.type == "exploit")
res['targets'] = {}
m.targets.each_index do |i|
res['targets'][i] = m.targets[i].name
end
if (m.default_target)
res['default_target'] = m.default_target
end
end
if(m.type == "auxiliary")
res['actions'] = {}
m.actions.each_index do |i|
res['actions'][i] = m.actions[i].name
end
if (m.default_action)
res['default_action'] = m.default_action
end
end
res
end
def compatible_payloads(token, mname)
authenticate(token)
m = _find_module('exploit',mname)
if(not m)
raise ::XMLRPC::FaultException.new(404, "unknown module")
end
res = {}
res['payloads'] = []
m.compatible_payloads.each do |k|
res['payloads'] << k[0]
end
res
end
def compatible_sessions(token, mname)
authenticate(token)
m = _find_module('post',mname)
if(not m)
raise ::XMLRPC::FaultException.new(404, "unknown module")
end
res = {}
res['sessions'] = m.compatible_sessions
res
end
def target_compatible_payloads(token, mname, target)
authenticate(token)
m = _find_module('exploit',mname)
if(not m)
raise ::XMLRPC::FaultException.new(404, "unknown module")
end
res = {}
res['payloads'] = []
m.datastore['TARGET'] = target.to_i
m.compatible_payloads.each do |k|
res['payloads'] << k[0]
end
res
end
def options(token, mtype, mname)
authenticate(token)
m = _find_module(mtype,mname)
res = {}
m.options.each_key do |k|
o = m.options[k]
res[k] = {
'type' => o.type,
'required' => o.required,
'advanced' => o.advanced,
'evasion' => o.evasion,
'desc' => o.desc
}
if(not o.default.nil?)
res[k]['default'] = o.default
end
if(o.enums.length > 1)
res[k]['enums'] = o.enums
end
end
res
end
def execute(token, mtype, mname, opts)
authenticate(token)
mod = _find_module(mtype,mname)
case mtype
when 'exploit'
_run_exploit(mod, opts)
when 'auxiliary'
_run_auxiliary(mod, opts)
when 'payload'
_run_payload(mod, opts)
when 'post'
_run_post(mod, opts)
end
end
def encode(token, data, encoder, options)
authenticate(token)
buf = Rex::Text.decode_base64(data)
# Load supported formats
supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
if (fmt = options['format'])
if not supported_formats.include?(fmt)
raise ::XMLRPC::FaultException.new(500, "failed to generate: invalid format: #{fmt}")
end
end
badchars = ''
if options['badchars']
badchars = Rex::Text.hex_to_raw(options['badchars'])
end
plat = nil
if options['plat']
plat = Msf::Module::PlatformList.transform(val)
end
arch = nil
if options['arch']
arch = options['arch']
end
ecount = 1
if options['ecount']
ecount = options['ecount'].to_i
end
exeopts = {
:inject => options['inject'],
:template => options['altexe'],
:template_path => options['exedir']
}
# If we were given addshellcode for a win32 payload,
# create a double-payload; one running in one thread, one running in the other
if options['addshellcode']
buf = Msf::Util::EXE.win32_rwx_exec_thread(buf,0,'end')
file = ::File.new(options['addshellcode'])
file.binmode
buf << file.read
file.close
end
enc = @framework.encoders.create(encoder)
begin
# Imports options
enc.datastore.update(options)
raw = buf.dup
1.upto(ecount) do |iteration|
# Encode it up
raw = enc.encode(raw, badchars, nil, plat)
end
output = Msf::Util::EXE.to_executable_fmt(@framework, arch, plat, raw, fmt, exeopts)
if not output
fmt ||= "ruby"
output = Msf::Simple::Buffer.transform(raw, fmt)
end
# How to warn?
#if exeopts[:fellback]
# $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}")
#end
{"encoded" => Rex::Text.encode_base64(output.to_s)}
rescue => e
raise ::XMLRPC::FaultException.new(500, "#{enc.refname} failed: #{e} #{e.backtrace}")
end
end
private
def _find_module(mtype,mname)
mod = @framework.modules.create(mname)
if(not mod)
raise ::XMLRPC::FaultException.new(404, "unknown module")
end
mod
end
def _run_exploit(mod, opts)
s = Msf::Simple::Exploit.exploit_simple(mod, {
'Payload' => opts['PAYLOAD'],
'Target' => opts['TARGET'],
'RunAsJob' => true,
'Options' => opts
})
{"result" => "success"}
end
def _run_auxiliary(mod, opts)
Msf::Simple::Auxiliary.run_simple(mod, {
'Action' => opts['ACTION'],
'RunAsJob' => true,
'Options' => opts
})
{"result" => "success"}
end
def _run_payload(mod, opts)
badchars = [opts['BadChars'] || ''].pack("H*")
fmt = opts['Format'] || 'raw'
force = opts['ForceEncode'] || false
template = opts['Template'] || nil
plat = opts['Platform'] || nil
keep = opts['KeepTemplateWorking'] || false
force = opts['ForceEncode'] || false
sled_size = opts['NopSledSize'].to_i || 0
iter = opts['Iterations'].to_i || 0
begin
res = Msf::Simple::Payload.generate_simple(mod, {
'BadChars' => badchars,
'Encoder' => opts['Encoder'],
'Format' => fmt,
'NoComment' => true,
'NopSledSize' => sled_size,
'Options' => opts,
'ForceEncode' => force,
'Template' => template,
'Platform' => plat,
'KeepTemplateWorking' => keep,
'Iterations' => iter
})
{"result" => "success", "payload" => res.unpack("H*")[0]}
rescue ::Exception => e
raise ::XMLRPC::FaultException.new(500, "failed to generate: #{e.message}")
end
end
def _run_post(mod, opts)
Msf::Simple::Post.run_simple(mod, {
'RunAsJob' => true,
'Options' => opts
})
{"result" => "success"}
end
end
end
end
-63
View File
@@ -1,63 +0,0 @@
module Msf
module RPC
class Plugin < Base
def load(token,path,xopts = {})
authenticate(token)
opts = {}
xopts.each do |k,v|
if k.class == String
opts[k.to_sym] = v
end
end
if (path !~ /#{File::SEPARATOR}/)
plugin_file_name = path
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
if not File.exists?( path + ".rb" )
# If the following "path" doesn't exist it will be caught when we attempt to load
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
end
end
begin
if (inst = @framework.plugins.load(path, opts))
return { "result" => "success" }
end
rescue ::Exception => e
elog("Error loading plugin #{path}: #{e}\n\n#{e.backtrace.join("\n")}", src = 'core', level = 0, from = caller)
return { "result" => "failure" }
end
end
def unload(token,name)
authenticate(token)
@framework.plugins.each { |plugin|
# Unload the plugin if it matches the name we're searching for
if (plugin.name == name)
@framework.plugins.unload(plugin)
return { "result" => "success" }
end
}
return { "result" => "failure" }
end
def loaded(token)
authenticate(token)
ret = {}
ret[:plugins] = []
@framework.plugins.each do |plugin|
ret[:plugins] << plugin.name
end
ret
end
end
end
end
-210
View File
@@ -1,210 +0,0 @@
require "xmlrpc/server"
require 'rex/service_manager'
require "rex"
module Msf
module RPC
module MonkeyPatcher
def initialize(*args)
# Enable Bigint processing (required for big file sizes,etc)
if XMLRPC::Config.const_defined?(:ENABLE_BIGINT)
XMLRPC::Config.send(:remove_const, :ENABLE_BIGINT)
XMLRPC::Config.const_set(:ENABLE_BIGINT, true)
end
# Enable nils in requests
if XMLRPC::Config.const_defined?(:ENABLE_NIL_CREATE)
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_CREATE)
XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
end
# Enable nils in replies
if XMLRPC::Config.const_defined?(:ENABLE_NIL_PARSER)
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_PARSER)
XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)
end
super(*args)
end
end
class Service < ::XMLRPC::BasicServer
include MonkeyPatcher
attr_accessor :service, :state, :on_input, :on_output, :on_error
attr_accessor :dispatcher_timeout
def initialize(srvhost, srvport, ssl=false, cert=nil, ckey=nil)
self.dispatcher_timeout = 0
self.service = Rex::Socket::TcpServer.create(
'LocalHost' => srvhost,
'LocalPort' => srvport,
'SSL' => ssl
)
self.service.on_client_connect_proc = Proc.new { |client|
on_client_connect(client)
}
self.service.on_client_data_proc = Proc.new { |client|
begin
Timeout.timeout(self.dispatcher_timeout) do
on_client_data(client)
end
rescue ::EOFError => e
raise e
rescue ::Exception => e
wlog("XMLRPC Server Error: #{client.inspect} #{e.class} #{e} #{e.backtrace}")
raise e
end
}
self.service.on_client_close_proc = Proc.new { |client|
on_client_close(client)
}
self.state = {}
super()
end
def start
self.state = {}
self.service.start
end
def stop
self.state = {}
self.service.stop
self.service.close
end
def wait
self.service.wait
end
def on_client_close(c)
self.state.delete(c)
end
def on_client_connect(c)
self.state[c] = ""
self.clean_state_table
end
def on_client_data(c)
data = c.get_once(-1)
if(not data)
c.close
return
end
if not self.state[c]
c.close
return
end
self.state[c] << data
procxml(c)
end
def clean_state_table
self.state.keys.each do |s|
self.state.delete(s) if s.closed?
end
end
def procxml(c)
while(self.state[c].index("\x00"))
mesg,left = self.state[c].split("\x00", 2)
self.state[c] = left
begin
self.on_input.call(mesg) if self.on_input
res = process(mesg)
self.on_output.call(res) if self.on_output
c.put(res+"\x00")
rescue ::Interrupt
raise $!
rescue ::Exception => e
self.on_error.call(e) if self.on_error
end
end
end
end
class WebService < ::XMLRPC::BasicServer
include MonkeyPatcher
attr_accessor :service, :state, :srvhost, :srvport, :uri
def initialize(port, host, uri = "/RPC2")
self.srvhost = host
self.srvport = port
self.uri = uri
self.service = nil
super()
end
def start
self.state = {}
self.service = Rex::ServiceManager.start(
Rex::Proto::Http::Server,
self.srvport,
self.srvhost,
{}
)
uopts = {
'Proc' => Proc.new { |cli, req|
on_request_uri(cli, req)
},
'Path' => self.uri
}
self.service.add_resource(self.uri,uopts)
end
def stop
self.state = {}
self.service.stop
end
def wait
self.service.wait
end
def on_client_close(c)
self.state.delete(c)
end
def on_client_connect(c)
self.state[c] = ""
end
def on_request_uri(cli, req)
begin
res = Rex::Proto::Http::Response.new()
res["Content-Type"] = "text/xml"
res.body = process(req.body)
rescue XMLRPC::FaultException => e
res = Rex::Proto::Http::Response.new(e.faultCode,e.faultString)
rescue
res = Rex::Proto::Http::Response.new(404,"An Error Occured")
end
cli.send_response(res)
end
end
end
end
-242
View File
@@ -1,242 +0,0 @@
require 'rex'
require 'rex/ui/text/output/buffer'
module Msf
module RPC
class Session < Base
def list(token)
authenticate(token)
res = {}
@framework.sessions.each do |sess|
i,s = sess
res[s.sid] = {
'type' => s.type.to_s,
'tunnel_local'=> s.tunnel_local.to_s,
'tunnel_peer' => s.tunnel_peer.to_s,
'via_exploit' => s.via_exploit.to_s,
'via_payload' => s.via_payload.to_s,
'desc' => s.desc.to_s,
'info' => s.info.to_s,
'workspace' => s.workspace.to_s,
'target_host' => s.target_host.to_s,
'username' => s.username.to_s,
'uuid' => s.uuid.to_s,
'exploit_uuid' => s.exploit_uuid.to_s,
'routes' => s.routes.join(",")
}
if(s.type.to_s == "meterpreter")
res[s.sid]['platform'] = s.platform.to_s
end
end
res
end
def stop(token, sid)
authenticate(token)
s = @framework.sessions[sid.to_i]
if(not s)
raise ::XMLRPC::FaultException.new(404, "unknown session while stopping")
end
s.kill
{ "result" => "success" }
end
# Shell read is now a positon-aware reader of the shell's associated
# ring buffer. For more direct control of the pointer into a ring
# buffer, a client can instead use ring_read, and note the returned
# sequence number on their own (making multiple views into the same
# session possible, regardless of position in the stream)
def shell_read(token, sid, ptr=nil)
_valid_session(token,sid,"shell")
# @session_sequence tracks the pointer into the ring buffer
# data of sessions (by sid) in order to emulate the old behavior
# of shell_read
@session_sequence ||= {}
@session_sequence[sid] ||= 0
ring_buffer = ring_read(token,sid,(ptr || @session_sequence[sid]))
if not (ring_buffer["seq"].nil? || ring_buffer["seq"].empty?)
@session_sequence[sid] = ring_buffer["seq"].to_i
end
return ring_buffer
end
# shell_write is pretty much totally identical to ring_put
def shell_write(token, sid, data)
_valid_session(token,sid,"shell")
ring_put(token,sid,data)
end
def shell_upgrade(token, sid, lhost, lport)
s = _valid_session(token,sid,"shell")
s.exploit_datastore['LHOST'] = lhost
s.exploit_datastore['LPORT'] = lport
s.execute_script('spawn_meterpreter', nil)
{ "result" => "success" }
end
def meterpreter_read(token, sid)
s = _valid_session(token,sid,"meterpreter")
if not s.user_output.respond_to? :dump_buffer
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
end
data = s.user_output.dump_buffer
{ "data" => Rex::Text.encode_base64(data), "encoding" => "base64" }
end
def ring_read(token, sid, ptr=nil)
authenticate(token)
s = _valid_session(token,sid,"ring")
begin
res = s.ring.read_data(ptr)
{ "seq" => res[0].to_s, "data" =>(Rex::Text.encode_base64(res[1].to_s)), "encoding" => "base64"}
rescue ::Exception => e
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
end
end
def ring_put(token, sid, data)
authenticate(token)
s = _valid_session(token,sid,"ring")
buff = Rex::Text.decode_base64(data)
begin
res = s.shell_write(buff)
{ "write_count" => res.to_s}
rescue ::Exception => e
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
end
end
def ring_last(token, sid)
authenticate(token)
s = _valid_session(token,sid,"ring")
{ "seq" => s.ring.last_sequence.to_s }
end
def ring_clear(token, sid)
authenticate(token)
s = _valid_session(token,sid,"ring")
res = s.ring.clear_data
if res.compact.empty?
{ "result" => "success"}
else # Doesn't seem like this can fail. Maybe a race?
{ "result" => "failure"}
end
end
#
# Run a single meterpreter console command
#
def meterpreter_write(token, sid, data)
s = _valid_session(token,sid,"meterpreter")
if not s.user_output.respond_to? :dump_buffer
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
end
buff = Rex::Text.decode_base64(data)
interacting = false
s.channels.each_value do |ch|
interacting ||= ch.respond_to?('interacting') && ch.interacting
end
if interacting
s.user_input.put(buff+"\n")
else
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(buff) }
end
{}
end
def meterpreter_session_detach(token,sid)
s = _valid_session(token,sid,"meterpreter")
s.channels.each_value do |ch|
if(ch.respond_to?('interacting') && ch.interacting)
ch.detach()
return { "result" => "success" }
end
end
{ "result" => "failure" }
end
def meterpreter_session_kill(token,sid)
s = _valid_session(token,sid,"meterpreter")
s.channels.each_value do |ch|
if(ch.respond_to?('interacting') && ch.interacting)
ch._close
return { "result" => "success" }
end
end
{ "result" => "failure" }
end
def meterpreter_tabs(token,sid, line)
s = _valid_session(token,sid,"meterpreter")
{ "tabs" => s.console.tab_complete(line) }
end
# runs a meterpreter command even if interacting with a shell or other channel
def meterpreter_run_single(token, sid, data)
s = _valid_session(token,sid,"meterpreter")
if not s.user_output.respond_to? :dump_buffer
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
end
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) }
{}
end
def meterpreter_script(token, sid, data)
meterpreter_run_single(token, sid, "run #{data}")
end
def compatible_modules(token, sid)
authenticate(token)
ret = []
mtype = "post"
names = @framework.post.keys.map{ |x| "post/#{x}" }
names.each do |mname|
m = _find_module(mtype, mname)
next if not m.session_compatible?(sid)
ret << m.fullname
end
ret
end
private
def _find_module(mtype,mname)
mod = @framework.modules.create(mname)
if(not mod)
raise ::XMLRPC::FaultException.new(404, "unknown module")
end
mod
end
def _valid_session(token,sid,type)
authenticate(token)
s = @framework.sessions[sid.to_i]
if(not s)
raise ::XMLRPC::FaultException.new(404, "unknown session while validating")
end
if type == "ring"
if not s.respond_to?(:ring)
raise ::XMLRPC::FaultException.new(403, "session #{s.type} does not support ring operations")
end
elsif(s.type != type)
raise ::XMLRPC::FaultException.new(403, "session is not "+type)
end
s
end
end
end
end
+9 -11
View File
@@ -100,7 +100,6 @@ public
host = {}
host[:created_at] = h.created_at.to_i
host[:address] = h.address.to_s
host[:address6] = h.address6.to_s
host[:mac] = h.mac.to_s
host[:name] = h.name.to_s
host[:state] = h.state.to_s
@@ -135,7 +134,7 @@ public
:limit => limit, :offset => offset).each do |s|
service = {}
host = s.host
service[:host] = host.address || host.address6 || "unknown"
service[:host] = host.address || "unknown"
service[:created_at] = s[:created_at].to_i
service[:updated_at] = s[:updated_at].to_i
service[:port] = s[:port]
@@ -172,7 +171,7 @@ public
vuln[:proto] = nil
end
vuln[:time] = v.created_at.to_i
vuln[:host] = v.host.address || v.host.address6 || nil
vuln[:host] = v.host.address || nil
vuln[:name] = v.name
vuln[:refs] = reflist.join(',')
ret[:vulns] << vuln
@@ -261,7 +260,6 @@ public
host = {}
host[:created_at] = h.created_at.to_i
host[:address] = h.address.to_s
host[:address6] = h.address6.to_s
host[:mac] = h.mac.to_s
host[:name] = h.name.to_s
host[:state] = h.state.to_s
@@ -324,7 +322,7 @@ public
services.each do |s|
service = {}
host = s.host
service[:host] = host.address || host.address6 || "unknown"
service[:host] = host.address || "unknown"
service[:created_at] = s[:created_at].to_i
service[:updated_at] = s[:updated_at].to_i
service[:port] = s[:port]
@@ -371,7 +369,7 @@ public
notes.each do |n|
note = {}
host = n.host
note[:host] = host.address || host.address6 || "unknown"
note[:host] = host.address || "unknown"
if n.service
note[:port] = n.service.port
note[:proto] = n.service.proto
@@ -449,7 +447,7 @@ public
note[:time] = n.created_at.to_i
note[:host] = ""
note[:service] = ""
note[:host] = n.host.address || n.host.address6 if(n.host)
note[:host] = n.host.address if(n.host)
note[:service] = n.service.name || n.service.port if(n.service)
note[:type ] = n.ntype.to_s
note[:data] = n.data.inspect
@@ -718,7 +716,7 @@ public
wspace.events.all(:limit => limit, :offset => offset).each do |e|
event = {}
event[:host] = e.host.address || e.host.address6 if(e.host)
event[:host] = e.host.address if(e.host)
event[:created_at] = e.created_at.to_i
event[:updated_at] = e.updated_at.to_i
event[:name] = e.name
@@ -757,7 +755,7 @@ public
ret[:loots] = []
wspace.loots.all(:limit => limit, :offset => offset).each do |l|
loot = {}
loot[:host] = l.host.address || l.host.address6 if(l.host)
loot[:host] = l.host.address if(l.host)
loot[:service] = l.service.name || n.service.port if(n.service)
loot[:ltype] = l.ltype
loot[:ctype] = l.ctype
@@ -790,7 +788,7 @@ public
DBManager::Cred.find(:all, :include => {:service => :host}, :conditions => ["hosts.workspace_id = ?",
framework.db.workspace.id ], :limit => limit, :offset => offset).each do |c|
cred = {}
cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host)
cred[:host] = c.service.host.address if(c.service.host)
cred[:updated_at] = c.updated_at.to_i
cred[:port] = c.service.port
cred[:proto] = c.service.proto
@@ -840,7 +838,7 @@ public
vulns.each do |v|
vuln= {}
host= v.host
vuln[:host] = host.address || host.address6 || "unknown"
vuln[:host] = host.address || "unknown"
if v.service
vuln[:port] = v.service.port
vuln[:proto] = v.service.proto
+31 -9
View File
@@ -169,7 +169,7 @@ module Socket
#
def self.getaddress(addr, accept_ipv6 = true)
begin
if dotted_ip?(addr)
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
return addr
end
@@ -205,12 +205,12 @@ module Socket
#
def self.getaddresses(addr, accept_ipv6 = true)
begin
if dotted_ip?(addr)
return addr
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
return [addr]
end
res = ::Socket.gethostbyname(addr)
return nil if not res
return [] if not res
# Shift the first three elements out
rname = res.shift
@@ -223,12 +223,12 @@ module Socket
end
# Make sure we have at least one name
return nil if res.length == 0
return [] if res.length == 0
# Return an array of all addresses
res.map{ |addr| self.addr_ntoa(addr) }
rescue ::ArgumentError # Win32 bug
nil
[]
end
end
@@ -357,10 +357,10 @@ module Socket
# IPv4
if (addr < 0x100000000 and not v6)
nboa.unpack('C4').join('.')
addr_ntoa(nboa)
# IPv6
else
nboa.unpack('n8').map{ |c| "%.4x" % c }.join(":")
addr_ntoa(nboa)
end
end
@@ -383,11 +383,32 @@ module Socket
# IPv6
if (addr.length == 16)
return addr.unpack('n8').map{ |c| "%.4x" % c }.join(":")
return compress_address(addr.unpack('n8').map{ |c| "%x" % c }.join(":"))
end
raise RuntimeError, "Invalid address format"
end
#
# Implement zero compression for IPv6 addresses.
# Uses the compression method from Marco Ceresa's IPAddress GEM
# https://github.com/bluemonk/ipaddress/blob/master/lib/ipaddress/ipv6.rb
#
def self.compress_address(addr)
return addr unless is_ipv6?(addr)
addr = addr.dup
while true
break if addr.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
break if addr.sub!(/\b0:0:0:0:0:0:0\b/, ':')
break if addr.sub!(/\b0:0:0:0:0:0\b/, ':')
break if addr.sub!(/\b0:0:0:0:0\b/, ':')
break if addr.sub!(/\b0:0:0:0\b/, ':')
break if addr.sub!(/\b0:0:0\b/, ':')
break if addr.sub!(/\b0:0\b/, ':')
break
end
addr.sub(/:{3,}/, '::')
end
#
# Converts a network byte order address to an integer
@@ -655,6 +676,7 @@ module Socket
return [lsock, rsock]
end
##
#
+6 -3
View File
@@ -73,16 +73,19 @@ class RangeWalker
else
return false
end
elsif arg.include?(":")
# Then it's IPv6
# Can't really do much with IPv6 right now, just return it and
# hope for the best
# IPv6 ranges are not yet supported (or useful)
return false unless Rex::Socket.is_ipv6?(arg)
addr = Rex::Socket.addr_atoi(arg)
ranges.push [addr, addr, true]
elsif arg =~ /[^-0-9,.*]/
# Then it's a domain name and we should send it on to addr_atoi
# unmolested to force a DNS lookup.
Rex::Socket.addr_atoi_list(arg).each { |addr| ranges.push [addr, addr] }
elsif arg =~ /^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})-([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/
# Then it's in the format of 1.2.3.4-5.6.7.8
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
@@ -48,6 +48,13 @@ class Metasploit3 < Msf::Auxiliary
OptBool.new('EXTRALINE', [ true, "Add extra CRLF's in response to LIST",true])
], self.class)
end
# Not compatible today
def support_ipv6?
false
end
#---------------------------------------------------------------------------------
def setup
@@ -40,7 +40,11 @@ class Metasploit3 < Msf::Auxiliary
], self.class)
end
# Not compatible today
def support_ipv6?
false
end
def resolve(ip)
results = ''
apikey = datastore['apikey']
@@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('FILTER','PCAPFILE')
end
# No IPv6 support yet
def support_ipv6?
false
end
def run_batch_size
datastore['BATCHSIZE'] || 256
end
@@ -41,6 +41,11 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('RHOST', 'RPORT')
end
# No IPv6 support yet
def support_ipv6?
false
end
def run_host(ip)
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
@@ -37,6 +37,11 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('FILTER','PCAPFILE')
end
# No IPv6 support yet
def support_ipv6?
false
end
def run_batch_size
datastore['BATCHSIZE'] || 256
@@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
deregister_options('FILTER','PCAPFILE')
end
# No IPv6 support yet
def support_ipv6?
false
end
def run_batch_size
datastore['BATCHSIZE'] || 256
end
+5
View File
@@ -61,6 +61,11 @@ class Metasploit3 < Msf::Auxiliary
], self.class)
end
# Not compatible today
def support_ipv6?
false
end
def run
@formsdir = datastore['FORMSDIR']
@template = datastore['TEMPLATE']
+2 -8
View File
@@ -37,7 +37,7 @@ opts = {
'User' => 'msf',
'SSL' => true,
'ServerPort' => 55553,
'Type' => 'Xml'
'Type' => 'Msg'
}
# Parse command line arguments.
@@ -53,8 +53,6 @@ arguments.parse(ARGV) { |opt, idx, val|
opts['User'] = val
when '-P'
opts['Pass'] = val
when '-t'
opts['Type'] = (val =~ /xml/i) ? 'XML' : 'Msg'
when "-h"
print("\nUsage: #{File.basename(__FILE__)} <options>\n" + arguments.usage)
exit
@@ -76,11 +74,7 @@ end
$0 = "msfrpc"
if opts['Type'] == 'Msg'
require 'msf/core/rpc/v10/client'
else
require 'msf/core/rpc/client'
end
require 'msf/core/rpc/v10/client'
require 'rex/ui'
rpc = Msf::RPC::Client.new(
+2 -6
View File
@@ -28,7 +28,6 @@ arguments = Rex::Parser::Arguments.new(
"-p" => [ true, "Bind to this port instead of 55553" ],
"-U" => [ true, "Specify the username to access msfrpcd" ],
"-P" => [ true, "Specify the password to access msfrpcd" ],
"-t" => [ true, "Server type, [Basic|Web|Msg]" ],
"-u" => [ true, "URI for Web server" ],
"-S" => [ false, "Disable SSL on the RPC socket" ],
"-f" => [ false, "Run the daemon in the foreground" ],
@@ -40,7 +39,7 @@ opts = {
'SSL' => true,
'ServerHost' => '0.0.0.0',
'ServerPort' => 55553,
'ServerType' => 'Basic'
'ServerType' => 'Msg'
}
foreground = false
@@ -62,8 +61,6 @@ arguments.parse(ARGV) { |opt, idx, val|
opts['Pass'] = val
when "-f"
foreground = true
when "-t"
opts['ServerType'] = val
when "-u"
opts['URI'] = val
when "-n"
@@ -81,8 +78,7 @@ end
$0 = "msfrpcd"
rpctype = 'XML'
rpctype = 'MSG' if opts['ServerType'].downcase == 'msg'
rpctype = 'MSG'
$stderr.puts "[*] #{rpctype}RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"}):#{opts['ServerType']}..."
-188
View File
@@ -1,188 +0,0 @@
#!/usr/bin/env ruby
#
# $Id$
#
# This plugin provides an msf daemon interface that spawns a listener on a
# defined port (default 55553) and gives each connecting client its own
# console interface. These consoles all share the same framework instance.
# Be aware that the console instance that spawns on the port is entirely
# unauthenticated, so realize that you have been warned.
#
# $Revision$
#
require "msf/core/rpc"
require "fileutils"
module Msf
###
#
# This class implements the msfd plugin interface.
#
###
class Plugin::XMLRPC < Msf::Plugin
#
# The default local hostname that the server listens on.
#
DefaultHost = "127.0.0.1"
#
# The default local port that the server listens on.
#
DefaultPort = 55553
#
# ServerPort
#
# The local port to listen on for connections. The default is 55553
#
def initialize(framework, opts)
super
host = opts['ServerHost'] || DefaultHost
port = opts['ServerPort'] || DefaultPort
ssl = (opts['SSL'] and opts['SSL'].to_s =~ /^[ty]/i) ? true : false
cert = opts['SSLCert']
ckey = opts['SSLKey']
user = opts['User'] || "msf"
pass = opts['Pass'] || ::Rex::Text.rand_text_alphanumeric(8)
type = opts['ServerType'] || "Basic"
uri = opts['URI'] || "/RPC2"
print_status("XMLRPC Service: #{host}:#{port} #{ssl ? " (SSL)" : ""}")
print_status("XMLRPC Username: #{user}")
print_status("XMLRPC Password: #{pass}")
print_status("XMLRPC Server Type: #{type}")
@users = [ [user,pass] ]
if(type =~ /Web/i)
print_status("XMLRPC Web URI: #{uri}")
self.server = ::Msf::RPC::WebService.new(port,host,uri)
elsif(type =~ /Basic/i)
self.server = ::Msf::RPC::Service.new(host,port,ssl,cert,ckey)
else
print_status("Invalid server type #{type}, please choose Web or Basic")
end
# If the run in foreground flag is not specified, then go ahead and fire
# it off in a worker thread.
if (opts['RunInForeground'] != true)
# Store a handle to the thread so we can kill it during
# cleanup when we get unloaded.
self.thread = Thread.new {
run
}
end
end
#
# Returns 'xmlrpc'
#
def name
"xmlrpc"
end
#
# Returns the plugin description.
#
def desc
"Provides a XMLRPC interface over a listening TCP port."
end
#
# The meat of the plugin, sets up handlers for requests
#
def run
# Initialize the list of authenticated sessions
@tokens = {}
args = [framework,@tokens,@users]
# Add handlers for every class
self.server.add_handler(::XMLRPC::iPIMethods("auth"),
::Msf::RPC::Auth.new(*args)
)
# Note the extra argument for core as compared to the other
# handlers. This allows rpc clients access to the plugin so
# they can shutdown the server.
core_args = args + [self]
self.server.add_handler(::XMLRPC::iPIMethods("core"),
::Msf::RPC::Core.new(*core_args)
)
self.server.add_handler(::XMLRPC::iPIMethods("session"),
::Msf::RPC::Session.new(*args)
)
self.server.add_handler(::XMLRPC::iPIMethods("job"),
::Msf::RPC::Job.new(*args)
)
self.server.add_handler(::XMLRPC::iPIMethods("module"),
::Msf::RPC::Module.new(*args)
)
self.server.add_handler(::XMLRPC::iPIMethods("console"),
::Msf::RPC::Console.new(*args)
)
self.server.add_handler(::XMLRPC::iPIMethods("db"),
::Msf::RPC::Db.new(*args)
)
self.server.add_handler(::XMLRPC::iPIMethods("plugin"),
::Msf::RPC::Plugin.new(*args)
)
# Set the default/catch-all handler
self.server.set_default_handler do |name, *args|
raise ::XMLRPC::FaultException.new(-99, "Method #{name} missing or wrong number of parameters!")
end
# Start the actual service
self.server.start
# Wait for the service to complete
self.server.wait
end
#
# Closes the listener service.
#
def cleanup
self.server.stop if self.server
self.thread.kill if self.thread
self.server = nil
super
end
def stop_rpc
print_line
print_status("XMLRPC Client requested server stop")
# Plugins aren't really meant to be able to unload themselves, so this
# is a bit of a corner case. Unloading ourselves ends up killing the
# thread that's doing the unloading so we need to fire off the unload
# in a seperate one.
Thread.new {
framework.plugins.unload(self)
}
nil
end
#
# The XMLRPC instance.
#
attr_accessor :server
attr_accessor :thread
attr_accessor :users
attr_accessor :tokens
end
end