Merge branch '4.3-schema'

unstable
HD Moore 2011-12-05 15:04:35 -06:00
commit dbd00efefe
29 changed files with 146 additions and 2753 deletions

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

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

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/

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

View File

@ -602,6 +602,14 @@ class Module
(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.

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

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

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

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

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

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

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,12 +383,33 @@ 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
#
@ -656,6 +677,7 @@ module Socket
return [lsock, rsock]
end
##
#
# Class initialization

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

View File

@ -49,6 +49,13 @@ class Metasploit3 < Msf::Auxiliary
], self.class)
end
# Not compatible today
def support_ipv6?
false
end
#---------------------------------------------------------------------------------
def setup
super

View File

@ -40,6 +40,10 @@ class Metasploit3 < Msf::Auxiliary
], self.class)
end
# Not compatible today
def support_ipv6?
false
end
def resolve(ip)
results = ''

View File

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

View File

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

View File

@ -38,6 +38,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

View File

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

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']

8
msfrpc
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 'rex/ui'
rpc = Msf::RPC::Client.new(

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

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