bug/bundler_fix
jvazquez-r7 2013-04-03 19:17:53 +02:00
commit 358c43f6f6
65 changed files with 2208 additions and 492 deletions

View File

@ -27,11 +27,19 @@ group :development do
end
group :development, :test do
# supplies factories for producing model instance for specs
# Version 4.1.0 or newer is needed to support generate calls without the
# 'FactoryGirl.' in factory definitions syntax.
gem 'factory_girl', '>= 4.1.0'
# running documentation generation tasks and rspec tasks
gem 'rake'
end
group :test do
# Removes records from database created during tests. Can't use rspec-rails'
# transactional fixtures because multiple connections are in use so
# transactions won't work.
gem 'database_cleaner'
# testing framework
gem 'rspec', '>= 2.12'
# code coverage for tests

View File

@ -26,7 +26,10 @@ GEM
arel (3.0.2)
builder (3.0.4)
coderay (1.0.9)
database_cleaner (0.9.1)
diff-lcs (1.1.3)
factory_girl (4.2.0)
activesupport (>= 3.0.0)
i18n (0.6.1)
json (1.7.7)
method_source (0.8.1)
@ -64,6 +67,8 @@ PLATFORMS
DEPENDENCIES
activerecord
activesupport (>= 3.0.0)
database_cleaner
factory_girl (>= 4.1.0)
json
metasploit_data_models!
msgpack

View File

@ -0,0 +1,15 @@
require 'metasploit/framework'
module Metasploit
module Framework
module Database
def self.configurations
YAML.load_file(configurations_pathname)
end
def self.configurations_pathname
Metasploit::Framework.root.join('config', 'database.yml')
end
end
end
end

View File

@ -1,5 +1,4 @@
# -*- coding: binary -*-
###
#
# framework-base
# --------------
@ -13,8 +12,6 @@
# Beyond providing the default sessions, framework-base also provides
# a wrapper interface to framework-core that makes some of the tasks,
# such as exploitation, into easier to manage functions.
#
###
# framework-base depends on framework-core
require 'msf/core'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base'
require 'msf/base/sessions/scriptable'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/meterpreter'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'shellwords'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/meterpreter'

View File

@ -1,7 +1,4 @@
# -*- coding: binary -*-
##
# $Id: meterpreter_options.rb 10595 2010-10-08 04:11:47Z hdm $
##
require 'msf/base/sessions/meterpreter'
require 'msf/windows_error'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/meterpreter'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/meterpreter'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/meterpreter'
require 'msf/windows_error'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/base/sessions/command_shell_options'

View File

@ -1,9 +1,7 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'net/https'
require 'net/http'

View File

@ -1,9 +1,7 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'net/https'
require 'net/http'

View File

@ -1,9 +1,7 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'net/https'
require 'net/http'

View File

@ -1,9 +1,7 @@
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'net/https'
require 'net/http'

View File

@ -1,35 +1,61 @@
# -*- coding: binary -*-
#
# Standard Library
#
require 'csv'
require 'tmpdir'
require 'uri'
require 'zip'
#
#
# Included Libraries
#
#
#
# PacketFu
#
require 'packetfu'
#
# Rex
#
require 'rex/socket'
# Check Rex::Parser.nokogiri_loaded for status of the Nokogiri parsers
require 'rex/parser/nmap_nokogiri'
require 'rex/parser/nexpose_simple_nokogiri'
require 'rex/parser/nexpose_raw_nokogiri'
require 'rex/parser/foundstone_nokogiri'
require 'rex/parser/mbsa_nokogiri'
require 'rex/parser/acunetix_nokogiri'
require 'rex/parser/appscan_nokogiri'
require 'rex/parser/burp_session_nokogiri'
require 'rex/parser/ci_nokogiri'
require 'rex/parser/wapiti_nokogiri'
require 'rex/parser/openvas_nokogiri'
require 'rex/parser/foundstone_nokogiri'
require 'rex/parser/fusionvm_nokogiri'
require 'rex/parser/mbsa_nokogiri'
require 'rex/parser/nexpose_raw_nokogiri'
require 'rex/parser/nexpose_simple_nokogiri'
require 'rex/parser/nmap_nokogiri'
require 'rex/parser/openvas_nokogiri'
require 'rex/parser/wapiti_nokogiri'
# Legacy XML parsers -- these will be converted some day
require 'rex/parser/nmap_xml'
require 'rex/parser/nexpose_xml'
require 'rex/parser/retina_xml'
require 'rex/parser/netsparker_xml'
require 'rex/parser/nessus_xml'
require 'rex/parser/ip360_xml'
require 'rex/parser/ip360_aspl_xml'
require 'rex/parser/ip360_xml'
require 'rex/parser/nessus_xml'
require 'rex/parser/netsparker_xml'
require 'rex/parser/nexpose_xml'
require 'rex/parser/nmap_xml'
require 'rex/parser/retina_xml'
require 'rex/socket'
require 'zip'
require 'packetfu'
require 'uri'
require 'tmpdir'
require 'csv'
#
# Project
#
require 'msf/core/db_manager/import_msf_xml'
module Msf
@ -129,6 +155,7 @@ end
#
###
class DBManager
include Msf::DBManager::ImportMsfXml
def rfc3330_reserved(ip)
case ip.class.to_s
@ -3669,334 +3696,6 @@ class DBManager
end
# For each host, step through services, notes, and vulns, and import
# them.
# TODO: loot, tasks, and reports
def import_msf_xml(args={}, &block)
data = args[:data]
wspace = args[:wspace] || workspace
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
allow_yaml = false
btag = nil
doc = rexmlify(data)
if doc.elements["MetasploitExpressV1"]
m_ver = 1
allow_yaml = true
btag = "MetasploitExpressV1"
elsif doc.elements["MetasploitExpressV2"]
m_ver = 2
allow_yaml = true
btag = "MetasploitExpressV2"
elsif doc.elements["MetasploitExpressV3"]
m_ver = 3
btag = "MetasploitExpressV3"
elsif doc.elements["MetasploitExpressV4"]
m_ver = 4
btag = "MetasploitExpressV4"
elsif doc.elements["MetasploitV4"]
m_ver = 4
btag = "MetasploitV4"
else
m_ver = nil
end
unless m_ver and btag
raise DBImportError.new("Unsupported Metasploit XML document format")
end
doc.elements.each("/#{btag}/hosts/host") do |host|
host_data = {}
host_data[:workspace] = wspace
host_data[:host] = nils_for_nulls(host.elements["address"].text.to_s.strip)
if bl.include? host_data[:host]
next
else
yield(:address,host_data[:host]) if block
end
host_data[:mac] = nils_for_nulls(host.elements["mac"].text.to_s.strip)
if host.elements["comm"].text
host_data[:comm] = nils_for_nulls(host.elements["comm"].text.to_s.strip)
end
%W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum|
if host.elements[datum].text
host_data[datum.gsub('-','_')] = nils_for_nulls(host.elements[datum].text.to_s.strip)
end
}
host_address = host_data[:host].dup # Preserve after report_host() deletes
hobj = report_host(host_data)
host.elements.each("host_details/host_detail") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_host_details(hobj, hdet_data)
end
host.elements.each("exploit_attempts/exploit_attempt") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_exploit_attempt(hobj, hdet_data)
end
host.elements.each('services/service') do |service|
service_data = {}
service_data[:workspace] = wspace
service_data[:host] = hobj
service_data[:port] = nils_for_nulls(service.elements["port"].text.to_s.strip).to_i
service_data[:proto] = nils_for_nulls(service.elements["proto"].text.to_s.strip)
%W{created-at updated-at name state info}.each { |datum|
if service.elements[datum].text
if datum == "info"
service_data["info"] = nils_for_nulls(unserialize_object(service.elements[datum], false))
else
service_data[datum.gsub("-","_")] = nils_for_nulls(service.elements[datum].text.to_s.strip)
end
end
}
report_service(service_data)
end
host.elements.each('notes/note') do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:host] = hobj
note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip)
note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml))
if note.elements["critical"].text
note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL"
end
if note.elements["seen"].text
note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL"
end
%W{created-at updated-at}.each { |datum|
if note.elements[datum].text
note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip)
end
}
report_note(note_data)
end
host.elements.each('tags/tag') do |tag|
tag_data = {}
tag_data[:addr] = host_address
tag_data[:wspace] = wspace
tag_data[:name] = tag.elements["name"].text.to_s.strip
tag_data[:desc] = tag.elements["desc"].text.to_s.strip
if tag.elements["report-summary"].text
tag_data[:summary] = tag.elements["report-summary"].text.to_s.strip
end
if tag.elements["report-detail"].text
tag_data[:detail] = tag.elements["report-detail"].text.to_s.strip
end
if tag.elements["critical"].text
tag_data[:crit] = true unless tag.elements["critical"].text.to_s.strip == "NULL"
end
report_host_tag(tag_data)
end
host.elements.each('vulns/vuln') do |vuln|
vuln_data = {}
vuln_data[:workspace] = wspace
vuln_data[:host] = hobj
vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.elements["info"], allow_yaml))
vuln_data[:name] = nils_for_nulls(vuln.elements["name"].text.to_s.strip)
%W{created-at updated-at exploited-at}.each { |datum|
if vuln.elements[datum] and vuln.elements[datum].text
vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.elements[datum].text.to_s.strip)
end
}
if vuln.elements["refs"]
vuln_data[:refs] = []
vuln.elements.each("refs/ref") do |ref|
vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip)
end
end
vobj = report_vuln(vuln_data)
vuln.elements.each("vuln_details/vuln_detail") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_details(vobj, vdet_data)
end
vuln.elements.each("vuln_attempts/vuln_attempt") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_attempt(vobj, vdet_data)
end
end
host.elements.each('creds/cred') do |cred|
cred_data = {}
cred_data[:workspace] = wspace
cred_data[:host] = hobj
%W{port ptype sname proto proof active user pass}.each {|datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.intern] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
%W{created-at updated-at}.each { |datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.gsub("-","_")] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
%W{source-type source-id}.each { |datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.gsub("-","_").intern] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
if cred_data[:pass] == "<masked>"
cred_data[:pass] = ""
cred_data[:active] = false
elsif cred_data[:pass] == "*BLANK PASSWORD*"
cred_data[:pass] = ""
end
report_cred(cred_data)
end
host.elements.each('sessions/session') do |sess|
sess_id = nils_for_nulls(sess.elements["id"].text.to_s.strip.to_i)
sess_data = {}
sess_data[:host] = hobj
%W{desc platform port stype}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
%W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.elements["datastore"], allow_yaml))
if sess.elements["routes"]
sess_data[:routes] = nils_for_nulls(unserialize_object(sess.elements["routes"], allow_yaml)) || []
end
if not sess_data[:closed_at] # Fake a close if we don't already have one
sess_data[:closed_at] = Time.now.utc
sess_data[:close_reason] = "Imported at #{Time.now.utc}"
end
existing_session = get_session(
:workspace => sess_data[:host].workspace,
:addr => sess_data[:host].address,
:time => sess_data[:opened_at]
)
this_session = existing_session || report_session(sess_data)
next if existing_session
sess.elements.each('events/event') do |sess_event|
sess_event_data = {}
sess_event_data[:session] = this_session
%W{created-at etype local-path remote-path}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.elements[datum].text.to_s.strip)
end
}
%W{command output}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.elements[datum], allow_yaml))
end
}
report_session_event(sess_event_data)
end
end
end
# Import web sites
doc.elements.each("/#{btag}/web_sites/web_site") do |web|
info = {}
info[:workspace] = wspace
%W{host port vhost ssl comments}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:options] = nils_for_nulls(unserialize_object(web.elements["options"], allow_yaml)) if web.elements["options"].respond_to?(:text)
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
%W{created-at updated-at}.each { |datum|
if web.elements[datum].text
info[datum.gsub("-","_")] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
}
report_web_site(info)
yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block
end
%W{page form vuln}.each do |wtype|
doc.elements.each("/#{btag}/web_#{wtype}s/web_#{wtype}") do |web|
info = {}
info[:workspace] = wspace
info[:host] = nils_for_nulls(web.elements["host"].text.to_s.strip) if web.elements["host"].respond_to?(:text)
info[:port] = nils_for_nulls(web.elements["port"].text.to_s.strip) if web.elements["port"].respond_to?(:text)
info[:ssl] = nils_for_nulls(web.elements["ssl"].text.to_s.strip) if web.elements["ssl"].respond_to?(:text)
info[:vhost] = nils_for_nulls(web.elements["vhost"].text.to_s.strip) if web.elements["vhost"].respond_to?(:text)
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
case wtype
when "page"
%W{path code body query cookie auth ctype mtime location}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:headers] = nils_for_nulls(unserialize_object(web.elements["headers"], allow_yaml))
when "form"
%W{path query method}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:params] = nils_for_nulls(unserialize_object(web.elements["params"], allow_yaml))
when "vuln"
%W{path query method pname proof risk name blame description category confidence}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:params] = nils_for_nulls(unserialize_object(web.elements["params"], allow_yaml))
info[:risk] = info[:risk].to_i
info[:confidence] = info[:confidence].to_i
end
%W{created-at updated-at}.each { |datum|
if web.elements[datum].text
info[datum.gsub("-","_")] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
}
self.send("report_web_#{wtype}", info)
yield("web_#{wtype}".intern, info[:path]) if block
end
end
end
# Convert the string "NULL" to actual nil
def nils_for_nulls(str)
str == "NULL" ? nil : str

View File

@ -0,0 +1,580 @@
module Msf
class DBManager
# Handles importing of the xml format exported by Pro. The methods are in a
# module because (1) it's just good code layout and (2) it allows the
# methods to be overridden in Pro without using alias_method_chain as
# methods defined in a class cannot be overridden by including a module
# (unless you're running Ruby 2.0 and can use prepend)
module ImportMsfXml
#
# CONSTANTS
#
# Elements that can be treated as text (i.e. do not need to be
# deserialized) in {#import_msf_web_page_element}
MSF_WEB_PAGE_TEXT_ELEMENT_NAMES = [
'auth',
'body',
'code',
'cookie',
'ctype',
'location',
'mtime'
]
# Elements that can be treated as text (i.e. do not need to be
# deserialized) in {#import_msf_web_element}.
MSF_WEB_TEXT_ELEMENT_NAMES = [
'created-at',
'host',
'path',
'port',
'query',
'ssl',
'updated-at',
'vhost'
]
# Elements that can be treated as text (i.e. do not need to be
# deserialized) in {#import_msf_web_vuln_element}.
MSF_WEB_VULN_TEXT_ELEMENT_NAMES = [
'blame',
'category',
'confidence',
'description',
'method',
'name',
'pname',
'proof',
'risk'
]
#
# Instance Methods
#
# Imports web_form element using {Msf::DBManager#report_web_form}.
#
# @param element [REXML::Element] web_form element.
# @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing params.
# @option options [Mdm::Workspace, nil] :workspace
# (Msf::DBManager#workspace) workspace under which to report the
# Mdm::WebForm
# @yield [event, data]
# @yieldparam event [:web_page] The event name
# @yieldparam data [String] path
# @yieldreturn [void]
# @return [void]
def import_msf_web_form_element(element, options={}, &notifier)
options.assert_valid_keys(:allow_yaml, :workspace)
import_msf_web_element(element,
:allow_yaml => options[:allow_yaml],
:notifier => notifier,
:type => :form,
:workspace => options[:workspace]) do |element, options|
info = import_msf_text_element(element, 'method')
# FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_params = unserialize_object(
element.elements['params'],
options[:allow_yaml]
)
info[:params] = nils_for_nulls(unserialized_params)
info
end
end
# Imports web_page element using {Msf::DBManager#report_web_page}.
#
# @param element [REXML::Element] web_page element.
# @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing headers.
# @option options [Mdm::Workspace, nil] :workspace
# (Msf::DBManager#workspace) workspace under which to report the
# Mdm::WebPage.
# @yield [event, data]
# @yieldparam event [:web_page] The event name
# @yieldparam data [String] path
# @yieldreturn [void]
# @return [void]
def import_msf_web_page_element(element, options={}, &notifier)
options.assert_valid_keys(:allow_yaml, :workspace)
import_msf_web_element(element,
:allow_yaml => options[:allow_yaml],
:notifier => notifier,
:type => :page,
:workspace => options[:workspace]) do |element, options|
info = {}
MSF_WEB_PAGE_TEXT_ELEMENT_NAMES.each do |name|
element_info = import_msf_text_element(element, name)
info.merge!(element_info)
end
code = info[:code]
if code
info[:code] = code.to_i
end
# FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_headers = unserialize_object(
element.elements['headers'],
options[:allow_yaml]
)
info[:headers] = nils_for_nulls(unserialized_headers)
info
end
end
# Imports web_vuln element using {Msf::DBManager#report_web_vuln}.
#
# @param element [REXML::Element] web_vuln element.
# @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing headers.
# @option options [Mdm::Workspace, nil] :workspace
# (Msf::DBManager#workspace) workspace under which to report the
# Mdm::WebPage.
# @yield [event, data]
# @yieldparam event [:web_page] The event name
# @yieldparam data [String] path
# @yieldreturn [void]
# @return [void]
def import_msf_web_vuln_element(element, options={}, &notifier)
options.assert_valid_keys(:allow_yaml, :workspace)
import_msf_web_element(element,
:allow_yaml => options[:allow_yaml],
:notifier => notifier,
:workspace => options[:workspace],
:type => :vuln) do |element, options|
info = {}
MSF_WEB_VULN_TEXT_ELEMENT_NAMES.each do |name|
element_info = import_msf_text_element(element, name)
info.merge!(element_info)
end
confidence = info[:confidence]
if confidence
info[:confidence] = confidence.to_i
end
# FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_params = unserialize_object(
element.elements['params'],
options[:allow_yaml]
)
info[:params] = nils_for_nulls(unserialized_params)
risk = info[:risk]
if risk
info[:risk] = risk.to_i
end
info
end
end
# For each host, step through services, notes, and vulns, and import
# them.
# TODO: loot, tasks, and reports
def import_msf_xml(args={}, &block)
data = args[:data]
wspace = args[:wspace] || workspace
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
doc = rexmlify(data)
metadata = check_msf_xml_version!(doc)
allow_yaml = metadata[:allow_yaml]
btag = metadata[:root_tag]
doc.elements.each("/#{btag}/hosts/host") do |host|
host_data = {}
host_data[:workspace] = wspace
host_data[:host] = nils_for_nulls(host.elements["address"].text.to_s.strip)
if bl.include? host_data[:host]
next
else
yield(:address,host_data[:host]) if block
end
host_data[:mac] = nils_for_nulls(host.elements["mac"].text.to_s.strip)
if host.elements["comm"].text
host_data[:comm] = nils_for_nulls(host.elements["comm"].text.to_s.strip)
end
%W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum|
if host.elements[datum].text
host_data[datum.gsub('-','_')] = nils_for_nulls(host.elements[datum].text.to_s.strip)
end
}
host_address = host_data[:host].dup # Preserve after report_host() deletes
hobj = report_host(host_data)
host.elements.each("host_details/host_detail") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_host_details(hobj, hdet_data)
end
host.elements.each("exploit_attempts/exploit_attempt") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_exploit_attempt(hobj, hdet_data)
end
host.elements.each('services/service') do |service|
service_data = {}
service_data[:workspace] = wspace
service_data[:host] = hobj
service_data[:port] = nils_for_nulls(service.elements["port"].text.to_s.strip).to_i
service_data[:proto] = nils_for_nulls(service.elements["proto"].text.to_s.strip)
%W{created-at updated-at name state info}.each { |datum|
if service.elements[datum].text
if datum == "info"
service_data["info"] = nils_for_nulls(unserialize_object(service.elements[datum], false))
else
service_data[datum.gsub("-","_")] = nils_for_nulls(service.elements[datum].text.to_s.strip)
end
end
}
report_service(service_data)
end
host.elements.each('notes/note') do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:host] = hobj
note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip)
note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml))
if note.elements["critical"].text
note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL"
end
if note.elements["seen"].text
note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL"
end
%W{created-at updated-at}.each { |datum|
if note.elements[datum].text
note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip)
end
}
report_note(note_data)
end
host.elements.each('tags/tag') do |tag|
tag_data = {}
tag_data[:addr] = host_address
tag_data[:wspace] = wspace
tag_data[:name] = tag.elements["name"].text.to_s.strip
tag_data[:desc] = tag.elements["desc"].text.to_s.strip
if tag.elements["report-summary"].text
tag_data[:summary] = tag.elements["report-summary"].text.to_s.strip
end
if tag.elements["report-detail"].text
tag_data[:detail] = tag.elements["report-detail"].text.to_s.strip
end
if tag.elements["critical"].text
tag_data[:crit] = true unless tag.elements["critical"].text.to_s.strip == "NULL"
end
report_host_tag(tag_data)
end
host.elements.each('vulns/vuln') do |vuln|
vuln_data = {}
vuln_data[:workspace] = wspace
vuln_data[:host] = hobj
vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.elements["info"], allow_yaml))
vuln_data[:name] = nils_for_nulls(vuln.elements["name"].text.to_s.strip)
%W{created-at updated-at exploited-at}.each { |datum|
if vuln.elements[datum] and vuln.elements[datum].text
vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.elements[datum].text.to_s.strip)
end
}
if vuln.elements["refs"]
vuln_data[:refs] = []
vuln.elements.each("refs/ref") do |ref|
vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip)
end
end
vobj = report_vuln(vuln_data)
vuln.elements.each("vuln_details/vuln_detail") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_details(vobj, vdet_data)
end
vuln.elements.each("vuln_attempts/vuln_attempt") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_attempt(vobj, vdet_data)
end
end
host.elements.each('creds/cred') do |cred|
cred_data = {}
cred_data[:workspace] = wspace
cred_data[:host] = hobj
%W{port ptype sname proto proof active user pass}.each {|datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.intern] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
%W{created-at updated-at}.each { |datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.gsub("-","_")] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
%W{source-type source-id}.each { |datum|
if cred.elements[datum].respond_to? :text
cred_data[datum.gsub("-","_").intern] = nils_for_nulls(cred.elements[datum].text.to_s.strip)
end
}
if cred_data[:pass] == "<masked>"
cred_data[:pass] = ""
cred_data[:active] = false
elsif cred_data[:pass] == "*BLANK PASSWORD*"
cred_data[:pass] = ""
end
report_cred(cred_data)
end
host.elements.each('sessions/session') do |sess|
sess_id = nils_for_nulls(sess.elements["id"].text.to_s.strip.to_i)
sess_data = {}
sess_data[:host] = hobj
%W{desc platform port stype}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
%W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.elements["datastore"], allow_yaml))
if sess.elements["routes"]
sess_data[:routes] = nils_for_nulls(unserialize_object(sess.elements["routes"], allow_yaml)) || []
end
if not sess_data[:closed_at] # Fake a close if we don't already have one
sess_data[:closed_at] = Time.now.utc
sess_data[:close_reason] = "Imported at #{Time.now.utc}"
end
existing_session = get_session(
:workspace => sess_data[:host].workspace,
:addr => sess_data[:host].address,
:time => sess_data[:opened_at]
)
this_session = existing_session || report_session(sess_data)
next if existing_session
sess.elements.each('events/event') do |sess_event|
sess_event_data = {}
sess_event_data[:session] = this_session
%W{created-at etype local-path remote-path}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.elements[datum].text.to_s.strip)
end
}
%W{command output}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.elements[datum], allow_yaml))
end
}
report_session_event(sess_event_data)
end
end
end
# Import web sites
doc.elements.each("/#{btag}/web_sites/web_site") do |web|
info = {}
info[:workspace] = wspace
%W{host port vhost ssl comments}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:options] = nils_for_nulls(unserialize_object(web.elements["options"], allow_yaml)) if web.elements["options"].respond_to?(:text)
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
%W{created-at updated-at}.each { |datum|
if web.elements[datum].text
info[datum.gsub("-","_")] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
}
report_web_site(info)
yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block
end
%W{page form vuln}.each do |wtype|
doc.elements.each("/#{btag}/web_#{wtype}s/web_#{wtype}") do |element|
send(
"import_msf_web_#{wtype}_element",
element,
:allow_yaml => allow_yaml,
:workspace => wspace,
&block
)
end
end
end
private
# Checks if the XML document has a format version that the importer
# understands.
#
# @param document [REXML::Document] a REXML::Document produced by
# {Msf::DBManager#rexmlify}.
# @return [Hash{Symbol => Object}] `:allow_yaml` is true if the format
# requires YAML loading when calling
# {Msf::DBManager#unserialize_object}. `:root_tag` the tag name of the
# root element for MSF XML.
# @raise [Msf::DBImportError] if unsupported format
def check_msf_xml_version!(document)
metadata = {
# FIXME https://www.pivotaltracker.com/story/show/47128407
:allow_yaml => false,
:root_tag => nil
}
if document.elements['MetasploitExpressV1']
# FIXME https://www.pivotaltracker.com/story/show/47128407
metadata[:allow_yaml] = true
metadata[:root_tag] = 'MetasploitExpressV1'
elsif document.elements['MetasploitExpressV2']
# FIXME https://www.pivotaltracker.com/story/show/47128407
metadata[:allow_yaml] = true
metadata[:root_tag] = 'MetasploitExpressV2'
elsif document.elements['MetasploitExpressV3']
metadata[:root_tag] = 'MetasploitExpressV3'
elsif document.elements['MetasploitExpressV4']
metadata[:root_tag] = 'MetasploitExpressV4'
elsif document.elements['MetasploitV4']
metadata[:root_tag] = 'MetasploitV4'
end
unless metadata[:root_tag]
raise Msf::DBImportError,
'Unsupported Metasploit XML document format'
end
metadata
end
# Retrieves text of element if it exists.
#
# @param parent_element [REXML::Element] element under which element with
# `child_name` exists.
# @param child_name [String] the name of the element under
# `parent_element` whose text should be returned
# @return [{}] if element with child_name does not exist or does not have
# text.
# @return [Hash{Symbol => String}] Maps child_name symbol to text. Text is
# stripped and any NULLs are converted to `nil`.
# @return [nil] if element with `child_name` does not exist under
# `parent_element`.
def import_msf_text_element(parent_element, child_name)
child_element = parent_element.elements[child_name]
info = {}
if child_element
stripped = child_element.text.to_s.strip
attribute_name = child_name.underscore.to_sym
info[attribute_name] = nils_for_nulls(stripped)
end
info
end
# Imports web_form, web_page, or web_vuln element using
# {Msf::DBManager#report_web_form}, {Msf::DBManager#report_web_page}, and
# {Msf::DBManager#report_web_vuln}, respectively.
#
# @param element [REXML::Element] the web_form, web_page, or web_vuln
# element.
# @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing elements.
# @option options [Proc] :notifier Block called with web_* event and path
# @option options [Symbol] :type the type of web element, such as :form,
# :page, or :vuln. Must correspond to a report_web_<type> method on
# {Msf::DBManager}.
# @option options [Mdm::Workspace, nil] :workspace
# (Msf::DBManager#workspace) workspace under which to report the
# imported record.
# @yield [element, options]
# @yieldparam element [REXML::Element] the web_form, web_page, or
# web_vuln element passed to {#import_msf_web_element}.
# @yieldparam options [Hash{Symbol => Object}] options for parsing
# @yieldreturn [Hash{Symbol => Object}] info
# @return [void]
# @raise [KeyError] if `:type` is not given
def import_msf_web_element(element, options={}, &specialization)
options.assert_valid_keys(:allow_yaml, :notifier, :type, :workspace)
type = options.fetch(:type)
info = {}
info[:workspace] = options[:workspace] || self.workspace
MSF_WEB_TEXT_ELEMENT_NAMES.each do |name|
element_info = import_msf_text_element(element, name)
info.merge!(element_info)
end
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
specialized_info = specialization.call(element, options)
info.merge!(specialized_info)
self.send("report_web_#{type}", info)
notifier = options[:notifier]
if notifier
event = "web_#{type}".to_sym
notifier.call(event, info[:path])
end
end
end
end
end

View File

@ -1,14 +1,10 @@
# -*- coding: binary -*-
##
# $Id$
##
##
#
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core/auxiliary'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/exploitation/cmdstager'
require 'msf/core/exploit/exe'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/core/exploit/cmdstager'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/core/exploit/cmdstager'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/text'
require 'msf/core/exploit/tftp'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'msf/core/exploit/cmdstager'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id: $
##
require 'msf/core/exploit/cmdstager'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/proto/dhcp'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/proto/tftp'

View File

@ -58,7 +58,8 @@ class Msf::Modules::Loader::Base
MODULE_EXTENSION = '.rb'
# String used to separate module names in a qualified module name.
MODULE_SEPARATOR = '::'
# The base namespace name under which {#namespace_module #namespace_modules} are created.
# The base namespace name under which {#create_namespace_module
# namespace modules are created}.
NAMESPACE_MODULE_NAMES = ['Msf', 'Modules']
# Regex that can distinguish regular ruby source from unit test source.
UNIT_TEST_REGEX = /rb\.(ut|ts)\.rb$/
@ -340,7 +341,8 @@ class Msf::Modules::Loader::Base
# module's classes. The wrapper module must be named so that active_support's autoloading code doesn't break when
# searching constants from inside the Metasploit(1|2|3) class.
#
# @param [String] namespace_module_names (see #{namespace_module_names})
# @param namespace_module_names [Array<String>]
# {NAMESPACE_MODULE_NAMES} + <derived-constant-safe names>
# @return [Module] module that can wrap the module content from {#read_module_content} using
# module_eval_with_lexical_scope.
#
@ -375,7 +377,7 @@ class Msf::Modules::Loader::Base
namespace_module
end
# Returns the module with {#module_names} if it exists.
# Returns the module with `module_names` if it exists.
#
# @param [Array<String>] module_names a list of module names to resolve from Object downward.
# @return [Module] module that wraps the previously loaded content from {#read_module_content}.
@ -484,13 +486,14 @@ class Msf::Modules::Loader::Base
# Returns the fully-qualified name to the {#create_namespace_module} that wraps the module with the given module
# reference name.
#
# @param [String] module_reference_name The canonical name for referring to the module.
# @param [String] module_full_name The canonical name for referring to the
# module.
# @return [String] name of module.
#
# @see MODULE_SEPARATOR
# @see #namespace_module_names
def namespace_module_name(uniq_module_reference_name)
namespace_module_names = self.namespace_module_names(uniq_module_reference_name)
def namespace_module_name(module_full_name)
namespace_module_names = self.namespace_module_names(module_full_name)
namespace_module_name = namespace_module_names.join(MODULE_SEPARATOR)
namespace_module_name
@ -502,20 +505,20 @@ class Msf::Modules::Loader::Base
# escaped by using 'H*' unpacking and prefixing each code with X so
# the code remains a valid module name when it starts with a digit.
#
# @param [String] uniq_module_reference_name The unique canonical name
# @param [String] module_full_name The unique canonical name
# for the module including type.
# @return [Array<String>] {NAMESPACE_MODULE_NAMES} + <derived-constant-safe names>
#
# @see namespace_module
def namespace_module_names(uniq_module_reference_name)
NAMESPACE_MODULE_NAMES + [ "Mod" + uniq_module_reference_name.unpack("H*").first.downcase ]
def namespace_module_names(module_full_name)
NAMESPACE_MODULE_NAMES + [ "Mod" + module_full_name.unpack("H*").first.downcase ]
end
def namespace_module_transaction(uniq_module_reference_name, options={}, &block)
def namespace_module_transaction(module_full_name, options={}, &block)
options.assert_valid_keys(:reload)
reload = options[:reload] || false
namespace_module_names = self.namespace_module_names(uniq_module_reference_name)
namespace_module_names = self.namespace_module_names(module_full_name)
previous_namespace_module = current_module(namespace_module_names)

View File

@ -1,4 +1,15 @@
# -*- coding: binary -*-
#
# Rex
#
require 'rex/ui/text/output/buffer/stdout'
#
# Project
#
require 'msf/ui/console/command_dispatcher/encoder'
require 'msf/ui/console/command_dispatcher/exploit'
require 'msf/ui/console/command_dispatcher/nop'
@ -2532,11 +2543,12 @@ class Core
# redirect output after saving the old ones and getting a new output buffer to use for redirect
orig_driver_output = orig_driver.output
orig_driver_input = orig_driver.input
# we use a rex buffer but add a write method to the instance, which is required in order to be valid $stdout
# we use a rex buffer but add a write method to the instance, which is
# required in order to be valid $stdout
temp_output = Rex::Ui::Text::Output::Buffer.new
def temp_output.write(msg = '')
self.print_raw(msg)
end
temp_output.extend Rex::Ui::Text::Output::Buffer::Stdout
orig_driver.init_ui(orig_driver_input,temp_output)
# run the desired command to be grepped
orig_driver.run_single(cmd)

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/parser/arguments'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/exploitation/cmdstager/base'
require 'rex/exploitation/cmdstager/vbs'

View File

@ -1,7 +1,4 @@
# -*- coding: binary -*-
##
# $Id: debug_asm.rb 12595 2011-05-12 18:33:49Z jduck $
##
require 'rex/text'
require 'rex/arch'

View File

@ -1,7 +1,4 @@
# -*- coding: binary -*-
##
# $Id: debug_write.rb 12595 2011-05-12 18:33:49Z jduck $
##
require 'rex/text'
require 'rex/arch'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/text'
require 'rex/arch'

View File

@ -1,7 +1,4 @@
# -*- coding: binary -*-
##
# $Id: vbs.rb 12595 2011-05-12 18:33:49Z jduck $
##
require 'rex/text'
require 'rex/arch'

View File

@ -1,7 +1,5 @@
# -*- coding: binary -*-
##
# $Id$
##
require 'rex/text'
require 'rkelly'

View File

@ -100,12 +100,6 @@ class Section
def file_offset_to_rva(foffset)
return offset_to_rva(foffset - file_offset)
end
# if offset < 0 || offset < file_offset || offset >= file_offset+size
# raise BoundsError, "File offset #{offset} outside of section", caller
# end
#
# return (offset - file_offset) + base_rva
# end
def rva_to_offset(rva)
offset = rva - base_rva

View File

@ -131,7 +131,7 @@ class LogicalBlock
#
# Increments the number of blocks that have completed their dependency
# pass on this block. This number should never become higher than the
# @references attribute.
# `@references` attribute.
#
def deref
@used_references += 1

View File

@ -1,11 +1,7 @@
# -*- coding: binary -*-
##
#
# NAT-PMP protocol support
#
# by Jon Hart <jhart@spoofed.org>
#
##
# @author Jon Hart <jhart@spoofed.org>
require 'rex/proto/natpmp/constants'
require 'rex/proto/natpmp/packet'

View File

@ -40,17 +40,13 @@
# The latter has a minor bug in its separate_keys function.
# The third key has to begin from the 14th character of the
# input string instead of 13th:)
#--
# $Id: ntlm.rb 11678 2011-01-30 19:26:35Z hdm $
#++
#this class defines the base type needed for other modules like message and crypt
require 'rex/proto/ntlm/constants'
module Rex
module Proto
module NTLM
# The base type needed for other modules like message and crypt
class Base
CONST = Rex::Proto::NTLM::Constants
@ -164,15 +160,19 @@ CONST = Rex::Proto::NTLM::Constants
class FieldSet
class << FieldSet
def define(&block)
c = Class.new(self)
def c.inherited(subclass)
proto = @proto
subclass.instance_eval {
@proto = proto
}
klass = Class.new(self) do
def self.inherited(subclass)
proto = @proto
subclass.instance_eval do
@proto = proto
end
end
end
c.module_eval(&block)
c
klass.module_eval(&block)
klass
end
def string(name, opts)

View File

@ -1,19 +1,13 @@
# -*- coding: binary -*-
##
# $Id: $
##
##
#
# RFB protocol support
#
# by Joshua J. Drake <jduck>
# @author Joshua J. Drake <jduck>
#
# Based on:
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
#
##
require 'rex/proto/rfb/constants'
require 'rex/proto/rfb/cipher'

View File

@ -1,23 +1,18 @@
#!/usr/bin/env ruby
# -*- coding: binary -*-
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
##
#
# $Id: $
##
##
#
# RFB protocol support
#
# by Joshua J. Drake <jduck>
# @author Joshua J. Drake <jduck>
#
# Based on:
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
#
##
$:.unshift(File.join(File.dirname(__FILE__), '..', '..'))
require 'rex/socket'
require 'rex/proto/rfb'

View File

@ -1020,7 +1020,7 @@ module Text
rand_base(len, bad, *foo )
end
# Generate a random GUID, of the form {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
# Generate a random GUID, of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
def self.rand_guid
"{#{[8,4,4,4,12].map {|a| rand_text_hex(a) }.join("-")}}"
end

View File

@ -0,0 +1,25 @@
# make sure the classes are defined before opening it to define submodule
require 'rex/ui/text/output'
require 'rex/ui/text/output/buffer'
module Rex
module Ui
module Text
class Output
class Buffer
# Adds {#write} method to {Rex::Ui::Text::Output::Buffer} so it can
# function as a stand-in for `$stdout`
module Stdout
# Prints raw message.
#
# @param (see Rex::Ui::Text::Output::Buffer#write)
# @return (see Rex::Ui::Text::Output::Buffer#write)
def write(msg = '')
print_raw(msg)
end
end
end
end
end
end
end

View File

@ -1,6 +1,7 @@
load 'active_record/railties/databases.rake'
require 'metasploit/framework'
require 'metasploit/framework/database'
# A modification to remove dependency on Rails.env
#
@ -21,19 +22,10 @@ def configs_for_environment
valid_environment_configurations
end
# This would normally use Rails.application.config.database_configuration
def database_configurations
YAML.load_file(database_configurations_pathname)
end
def database_configurations_pathname
Metasploit::Framework.root.join('config', 'database.yml')
end
# emulate initializer "active_record.initialize_database" from active_record/railtie
ActiveSupport.on_load(:active_record) do
self.configurations = database_configurations
puts "Connecting to database specified by #{database_configurations_pathname}"
self.configurations = Metasploit::Framework::Database.configurations
puts "Connecting to database specified by #{Metasploit::Framework::Database.configurations_pathname}"
spec = configurations[Metasploit::Framework.env]
establish_connection(spec)
@ -58,7 +50,7 @@ Rake::Task['db:seed'].clear
db_namespace = namespace :db do
task :load_config do
ActiveRecord::Base.configurations = database_configurations
ActiveRecord::Base.configurations = Metasploit::Framework::Database.configurations
ActiveRecord::Migrator.migrations_paths = [
# rails isn't in Gemfile, so can't use the more appropriate

View File

@ -39,7 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
},
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' =>
'Targets' =>
[
['stunshell', {}]
],

View File

@ -0,0 +1,34 @@
FactoryGirl.define do
factory :mdm_web_form, :class => Mdm::WebForm do
#
# Associations
#
association :web_site, :factory => :mdm_web_site
# attributes that would be in web_form element from Pro export
trait :exported do
method { generate :mdm_web_form_method }
params { generate :mdm_web_form_params }
path { generate :mdm_web_form_path }
end
end
methods = ['GET', 'POST']
sequence :mdm_web_form_method do |n|
methods[n % methods.length]
end
sequence :mdm_web_form_params do |n|
[
[
"name#{n}",
"value#{n}"
]
]
end
sequence :mdm_web_form_path do |n|
"path/to/web/form/#{n}"
end
end

View File

@ -0,0 +1,64 @@
FactoryGirl.define do
factory :mdm_web_page, :class => Mdm::WebPage do
auth { generate :mdm_web_page_auth }
body { generate :mdm_web_page_body }
code { generate :mdm_web_page_code }
cookie { generate :mdm_web_page_cookie }
ctype { generate :mdm_web_page_ctype }
headers { generate :mdm_web_page_headers }
location { generate :mdm_web_page_location }
mtime { generate :mdm_web_page_mtime }
query { generate :mdm_web_page_query }
#
# Associations
#
association :web_site, :factory => :mdm_web_site
end
sequence :mdm_web_page_auth do |n|
"Authorization: #{n}"
end
sequence :mdm_web_page_body do |n|
xml = Builder::XmlMarkup.new(:indent => 2)
xml.html
xml.target!.strip
end
sequence :mdm_web_page_code do |n|
n
end
sequence :mdm_web_page_cookie do |n|
"name#{n}=value#{n}"
end
sequence :mdm_web_page_ctype do |n|
"application/x-#{n}"
end
sequence :mdm_web_page_headers do |n|
[
[
"Header#{n}",
"Value#{n}"
]
]
end
sequence :mdm_web_page_location do |n|
"http://example.com/location/#{n}"
end
sequence :mdm_web_page_mtime do |n|
past = Time.now - n
past.utc.strftime('%a, %d %b %Y %H:%M:%S %Z')
end
sequence :mdm_web_page_query do |n|
"param#{n}=value#{n}"
end
end

View File

@ -0,0 +1,14 @@
FactoryGirl.define do
factory :exported_web_vuln, :parent => :mdm_web_vuln do
blame { generate :mdm_web_vuln_blame }
description { generate :mdm_web_vuln_description }
end
sequence :mdm_web_vuln_blame do |n|
"Blame employee ##{n}"
end
sequence :mdm_web_vuln_description do |n|
"Mdm::WebVuln#description #{n}"
end
end

View File

@ -0,0 +1,22 @@
#
# Specs
#
require 'spec_helper'
#
# Project
#
require 'metasploit/framework/database'
require 'msf/core'
describe Msf::DBManager do
include_context 'Msf::Simple::Framework'
subject(:db_manager) do
framework.db
end
it_should_behave_like 'Msf::DBManager::ImportMsfXml'
end

View File

@ -25,5 +25,22 @@ end
RSpec.configure do |config|
config.mock_with :rspec
# Can't use factory_girl_rails since not using rails, so emulate
# factory_girl.set_factory_paths initializer and after_initialize for
# FactoryGirl::Railtie
config.before(:suite) do
# Need to load Mdm models first so factories can use them
MetasploitDataModels.require_models
FactoryGirl.definition_file_paths = [
MetasploitDataModels.root.join('spec', 'factories'),
# Have metasploit-framework's definition file path last so it can
# modify gem factories.
Metasploit::Framework.root.join('spec', 'factories')
]
FactoryGirl.find_definitions
end
end

View File

@ -0,0 +1,34 @@
shared_context 'DatabaseCleaner' do
def with_established_connection
begin
ActiveRecord::Base.connection_pool.with_connection do
yield
end
rescue ActiveRecord::ConnectionNotEstablished
# if there isn't a connection established, then established one and try
# again
ActiveRecord::Base.configurations = Metasploit::Framework::Database.configurations
spec = ActiveRecord::Base.configurations[Metasploit::Framework.env]
ActiveRecord::Base.establish_connection(spec)
retry
end
end
# clean before all in case last test run was interrupted before
# after(:each) could clean up
before(:all) do
with_established_connection do
DatabaseCleaner.clean_with(:truncation)
end
end
# Clean up after each test
after(:each) do
with_established_connection do
# Testing using both :truncation and :deletion; :truncation took long
# for testing.
DatabaseCleaner.clean_with(:deletion)
end
end
end

View File

@ -0,0 +1,39 @@
require 'msf/base/simple/framework'
require 'metasploit/framework'
shared_context 'Msf::Simple::Framework' do
let(:dummy_pathname) do
Metasploit::Framework.root.join('spec', 'dummy')
end
let(:framework) do
Msf::Simple::Framework.create(
'ConfigDirectory' => framework_config_pathname.to_s,
# don't load any module paths so we can just load the module under test and save time
'DeferModuleLoads' => true
)
end
let(:framework_config_pathname) do
dummy_pathname.join('framework', 'config')
end
before(:each) do
framework_config_pathname.mkpath
end
after(:each) do
dummy_pathname.rmtree
end
after(:each) do
# explicitly kill threads so that they don't exhaust connection pool
thread_manager = framework.threads
thread_manager.each do |thread|
thread.kill
end
thread_manager.monitor.kill
end
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
shared_examples_for 'Msf::DBManager::ImportMsfXml#check_msf_xml_version! with root tag' do |root_tag, options={}|
options.assert_valid_keys(:allow_yaml)
allow_yaml = options.fetch(:allow_yaml)
context "with #{root_tag}" do
let(:root_tag) do
root_tag
end
should_label_by_allow_yaml = {
true => 'should',
false => 'should not'
}
should_label = should_label_by_allow_yaml[allow_yaml]
it "#{should_label} allow YAML" do
expect(metadata[:allow_yaml]).to eq(allow_yaml)
end
it "should have #{root_tag} as root tag" do
metadata[:root_tag].should == root_tag
end
end
end

View File

@ -0,0 +1,41 @@
shared_examples_for 'Msf::DBManager::ImportMsfXml#import_msf_web_element specialization' do
it 'should call #import_msf_web_element with element' do
db_manager.should_receive(:import_msf_web_element).with(element, anything)
subject
end
it 'should call #import_msf_web_element with :allow_yaml and :workspace' do
db_manager.should_receive(:import_msf_web_element).with(
anything,
hash_including(
:allow_yaml => allow_yaml,
:workspace => workspace
)
)
subject
end
it 'should call #import_msf_web_element with :type' do
db_manager.should_receive(:import_msf_web_element).with(
anything,
hash_including(
:type => type
)
)
subject
end
it 'should pass block to #import_msf_web_element as :notifier' do
db_manager.should_receive(
:import_msf_web_element
).with(
anything,
hash_including(:notifier => notifier)
)
subject
end
end