Merge pull request #77 from rapid7/lab_temp2

squashed lab upload commit
unstable
Jonathan Cran 2011-12-22 13:00:26 -08:00
commit 5cec44bc43
11 changed files with 187 additions and 100 deletions

View File

@ -134,11 +134,11 @@ class FogDriver < VmDriver
end end
end end
def copy_from(from, to) def copy_from_guest(from, to)
raise "unimplemented" raise "unimplemented"
end end
def copy_to(from, to) def copy_to_guest(from, to)
raise "unimplemented" raise "unimplemented"
end end

View File

@ -102,7 +102,7 @@ class RemoteEsxDriver < VmDriver
raise "Not Implemented" raise "Not Implemented"
end end
def copy_from(from, to) def copy_from_guest(from, to)
if @os == "linux" if @os == "linux"
scp_from(from, to) scp_from(from, to)
else else
@ -110,7 +110,7 @@ class RemoteEsxDriver < VmDriver
end end
end end
def copy_to(from, to) def copy_to_guest(from, to)
if @os == "linux" if @os == "linux"
scp_to(from, to) scp_to(from, to)
else else

View File

@ -116,7 +116,7 @@ class RemoteWorkstationDriver < VmDriver
end end
end end
def copy_from(from, to) def copy_from_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
@ -133,7 +133,7 @@ class RemoteWorkstationDriver < VmDriver
end end
end end
def copy_to(from, to) def copy_to_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
@ -165,9 +165,8 @@ class RemoteWorkstationDriver < VmDriver
directory = filter_input(directory) directory = filter_input(directory)
if @tools if @tools
emote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " + remote_system_command("ssh #{@user}@#{@host} vmrun -T ws -gu #{@vm_user} -gp #{@vm_pass} " +
"createDirectoryInGuest \'#{@location}\' \'#{directory}\' nogui") "createDirectoryInGuest \'#{@location}\' \'#{directory}\' nogui")
system_command(vmrunstr)
else else
raise "Not Implemented - Install VmWare Tools" raise "Not Implemented - Install VmWare Tools"
end end
@ -178,8 +177,11 @@ class RemoteWorkstationDriver < VmDriver
end end
def running? def running?
## Get running VMs
running = `ssh #{@user}@#{@host} \"vmrun list nogui\"` # Get running VMs
running = remote_system_command("vmrun list nogui")
if running
running_array = running.split("\n") running_array = running.split("\n")
running_array.shift running_array.shift
@ -188,6 +190,7 @@ class RemoteWorkstationDriver < VmDriver
return true return true
end end
end end
end
false false
end end

View File

@ -98,14 +98,14 @@ module Drivers
system_command(command) system_command(command)
end end
def copy_from(from, to) def copy_from_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
raise "Not supported by Virtual Box" raise "Not supported by Virtual Box"
end end
def copy_to(from, to) def copy_to_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)

View File

@ -24,6 +24,7 @@ class VmDriver
@location = filter_command(config["location"]) @location = filter_command(config["location"])
@credentials = config["credentials"] || [] @credentials = config["credentials"] || []
@tools = filter_input(config["tools"]) @tools = filter_input(config["tools"])
@os = filter_input(config["os"]) @os = filter_input(config["os"])
@hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s) @hostname = filter_input(config["hostname"]) || filter_input(config["vmid"].to_s)
@ -86,11 +87,11 @@ class VmDriver
raise "Command not Implemented" raise "Command not Implemented"
end end
def copy_from(from, to) def copy_from_guest(from, to)
raise "Command not Implemented" raise "Command not Implemented"
end end
def copy_to(from, to) def copy_to_guest(from, to)
raise "Command not Implemented" raise "Command not Implemented"
end end
@ -142,7 +143,7 @@ private
def filter_input(string) def filter_input(string)
return "" unless string # nil becomes empty string return "" unless string # nil becomes empty string
return unless string.class == String # Allow other types unmodified return string unless string.class == String # Allow other types unmodified
unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string unless /^[\d\w\s\[\]\{\}\/\\\.\-\"\(\):!]*$/.match string
raise "WARNING! Invalid character in: #{string}" raise "WARNING! Invalid character in: #{string}"
@ -166,8 +167,7 @@ private
# the ability to still run clean (controlled entirely by us) # the ability to still run clean (controlled entirely by us)
# command lines. # command lines.
def system_command(command) def system_command(command)
#puts "DEBUG: system command #{command}" `#{command}`
system(command)
end end

View File

@ -107,7 +107,6 @@ class WorkstationDriver < VmDriver
# Ghettohack! # Ghettohack!
string = File.open(output_file,"r").read string = File.open(output_file,"r").read
`rm #{output_file}` `rm #{output_file}`
else else
raise "zomgwtfbbqnotools" raise "zomgwtfbbqnotools"
end end
@ -115,7 +114,7 @@ class WorkstationDriver < VmDriver
return string return string
end end
def copy_from(from, to) def copy_from_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
if @tools if @tools
@ -127,7 +126,8 @@ class WorkstationDriver < VmDriver
system_command(vmrunstr) system_command(vmrunstr)
end end
def copy_to(from, to) def copy_to_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
if @tools if @tools

View File

@ -91,13 +91,13 @@ class WorkstationVixrDriver < VmDriver
end end
end end
def copy_from(from, to) def copy_from_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
cp_from_host(from,to) cp_from_host(from,to)
end end
def copy_to(from, to) def copy_to_guest(from, to)
from = filter_input(from) from = filter_input(from)
to = filter_input(to) to = filter_input(to)
vm.cp_to_guest(from,to) vm.cp_to_guest(from,to)

View File

@ -1,19 +1,15 @@
$:.unshift(File.join(File.dirname(__FILE__), '..', '..')) $:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
module Lab
module Modifier
module Meterpreter
end
end
end
# This allows us to override the default way of running commands # This allows us to override the default way of running commands
# Currently useful for the esx controller # Currently useful for the esx controller
module Lab module Lab
class Vm module Modifier
module Meterpreter
attr_accessor :framework attr_accessor :framework
attr_accessor :session attr_accessor :session
@ -165,3 +161,5 @@ class Vm
end end
end end
end

View File

@ -18,6 +18,8 @@ class Vm
attr_accessor :host attr_accessor :host
attr_accessor :os attr_accessor :os
attr_accessor :arch attr_accessor :arch
attr_accessor :tags
attr_accessor :type
## Initialize takes a vm configuration hash of the form ## Initialize takes a vm configuration hash of the form
## - vmid (unique identifier) ## - vmid (unique identifier)
@ -75,8 +77,6 @@ class Vm
#Only fog systems need this #Only fog systems need this
@fog_config = config['fog_config'] @fog_config = config['fog_config']
#puts "Passing driver config: #{config}"
# Process the correct driver # Process the correct driver
if @driver_type == "workstation" if @driver_type == "workstation"
@driver = Lab::Drivers::WorkstationDriver.new(config) @driver = Lab::Drivers::WorkstationDriver.new(config)
@ -101,8 +101,6 @@ class Vm
# Load in a list of modifiers. These provide additional methods # Load in a list of modifiers. These provide additional methods
# Currently it is up to the user to verify that # Currently it is up to the user to verify that
# modifiers are properly used with the correct VM image. # modifiers are properly used with the correct VM image.
#
# If not, the results are likely to be disasterous.
@modifiers = config['modifiers'] @modifiers = config['modifiers']
if @modifiers if @modifiers
@ -112,6 +110,14 @@ class Vm
# modifier likely didn't exist # modifier likely didn't exist
end end
end end
# Consume all tags
@tags = config['tags']
end
def tagged?(tag_name)
return false unless @tags
return true if @tags.include?(tag_name)
end end
def running? def running?
@ -163,12 +169,12 @@ class Vm
@driver.start @driver.start
end end
def copy_to(from,to) def copy_to_guest(from,to)
@driver.copy_to(from,to) @driver.copy_to_guest(from,to)
end end
def copy_from(from,to) def copy_from_guest(from,to)
@driver.copy_from(from,to) @driver.copy_from_guest(from,to)
end end
def run_command(command) def run_command(command)
@ -196,7 +202,7 @@ class Vm
end end
def to_s def to_s
return "#{@vmid}" return "#{@hostname}"
end end
def to_yaml def to_yaml

View File

@ -50,13 +50,13 @@ module Controllers
def [](x) def [](x)
# Support indexing by both names and number # Support indexing by both names and number
if x.class == String if x.class == String
find_by_vmid(x) find_by_hostname(x)
else else
return @vms[x] return @vms[x]
end end
end end
def find_by_vmid(vmid) def find_by_hostname(vmid)
@vms.each do |vm| @vms.each do |vm|
if (vm.hostname.to_s.downcase == vmid.to_s.downcase) if (vm.hostname.to_s.downcase == vmid.to_s.downcase)
return vm return vm
@ -65,6 +65,12 @@ module Controllers
return nil return nil
end end
def find_by_tag(tag_name)
tagged_vms = []
@vms.each { |vm| tagged_vms << vm if vm.tagged?(tag_name) }
return tagged_vms
end
def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil) def add_vm(vmid, location=nil, os=nil, tools=nil, credentials=nil, user=nil, host=nil)
@vms << Vm.new( { 'vmid' => vmid, @vms << Vm.new( { 'vmid' => vmid,
'driver' => type, 'driver' => type,
@ -75,7 +81,7 @@ module Controllers
end end
def remove_by_vmid(vmid) def remove_by_vmid(vmid)
@vms.delete(self.find_by_vmid(vmid)) @vms.delete(self.find_by_hostname(vmid))
end end
def from_file(file) def from_file(file)
@ -108,6 +114,14 @@ module Controllers
false false
end end
def includes_hostname?(hostname)
@vms.each do |vm|
return true if (vm.hostname == hostname)
end
false
end
def build_from_dir(driver_type, dir, clear=false) def build_from_dir(driver_type, dir, clear=false)
if clear if clear
@ -229,7 +243,7 @@ module Controllers
def running?(vmid) def running?(vmid)
if includes_vmid?(vmid) if includes_vmid?(vmid)
return self.find_by_vmid(vmid).running? return self.find_by_hostname(vmid).running?
end end
return false return false
end end

View File

@ -28,6 +28,9 @@ class Plugin::Lab < Msf::Plugin
{ {
"lab_help" => "lab_help <lab command> - Show that command's description.", "lab_help" => "lab_help <lab command> - Show that command's description.",
"lab_show" => "lab_show - show all vms in the lab.", "lab_show" => "lab_show - show all vms in the lab.",
"lab_search" => "lab_search - search local vms in the lab.",
"lab_search_tags" => "lab_search_tag - search local vms in the lab.",
#"lab_search_remote" => "lab_search_remote - search remote vms in the lab.",
"lab_show_running" => "lab_show_running - show running vms.", "lab_show_running" => "lab_show_running - show running vms.",
"lab_load" => "lab_load [file] - load a lab definition from disk.", "lab_load" => "lab_load [file] - load a lab definition from disk.",
"lab_save" => "lab_save [filename] - persist a lab definition in a file.", "lab_save" => "lab_save [filename] - persist a lab definition in a file.",
@ -41,6 +44,7 @@ class Plugin::Lab < Msf::Plugin
"lab_stop" => "lab_stop [vmid+|all] stop the specified vm.", "lab_stop" => "lab_stop [vmid+|all] stop the specified vm.",
"lab_revert" => "lab_revert [vmid+|all] [snapshot] revert the specified vm.", "lab_revert" => "lab_revert [vmid+|all] [snapshot] revert the specified vm.",
"lab_snapshot" => "lab_snapshot [vmid+|all] [snapshot] snapshot all targets for this exploit.", "lab_snapshot" => "lab_snapshot [vmid+|all] [snapshot] snapshot all targets for this exploit.",
"lab_upload" => "lab_upload [vmid] [local_path] [remote_path] upload a file.",
"lab_run_command" => "lab_run_command [vmid+|all] [command] run a command on all targets.", "lab_run_command" => "lab_run_command [vmid+|all] [command] run a command on all targets.",
"lab_browse_to" => "lab_browse_to [vmid+|all] [uri] use the default browser to browse to a uri." "lab_browse_to" => "lab_browse_to [vmid+|all] [uri] use the default browser to browse to a uri."
} }
@ -103,16 +107,15 @@ class Plugin::Lab < Msf::Plugin
## ##
## Commands for dealing with a currently-loaded lab ## Commands for dealing with a currently-loaded lab
## ##
def cmd_lab_show(*args) def cmd_lab_show(*args)
if args.empty? if args.empty?
hlp_print_lab hlp_print_lab
else else
args.each do |vmid| args.each do |name|
if @controller.includes_vmid? vmid if @controller.includes_hostname? name
print_line @controller[vmid].to_yaml print_line @controller[name].to_yaml
else else
print_error "Unknown vm '#{vmid}'" print_error "Unknown vm '#{name}'"
end end
end end
end end
@ -122,27 +125,57 @@ class Plugin::Lab < Msf::Plugin
hlp_print_lab_running hlp_print_lab_running
end end
def cmd_lab_search(*args)
if args.empty?
hlp_print_lab
else
args.each do |arg|
print_line "Searching for vms with hostname matching #{arg}"
@controller.each do |vm|
print_line "checking to see #{vm.hostname} matches #{arg}"
print_line "#{vm.hostname} matched #{arg}" if vm.hostname =~ Regexp.new(arg)
end
end
end
end
def cmd_lab_search_tags(*args)
if args.empty?
hlp_print_lab
else
args.each do |arg|
print_line "Searching for vms with tags matching #{arg}"
@controller.each do |vm|
print_line "checking to see #{vm.hostname} is tagged #{arg}"
print_line "#{vm.hostname} tagged #{arg}" if vm.tagged?(arg)
end
end
end
end
def cmd_lab_start(*args) def cmd_lab_start(*args)
return lab_usage if args.empty? return lab_usage if args.empty?
if args[0] == "all" if args[0] == "all"
@controller.each do |vm| @controller.each do |vm|
print_line "Starting lab vm #{vm.vmid}." print_line "Starting lab vm #{vm.hostname}."
if !vm.running? if !vm.running?
vm.start vm.start
else else
print_line "Lab vm #{vm.vmid} already running." print_line "Lab vm #{vm.hostname} already running."
end end
end end
else else
args.each do |arg| args.each do |arg|
if @controller.includes_vmid? arg if @controller.includes_hostname? arg
vm = @controller.find_by_vmid(arg) vm = @controller.find_by_hostname(arg)
if !vm.running? if !vm.running?
print_line "Starting lab vm #{vm.vmid}." print_line "Starting lab vm #{vm.hostname}."
vm.start vm.start
else else
print_line "Lab vm #{vm.vmid} already running." print_line "Lab vm #{vm.hostname} already running."
end end
end end
end end
@ -154,22 +187,22 @@ class Plugin::Lab < Msf::Plugin
if args[0] == "all" if args[0] == "all"
@controller.each do |vm| @controller.each do |vm|
print_line "Stopping lab vm #{vm.vmid}." print_line "Stopping lab vm #{vm.hostname}."
if vm.running? if vm.running?
vm.stop vm.stop
else else
print_line "Lab vm #{vm.vmid} not running." print_line "Lab vm #{vm.hostname} not running."
end end
end end
else else
args.each do |arg| args.each do |arg|
if @controller.includes_vmid? arg if @controller.includes_hostname? arg
vm = @controller.find_by_vmid(arg) vm = @controller.find_by_hostname(arg)
if vm.running? if vm.running?
print_line "Stopping lab vm #{vm.vmid}." print_line "Stopping lab vm #{vm.hostname}."
vm.stop vm.stop
else else
print_line "Lab vm #{vm.vmid} not running." print_line "Lab vm #{vm.hostname} not running."
end end
end end
end end
@ -183,10 +216,10 @@ class Plugin::Lab < Msf::Plugin
@controller.each{ |vm| vm.suspend } @controller.each{ |vm| vm.suspend }
else else
args.each do |arg| args.each do |arg|
if @controller.includes_vmid? arg if @controller.includes_hostname? arg
if @controller.find_by_vmid(arg).running? if @controller.find_by_hostname(arg).running?
print_line "Suspending lab vm #{arg}." print_line "Suspending lab vm #{arg}."
@controller.find_by_vmid(arg).suspend @controller.find_by_hostname(arg).suspend
end end
end end
end end
@ -201,10 +234,10 @@ class Plugin::Lab < Msf::Plugin
@controller.each{ |vm| vm.reset } @controller.each{ |vm| vm.reset }
else else
args.each do |arg| args.each do |arg|
if @controller.includes_vmid? arg if @controller.includes_hostname? arg
if @controller.find_by_vmid(arg).running? if @controller.find_by_hostname(arg).running?
print_line "Resetting lab vm #{arg}." print_line "Resetting lab vm #{arg}."
@controller.find_by_vmid(arg).reset @controller.find_by_hostname(arg).reset
end end
end end
end end
@ -220,10 +253,10 @@ class Plugin::Lab < Msf::Plugin
print_line "Snapshotting all lab vms to snapshot: #{snapshot}." print_line "Snapshotting all lab vms to snapshot: #{snapshot}."
@controller.each{ |vm| vm.create_snapshot(snapshot) } @controller.each{ |vm| vm.create_snapshot(snapshot) }
else else
args[0..-2].each do |vmid_arg| args[0..-2].each do |name_arg|
next unless @controller.includes_vmid? vmid_arg next unless @controller.includes_hostname? name_arg
print_line "Snapshotting #{vmid_arg} to snapshot: #{snapshot}." print_line "Snapshotting #{name_arg} to snapshot: #{snapshot}."
@controller[vmid_arg].create_snapshot(snapshot) @controller[name_arg].create_snapshot(snapshot)
end end
end end
end end
@ -237,10 +270,10 @@ class Plugin::Lab < Msf::Plugin
print_line "Reverting all lab vms to snapshot: #{snapshot}." print_line "Reverting all lab vms to snapshot: #{snapshot}."
@controller.each{ |vm| vm.revert_snapshot(snapshot) } @controller.each{ |vm| vm.revert_snapshot(snapshot) }
else else
args[0..-2].each do |vmid_arg| args[0..-2].each do |name_arg|
next unless @controller.includes_vmid? vmid_arg next unless @controller.includes_hostname? name_arg
print_line "Reverting #{vmid_arg} to snapshot: #{snapshot}." print_line "Reverting #{name_arg} to snapshot: #{snapshot}."
@controller[vmid_arg].revert_snapshot(snapshot) @controller[name_arg].revert_snapshot(snapshot)
end end
end end
end end
@ -253,16 +286,48 @@ class Plugin::Lab < Msf::Plugin
print_line "Running command #{command} on all vms." print_line "Running command #{command} on all vms."
@controller.each do |vm| @controller.each do |vm|
if vm.running? if vm.running?
print_line "#{vm.vmid} running command: #{command}." print_line "#{vm.hostname} running command: #{command}."
vm.run_command(command) vm.run_command(command)
end end
end end
else
args[0..-2].each do |name_arg|
next unless @controller.includes_hostname? name_arg
if @controller[name_arg].running?
print_line "#{name_arg} running command: #{command}."
@controller[name_arg].run_command(command)
end
end
end
end
#
# Command: lab_upload [vmids] [from] [to]
#
# Description: Uploads a file to the guest(s)
#
# Quirks: Pass "all" as a vmid to have it operate on all vms.
#
def cmd_lab_upload(*args)
return lab_usage if args.empty?
return lab_usage if args.count < 3
local_path = args[args.count-2]
vm_path = args[args.count-1]
if args[0] == "all"
@controller.each do |vm|
if vm.running?
print_line "Copying from #{local_path} to #{vm_path} on #{vm.hostname}"
vm.copy_to_guest(local_path, vm_path)
end
end
else else
args[0..-2].each do |vmid_arg| args[0..-2].each do |vmid_arg|
next unless @controller.includes_vmid? vmid_arg next unless @controller.includes_vmid? vmid_arg
if @controller[vmid_arg].running? if @controller[vmid_arg].running?
print_line "#{vmid_arg} running command: #{command}." print_line "Copying from #{local_path} to #{vm_path} on #{vmid_arg}"
@controller[vmid_arg].run_command(command) @controller[vmid_arg].copy_to_guest(local_path, vm_path)
end end
end end
end end
@ -275,16 +340,16 @@ class Plugin::Lab < Msf::Plugin
print_line "Opening: #{uri} on all vms." print_line "Opening: #{uri} on all vms."
@controller.each do |vm| @controller.each do |vm|
if vm.running? if vm.running?
print_line "#{vm.vmid} opening to uri: #{uri}." print_line "#{vm.hostname} opening to uri: #{uri}."
vm.open_uri(uri) vm.open_uri(uri)
end end
end end
else else
args[0..-2].each do |vmid_arg| args[0..-2].each do |name_arg|
next unless @controller.includes_vmid? vmid_arg next unless @controller.includes_hostname? name_arg
if @controller[vmid_arg].running? if @controller[name_arg].running?
print_line "#{vmid_arg} opening to uri: #{uri}." print_line "#{name_arg} opening to uri: #{uri}."
@controller[vmid_arg].open_uri(uri) @controller[name_arg].open_uri(uri)
end end
end end
end end
@ -347,14 +412,13 @@ class Plugin::Lab < Msf::Plugin
tbl = Rex::Ui::Text::Table.new( tbl = Rex::Ui::Text::Table.new(
'Header' => 'Available Lab VMs', 'Header' => 'Available Lab VMs',
'Indent' => indent.length, 'Indent' => indent.length,
'Columns' => [ 'Vmid', 'Name', 'Location', "Power?" ] 'Columns' => [ 'Hostname', 'Driver', 'Type' ]
) )
@controller.each do |vm| @controller.each do |vm|
tbl << [ vm.vmid, tbl << [ vm.hostname,
vm.name, vm.driver.class,
vm.location, vm.type]
vm.running?]
end end
print_line tbl.to_s print_line tbl.to_s
@ -366,14 +430,14 @@ class Plugin::Lab < Msf::Plugin
tbl = Rex::Ui::Text::Table.new( tbl = Rex::Ui::Text::Table.new(
'Header' => 'Running Lab VMs', 'Header' => 'Running Lab VMs',
'Indent' => indent.length, 'Indent' => indent.length,
'Columns' => [ 'Vmid', 'Name', 'Location', 'Power?' ] 'Columns' => [ 'Hostname', 'Driver', 'Type', 'Power?' ]
) )
@controller.each do |vm| @controller.each do |vm|
if vm.running? if vm.running?
tbl << [ vm.vmid, tbl << [ vm.hostname,
vm.name, vm.driver.class,
vm.location, vm.type,
vm.running?] vm.running?]
end end
end end
@ -390,6 +454,8 @@ class Plugin::Lab < Msf::Plugin
# inheriting from Msf::Plugin to ensure that the framework attribute on # inheriting from Msf::Plugin to ensure that the framework attribute on
# their instance gets set. # their instance gets set.
# #
attr_accessor :controller
def initialize(framework, opts) def initialize(framework, opts)
super super