2013-04-01 21:06:40 +00:00
|
|
|
#
|
|
|
|
# Specs
|
|
|
|
#
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
#
|
|
|
|
# Project
|
|
|
|
#
|
|
|
|
|
|
|
|
require 'metasploit/framework/database'
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
describe Msf::DBManager do
|
2013-09-30 18:47:53 +00:00
|
|
|
include_context 'Msf::DBManager'
|
|
|
|
|
|
|
|
subject do
|
|
|
|
db_manager
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager::ImportMsfXml'
|
2014-10-08 20:30:20 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager::Migration'
|
|
|
|
it_should_behave_like 'Msf::DBManager::Sink'
|
2013-09-30 18:47:53 +00:00
|
|
|
|
2014-10-07 20:49:42 +00:00
|
|
|
context 'CONSTANTS' do
|
|
|
|
context 'ADAPTER' do
|
|
|
|
subject(:adapter) {
|
|
|
|
described_class::ADAPTER
|
|
|
|
}
|
|
|
|
|
|
|
|
it { is_expected.to eq('postgresql') }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it { is_expected.to respond_to :active }
|
|
|
|
|
2014-05-12 20:03:51 +00:00
|
|
|
context '#add_rails_engine_migration_paths' do
|
|
|
|
def add_rails_engine_migration_paths
|
|
|
|
db_manager.add_rails_engine_migration_paths
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'should not add duplicate paths to ActiveRecord::Migrator.migrations_paths' do
|
2014-05-12 20:03:51 +00:00
|
|
|
add_rails_engine_migration_paths
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
expect {
|
2014-05-12 20:03:51 +00:00
|
|
|
add_rails_engine_migration_paths
|
2013-09-30 18:47:53 +00:00
|
|
|
}.to_not change {
|
|
|
|
ActiveRecord::Migrator.migrations_paths.length
|
|
|
|
}
|
|
|
|
|
|
|
|
ActiveRecord::Migrator.migrations_paths.uniq.should == ActiveRecord::Migrator.migrations_paths
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :add_workspace }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :after_establish_connection }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :check }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :connect }
|
|
|
|
it { is_expected.to respond_to :connection_established? }
|
|
|
|
it { is_expected.to respond_to :create_db }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :create_request }
|
|
|
|
it { is_expected.to respond_to :create_target }
|
|
|
|
it { is_expected.to respond_to :creds }
|
|
|
|
it { is_expected.to respond_to :default_workspace }
|
|
|
|
it { is_expected.to respond_to :dehex }
|
|
|
|
it { is_expected.to respond_to :del_host }
|
|
|
|
it { is_expected.to respond_to :del_service }
|
|
|
|
it { is_expected.to respond_to :delete_all_targets }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :disconnect }
|
|
|
|
it { is_expected.to respond_to :driver }
|
|
|
|
it { is_expected.to respond_to :drivers }
|
|
|
|
it { is_expected.to respond_to :drivers= }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :each_cred }
|
|
|
|
it { is_expected.to respond_to :each_distinct_target }
|
|
|
|
it { is_expected.to respond_to :each_exploited_host }
|
|
|
|
it { is_expected.to respond_to :each_host }
|
|
|
|
it { is_expected.to respond_to :each_loot }
|
|
|
|
it { is_expected.to respond_to :each_note }
|
|
|
|
it { is_expected.to respond_to :each_request }
|
|
|
|
it { is_expected.to respond_to :each_request_target }
|
|
|
|
it { is_expected.to respond_to :each_request_target_with_body }
|
|
|
|
it { is_expected.to respond_to :each_request_target_with_headers }
|
|
|
|
it { is_expected.to respond_to :each_request_target_with_path }
|
|
|
|
it { is_expected.to respond_to :each_request_target_with_query }
|
|
|
|
it { is_expected.to respond_to :each_service }
|
|
|
|
it { is_expected.to respond_to :each_target }
|
|
|
|
it { is_expected.to respond_to :each_vuln }
|
|
|
|
it { is_expected.to respond_to :emit }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :error }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :events }
|
|
|
|
it { is_expected.to respond_to :exploited_hosts }
|
|
|
|
it { is_expected.to respond_to :find_or_create_client }
|
|
|
|
it { is_expected.to respond_to :find_or_create_cred }
|
|
|
|
it { is_expected.to respond_to :find_or_create_host }
|
|
|
|
it { is_expected.to respond_to :find_or_create_loot }
|
|
|
|
it { is_expected.to respond_to :find_or_create_note }
|
|
|
|
it { is_expected.to respond_to :find_or_create_ref }
|
|
|
|
it { is_expected.to respond_to :find_or_create_report }
|
|
|
|
it { is_expected.to respond_to :find_or_create_service }
|
|
|
|
it { is_expected.to respond_to :find_or_create_task }
|
|
|
|
it { is_expected.to respond_to :find_or_create_vuln }
|
|
|
|
it { is_expected.to respond_to :find_qualys_asset_ports }
|
|
|
|
it { is_expected.to respond_to :find_qualys_asset_vuln_refs }
|
|
|
|
it { is_expected.to respond_to :find_qualys_asset_vulns }
|
|
|
|
it { is_expected.to respond_to :find_vuln_by_details }
|
|
|
|
it { is_expected.to respond_to :find_vuln_by_refs }
|
|
|
|
it { is_expected.to respond_to :find_workspace }
|
|
|
|
it { is_expected.to respond_to :get_client }
|
|
|
|
it { is_expected.to respond_to :get_host }
|
|
|
|
it { is_expected.to respond_to :get_ref }
|
|
|
|
it { is_expected.to respond_to :get_service }
|
|
|
|
it { is_expected.to respond_to :get_session }
|
|
|
|
it { is_expected.to respond_to :get_target }
|
|
|
|
it { is_expected.to respond_to :get_vuln }
|
|
|
|
it { is_expected.to respond_to :has_host? }
|
|
|
|
it { is_expected.to respond_to :has_ref? }
|
|
|
|
it { is_expected.to respond_to :has_vuln? }
|
|
|
|
it { is_expected.to respond_to :hosts }
|
|
|
|
it { is_expected.to respond_to :import }
|
|
|
|
it { is_expected.to respond_to :import_acunetix_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_acunetix_xml }
|
|
|
|
it { is_expected.to respond_to :import_amap_log }
|
|
|
|
it { is_expected.to respond_to :import_amap_log_file }
|
|
|
|
it { is_expected.to respond_to :import_amap_mlog }
|
|
|
|
it { is_expected.to respond_to :import_appscan_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_appscan_xml }
|
|
|
|
it { is_expected.to respond_to :import_burp_session_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_burp_session_xml }
|
|
|
|
it { is_expected.to respond_to :import_ci_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_ci_xml }
|
|
|
|
it { is_expected.to respond_to :import_file }
|
|
|
|
it { is_expected.to respond_to :import_filetype_detect }
|
|
|
|
it { is_expected.to respond_to :import_foundstone_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_foundstone_xml }
|
|
|
|
it { is_expected.to respond_to :import_fusionvm_xml }
|
|
|
|
it { is_expected.to respond_to :import_ip360_aspl_xml }
|
|
|
|
it { is_expected.to respond_to :import_ip360_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_ip360_xml_v3 }
|
|
|
|
it { is_expected.to respond_to :import_ip_list }
|
|
|
|
it { is_expected.to respond_to :import_ip_list_file }
|
|
|
|
it { is_expected.to respond_to :import_libpcap }
|
|
|
|
it { is_expected.to respond_to :import_libpcap_file }
|
|
|
|
it { is_expected.to respond_to :import_mbsa_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_mbsa_xml }
|
|
|
|
it { is_expected.to respond_to :import_msf_collateral }
|
|
|
|
it { is_expected.to respond_to :import_msf_cred_dump }
|
|
|
|
it { is_expected.to respond_to :import_msf_cred_dump_zip }
|
|
|
|
it { is_expected.to respond_to :import_msf_file }
|
|
|
|
it { is_expected.to respond_to :import_msf_pwdump }
|
|
|
|
it { is_expected.to respond_to :import_msf_zip }
|
|
|
|
it { is_expected.to respond_to :import_nessus_nbe }
|
|
|
|
it { is_expected.to respond_to :import_nessus_nbe_file }
|
|
|
|
it { is_expected.to respond_to :import_nessus_xml }
|
|
|
|
it { is_expected.to respond_to :import_nessus_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_nessus_xml_v2 }
|
|
|
|
it { is_expected.to respond_to :import_netsparker_xml }
|
|
|
|
it { is_expected.to respond_to :import_netsparker_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_raw_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_rawxml }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_rawxml_file }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_simplexml }
|
|
|
|
it { is_expected.to respond_to :import_nexpose_simplexml_file }
|
|
|
|
it { is_expected.to respond_to :import_nikto_xml }
|
|
|
|
it { is_expected.to respond_to :import_nmap_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_nmap_xml }
|
|
|
|
it { is_expected.to respond_to :import_nmap_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_openvas_new_xml }
|
|
|
|
it { is_expected.to respond_to :import_openvas_new_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_openvas_xml }
|
|
|
|
it { is_expected.to respond_to :import_outpost24_noko_stream }
|
|
|
|
it { is_expected.to respond_to :import_outpost24_xml }
|
|
|
|
it { is_expected.to respond_to :import_qualys_asset_xml }
|
|
|
|
it { is_expected.to respond_to :import_qualys_scan_xml }
|
|
|
|
it { is_expected.to respond_to :import_qualys_scan_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_report }
|
|
|
|
it { is_expected.to respond_to :import_retina_xml }
|
|
|
|
it { is_expected.to respond_to :import_retina_xml_file }
|
|
|
|
it { is_expected.to respond_to :import_spiceworks_csv }
|
|
|
|
it { is_expected.to respond_to :import_wapiti_xml }
|
|
|
|
it { is_expected.to respond_to :import_wapiti_xml_file }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :initialize_adapter }
|
|
|
|
it { is_expected.to respond_to :initialize_database_support }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :inspect_single_packet }
|
|
|
|
it { is_expected.to respond_to :inspect_single_packet_http }
|
|
|
|
it { is_expected.to respond_to :ipv46_validator }
|
|
|
|
it { is_expected.to respond_to :ipv4_validator }
|
|
|
|
it { is_expected.to respond_to :ipv6_validator }
|
|
|
|
it { is_expected.to respond_to :loots }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :modules_cached }
|
|
|
|
it { is_expected.to respond_to :modules_cached }
|
|
|
|
it { is_expected.to respond_to :modules_cached= }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :modules_cached= }
|
|
|
|
it { is_expected.to respond_to :msf_import_timestamps }
|
|
|
|
it { is_expected.to respond_to :netsparker_method_map }
|
|
|
|
it { is_expected.to respond_to :netsparker_params_map }
|
|
|
|
it { is_expected.to respond_to :netsparker_pname_map }
|
|
|
|
it { is_expected.to respond_to :netsparker_vulnerability_map }
|
|
|
|
it { is_expected.to respond_to :nexpose_host_from_rawxml }
|
|
|
|
it { is_expected.to respond_to :nexpose_refs_to_struct }
|
|
|
|
it { is_expected.to respond_to :nils_for_nulls }
|
|
|
|
it { is_expected.to respond_to :nmap_msf_service_map }
|
|
|
|
it { is_expected.to respond_to :normalize_host }
|
|
|
|
it { is_expected.to respond_to :notes }
|
2014-10-07 20:49:42 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context '#purge_all_module_details' do
|
|
|
|
def purge_all_module_details
|
|
|
|
db_manager.purge_all_module_details
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:migrated) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail_count) do
|
|
|
|
2
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_details) do
|
|
|
|
FactoryGirl.create_list(
|
|
|
|
:mdm_module_detail,
|
|
|
|
module_detail_count
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:migrated => migrated)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with migrated' do
|
|
|
|
let(:migrated) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:modules_caching) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:modules_caching => modules_caching)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with modules_caching' do
|
|
|
|
let(:modules_caching) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should not destroy Mdm::Module::Details' do
|
|
|
|
expect {
|
|
|
|
purge_all_module_details
|
|
|
|
}.to_not change(Mdm::Module::Detail, :count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without modules_caching' do
|
|
|
|
it 'should destroy all Mdm::Module::Details' do
|
|
|
|
expect {
|
|
|
|
purge_all_module_details
|
|
|
|
}.to change(Mdm::Module::Detail, :count).by(-module_detail_count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without migrated' do
|
|
|
|
it 'should not destroy Mdm::Module::Details' do
|
|
|
|
expect {
|
|
|
|
purge_all_module_details
|
|
|
|
}.to_not change(Mdm::Module::Detail, :count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-07 20:25:00 +00:00
|
|
|
context '#remove_module_details' do
|
|
|
|
def remove_module_details
|
|
|
|
db_manager.remove_module_details(mtype, refname)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:migrated) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:mtype) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_mtype
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:refname) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_refname
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_detail) do
|
|
|
|
FactoryGirl.create(
|
|
|
|
:mdm_module_detail
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:migrated => migrated)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with migrated' do
|
|
|
|
let(:migrated) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_detail) do
|
|
|
|
FactoryGirl.create(:mdm_module_detail)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with matching Mdm::Module::Detail' do
|
|
|
|
let(:mtype) do
|
|
|
|
module_detail.mtype
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:refname) do
|
|
|
|
module_detail.refname
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should destroy Mdm::Module::Detail' do
|
|
|
|
expect {
|
|
|
|
remove_module_details
|
|
|
|
}.to change(Mdm::Module::Detail, :count).by(-1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without matching Mdm::Module::Detail' do
|
|
|
|
it 'should not destroy Mdm::Module::Detail' do
|
|
|
|
expect {
|
|
|
|
remove_module_details
|
|
|
|
}.to_not change(Mdm::Module::Detail, :count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without migrated' do
|
|
|
|
it 'should not destroy Mdm::Module::Detail' do
|
|
|
|
expect {
|
|
|
|
remove_module_details
|
|
|
|
}.to_not change(Mdm::Module::Detail, :count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :report_artifact }
|
|
|
|
it { is_expected.to respond_to :report_auth }
|
|
|
|
it { is_expected.to respond_to :report_auth_info }
|
|
|
|
it { is_expected.to respond_to :report_client }
|
|
|
|
it { is_expected.to respond_to :report_cred }
|
|
|
|
it { is_expected.to respond_to :report_event }
|
|
|
|
it { is_expected.to respond_to :report_exploit }
|
|
|
|
it { is_expected.to respond_to :report_exploit_attempt }
|
|
|
|
it { is_expected.to respond_to :report_exploit_failure }
|
|
|
|
it { is_expected.to respond_to :report_exploit_success }
|
|
|
|
it { is_expected.to respond_to :report_host }
|
|
|
|
it { is_expected.to respond_to :report_host_details }
|
|
|
|
it { is_expected.to respond_to :report_host_tag }
|
|
|
|
it { is_expected.to respond_to :report_import_note }
|
|
|
|
it { is_expected.to respond_to :report_loot }
|
|
|
|
it { is_expected.to respond_to :report_note }
|
|
|
|
it { is_expected.to respond_to :report_report }
|
|
|
|
it { is_expected.to respond_to :report_service }
|
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context '#report_session' do
|
|
|
|
let(:options) do
|
|
|
|
{}
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:report_session) do
|
|
|
|
db_manager.report_session(options)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with active' do
|
|
|
|
let(:active) do
|
|
|
|
true
|
|
|
|
end
|
2013-04-19 15:11:33 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with :session' do
|
|
|
|
before(:each) do
|
|
|
|
options[:session] = session
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Msf::Session' do
|
|
|
|
let(:exploit_datastore) do
|
|
|
|
Msf::ModuleDataStore.new(module_instance).tap do |datastore|
|
|
|
|
datastore['ParentModule'] = parent_module_fullname
|
|
|
|
|
|
|
|
remote_port = rand(2 ** 16 - 1)
|
|
|
|
datastore['RPORT'] = remote_port
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:host) do
|
|
|
|
FactoryGirl.create(:mdm_host, :workspace => session_workspace)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_instance) do
|
|
|
|
name = 'multi/handler'
|
|
|
|
|
|
|
|
double(
|
|
|
|
'Msf::Module',
|
|
|
|
:fullname => "exploit/#{name}",
|
|
|
|
:framework => framework,
|
|
|
|
:name => name
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:options_workspace) do
|
|
|
|
FactoryGirl.create(:mdm_workspace)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_module_fullname) do
|
|
|
|
"exploit/#{parent_module_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_module_name) do
|
|
|
|
'windows/smb/ms08_067_netapi'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_path) do
|
|
|
|
Metasploit::Framework.root.join('modules').to_path
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:session) do
|
|
|
|
session_class.new.tap do |session|
|
|
|
|
session.exploit_datastore = exploit_datastore
|
|
|
|
session.info = 'Info'
|
|
|
|
session.platform = 'Platform'
|
|
|
|
session.session_host = host.address
|
|
|
|
session.sid = rand(100)
|
|
|
|
session.type = 'Session Type'
|
|
|
|
session.via_exploit = 'exploit/multi/handler'
|
|
|
|
session.via_payload = 'payload/single/windows/metsvc_bind_tcp'
|
|
|
|
session.workspace = session_workspace.name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:session_class) do
|
|
|
|
Class.new do
|
|
|
|
include Msf::Session
|
|
|
|
|
|
|
|
attr_accessor :datastore
|
|
|
|
attr_accessor :platform
|
|
|
|
attr_accessor :type
|
|
|
|
attr_accessor :via_exploit
|
|
|
|
attr_accessor :via_payload
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:session_workspace) do
|
|
|
|
FactoryGirl.create(:mdm_workspace)
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
reference_name = 'multi/handler'
|
|
|
|
path = File.join(parent_path, 'exploits', reference_name)
|
|
|
|
|
|
|
|
# fake cache data for exploit/multi/handler so it can be loaded
|
|
|
|
framework.modules.send(
|
|
|
|
:module_info_by_path=,
|
|
|
|
{
|
|
|
|
path =>
|
|
|
|
{
|
|
|
|
:parent_path => parent_path,
|
|
|
|
:reference_name => reference_name,
|
|
|
|
:type => 'exploit',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
FactoryGirl.create(
|
|
|
|
:mdm_module_detail,
|
|
|
|
:fullname => parent_module_fullname,
|
|
|
|
:name => parent_module_name
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :workspace' do
|
|
|
|
before(:each) do
|
|
|
|
options[:workspace] = options_workspace
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should not find workspace from session' do
|
|
|
|
db_manager.should_not_receive(:find_workspace)
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :workspace' do
|
|
|
|
it 'should find workspace from session' do
|
|
|
|
db_manager.should_receive(:find_workspace).with(session.workspace).and_call_original
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
2013-04-19 15:11:33 +00:00
|
|
|
|
|
|
|
it 'should pass session.workspace to #find_or_create_host' do
|
2013-09-30 18:47:53 +00:00
|
|
|
db_manager.should_receive(:find_or_create_host).with(
|
|
|
|
hash_including(
|
|
|
|
:workspace => session_workspace
|
|
|
|
)
|
|
|
|
).and_return(host)
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with workspace from either :workspace or session' do
|
|
|
|
it 'should pass normalized host from session as :host to #find_or_create_host' do
|
|
|
|
normalized_host = double('Normalized Host')
|
|
|
|
db_manager.stub(:normalize_host).with(session).and_return(normalized_host)
|
|
|
|
# stub report_vuln so its use of find_or_create_host and normalize_host doesn't interfere.
|
|
|
|
db_manager.stub(:report_vuln)
|
|
|
|
|
|
|
|
db_manager.should_receive(:find_or_create_host).with(
|
|
|
|
hash_including(
|
|
|
|
:host => normalized_host
|
|
|
|
)
|
|
|
|
).and_return(host)
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with session responds to arch' do
|
|
|
|
let(:arch) do
|
|
|
|
FactoryGirl.generate :mdm_host_arch
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
session.stub(:arch => arch)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should pass :arch to #find_or_create_host' do
|
|
|
|
db_manager.should_receive(:find_or_create_host).with(
|
|
|
|
hash_including(
|
|
|
|
:arch => arch
|
|
|
|
)
|
|
|
|
).and_call_original
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without session responds to arch' do
|
|
|
|
it 'should not pass :arch to #find_or_create_host' do
|
|
|
|
db_manager.should_receive(:find_or_create_host).with(
|
|
|
|
hash_excluding(
|
|
|
|
:arch
|
|
|
|
)
|
|
|
|
).and_call_original
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Session' do
|
|
|
|
expect {
|
|
|
|
report_session
|
|
|
|
}.to change(Mdm::Session, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it { should be_an Mdm::Session }
|
|
|
|
|
|
|
|
it 'should set session.db_record to created Mdm::Session' do
|
|
|
|
mdm_session = report_session
|
|
|
|
|
|
|
|
session.db_record.should == mdm_session
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with session.via_exploit' do
|
|
|
|
it 'should create session.via_exploit module' do
|
|
|
|
framework.modules.should_receive(:create).with(session.via_exploit).and_call_original
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create Mdm::Vuln' do
|
|
|
|
expect {
|
|
|
|
report_session
|
|
|
|
}.to change(Mdm::Vuln, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'created Mdm::Vuln' do
|
|
|
|
let(:mdm_session) do
|
|
|
|
Mdm::Session.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:rport) do
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
Timecop.freeze
|
|
|
|
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
|
|
|
after(:each) do
|
|
|
|
Timecop.return
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:vuln) do
|
|
|
|
Mdm::Vuln.last
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.host).to eq(Mdm::Host.last) }
|
|
|
|
it { expect(subject.refs).to eq([]) }
|
|
|
|
it { expect(subject.exploited_at).to be_within(1.second).of(Time.now.utc) }
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
context "with session.exploit_datastore['ParentModule']" do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.info).to eq("Exploited by #{parent_module_fullname} to create Session #{mdm_session.id}") }
|
|
|
|
it { expect(subject.name).to eq(parent_module_name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
let(:reference_name) do
|
|
|
|
'windows/smb/ms08_067_netapi'
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
path = File.join(
|
|
|
|
parent_path,
|
|
|
|
'exploits',
|
|
|
|
"#{reference_name}.rb"
|
|
|
|
)
|
|
|
|
type = 'exploit'
|
|
|
|
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
|
|
framework.modules.send(
|
|
|
|
:module_info_by_path=,
|
|
|
|
{
|
|
|
|
path =>
|
|
|
|
{
|
|
|
|
:parent_path => parent_path,
|
|
|
|
:reference_name => reference_name,
|
|
|
|
:type => type,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.info).to eq("Exploited by #{session.via_exploit} to create Session #{mdm_session.id}") }
|
|
|
|
it { expect(subject.name).to eq(reference_name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with RPORT' do
|
|
|
|
let(:rport) do
|
|
|
|
# use service.port instead of having service use rport so
|
|
|
|
# that service is forced to exist before call to
|
|
|
|
# report_service, which happens right after using rport in
|
|
|
|
# outer context's before(:each)
|
|
|
|
service.port
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:service) do
|
|
|
|
FactoryGirl.create(
|
|
|
|
:mdm_service,
|
|
|
|
:host => host
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.service).to eq(service) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without RPORT' do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.service).to be_nil }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'created Mdm::ExploitAttempt' do
|
|
|
|
let(:rport) do
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
Timecop.freeze
|
|
|
|
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
|
|
|
after(:each) do
|
|
|
|
Timecop.return
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:exploit_attempt) do
|
|
|
|
Mdm::ExploitAttempt.last
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.attempted_at).to be_within(1.second).of(Time.now.utc) }
|
2013-09-30 18:47:53 +00:00
|
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.session_id).to eq(Mdm::Session.last.id) }
|
|
|
|
it { expect(subject.exploited).to be_truthy }
|
2013-09-30 18:47:53 +00:00
|
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.vuln_id).to eq(Mdm::Vuln.last.id) }
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
context "with session.datastore['ParentModule']" do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.module).to eq(parent_module_fullname) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
before(:each) do
|
|
|
|
session.via_exploit = parent_module_fullname
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.module).to eq(session.via_exploit) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'returned Mdm::Session' do
|
|
|
|
before(:each) do
|
|
|
|
Timecop.freeze
|
|
|
|
end
|
|
|
|
|
|
|
|
after(:each) do
|
|
|
|
Timecop.return
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:mdm_session) do
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Ensure session has attributes present so its on mdm_session are
|
|
|
|
# not just comparing nils.
|
|
|
|
#
|
|
|
|
|
|
|
|
it 'should have session.info present' do
|
|
|
|
session.info.should be_present
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have session.sid present' do
|
|
|
|
session.sid.should be_present
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have session.platform present' do
|
|
|
|
session.platform.should be_present
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have session.type present' do
|
|
|
|
session.type.should be_present
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have session.via_exploit present' do
|
|
|
|
session.via_exploit.should be_present
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should have session.via_payload present' do
|
|
|
|
session.via_exploit.should be_present
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.datastore).to eq(session.exploit_datastore.to_h) }
|
|
|
|
it { expect(subject.desc).to eq(session.info) }
|
|
|
|
it { expect(subject.host_id).to eq(Mdm::Host.last.id) }
|
|
|
|
it { expect(subject.last_seen).to be_within(1.second).of(Time.now.utc) }
|
|
|
|
it { expect(subject.local_id).to eq(session.sid) }
|
|
|
|
it { expect(subject.opened_at).to be_within(1.second).of(Time.now.utc) }
|
|
|
|
it { expect(subject.platform).to eq(session.platform) }
|
|
|
|
it { expect(subject.routes).to eq([]) }
|
|
|
|
it { expect(subject.stype).to eq(session.type) }
|
|
|
|
it { expect(subject.via_payload).to eq(session.via_payload) }
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
it "should have session.via_exploit of 'exploit/multi/handler'" do
|
|
|
|
session.via_exploit.should == 'exploit/multi/handler'
|
|
|
|
end
|
|
|
|
|
|
|
|
context "with session.exploit_datastore['ParentModule']" do
|
|
|
|
it "should have session.exploit_datastore['ParentModule']" do
|
|
|
|
session.exploit_datastore['ParentModule'].should_not be_nil
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.via_exploit).to eq(parent_module_fullname) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
|
|
before(:each) do
|
|
|
|
reference_name = 'windows/smb/ms08_067_netapi'
|
|
|
|
path = File.join(
|
|
|
|
parent_path,
|
|
|
|
'exploits',
|
|
|
|
"#{reference_name}.rb"
|
|
|
|
)
|
|
|
|
type = 'exploit'
|
|
|
|
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
|
|
framework.modules.send(
|
|
|
|
:module_info_by_path=,
|
|
|
|
{
|
|
|
|
path =>
|
|
|
|
{
|
|
|
|
:parent_path => parent_path,
|
|
|
|
:reference_name => reference_name,
|
|
|
|
:type => type,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should not have session.via_exploit of 'exploit/multi/handler'" do
|
|
|
|
session.via_exploit.should_not == 'exploit/multi/handler'
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.via_exploit).to eq(session.via_exploit) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without Msf::Session' do
|
|
|
|
let(:session) do
|
|
|
|
double('Not a Msf::Session')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should raise ArgumentError' do
|
|
|
|
expect {
|
|
|
|
report_session
|
|
|
|
}.to raise_error(ArgumentError, "Invalid :session, expected Msf::Session")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :session' do
|
|
|
|
context 'with :host' do
|
|
|
|
before(:each) do
|
|
|
|
options[:host] = host
|
|
|
|
end
|
2013-04-19 15:11:33 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with Mdm::Host' do
|
|
|
|
let(:host) do
|
|
|
|
FactoryGirl.create(:mdm_host)
|
2013-04-19 15:11:33 +00:00
|
|
|
end
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
context 'created Mdm::Session' do
|
|
|
|
let(:closed_at) do
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:close_reason) do
|
|
|
|
'Closed because...'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:description) do
|
|
|
|
'Session Description'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:exploit_full_name) do
|
|
|
|
'exploit/windows/smb/ms08_067_netapi'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:last_seen) do
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:opened_at) do
|
|
|
|
Time.now.utc - 5.minutes
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:payload_full_name) do
|
|
|
|
'payload/singles/windows/metsvc_reverse_tcp'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:platform) do
|
|
|
|
'Host Platform'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:routes) do
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:session_type) do
|
|
|
|
'Session Type'
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
options[:closed_at] = closed_at
|
|
|
|
options[:close_reason] = close_reason
|
|
|
|
options[:desc] = description
|
|
|
|
options[:last_seen] = last_seen
|
|
|
|
options[:opened_at] = opened_at
|
|
|
|
options[:platform] = platform
|
|
|
|
options[:routes] = routes
|
|
|
|
options[:stype] = session_type
|
|
|
|
options[:via_payload] = payload_full_name
|
|
|
|
options[:via_exploit] = exploit_full_name
|
|
|
|
end
|
|
|
|
|
|
|
|
subject(:mdm_session) do
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.close_reason).to eq(close_reason) }
|
|
|
|
it { expect(subject.desc).to eq(description) }
|
|
|
|
it { expect(subject.host).to eq(host) }
|
|
|
|
it { expect(subject.platform).to eq(platform) }
|
|
|
|
it { expect(subject.stype).to eq(session_type) }
|
|
|
|
it { expect(subject.via_exploit).to eq(exploit_full_name) }
|
|
|
|
it { expect(subject.via_payload).to eq(payload_full_name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
context 'with :last_seen' do
|
|
|
|
let(:last_seen) do
|
|
|
|
opened_at
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.last_seen).to eq(last_seen) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :closed_at' do
|
|
|
|
let(:closed_at) do
|
|
|
|
opened_at + 1.minute
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.closed_at).to eq(closed_at) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :closed_at' do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.closed_at).to be_nil }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :last_seen' do
|
|
|
|
context 'with :closed_at' do
|
|
|
|
let(:closed_at) do
|
|
|
|
opened_at + 1.minute
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.last_seen).to eq(closed_at) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :closed_at' do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.last_seen).to be_nil }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :routes' do
|
|
|
|
let(:routes) do
|
|
|
|
FactoryGirl.build_list(
|
|
|
|
:mdm_route,
|
|
|
|
1,
|
|
|
|
:session => nil
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.routes).to eq(routes) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :routes' do
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.routes).to eq([]) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without Mdm::Host' do
|
|
|
|
let(:host) do
|
|
|
|
'192.168.0.1'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should raise ArgumentError' do
|
|
|
|
expect {
|
|
|
|
report_session
|
|
|
|
}.to raise_error(ArgumentError, "Invalid :host, expected Host object")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without :host' do
|
|
|
|
it 'should raise ArgumentError' do
|
|
|
|
expect {
|
|
|
|
report_session
|
|
|
|
}.to raise_error(ArgumentError)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without active' do
|
|
|
|
let(:active) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
it { should be_nil }
|
|
|
|
|
|
|
|
it 'should not create a connection' do
|
2014-05-12 20:03:51 +00:00
|
|
|
ActiveRecord::Base.connection_pool.should_not_receive(:with_connection)
|
2013-09-30 18:47:53 +00:00
|
|
|
|
|
|
|
report_session
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :report_session_event }
|
|
|
|
it { is_expected.to respond_to :report_session_route }
|
|
|
|
it { is_expected.to respond_to :report_session_route_remove }
|
|
|
|
it { is_expected.to respond_to :report_task }
|
|
|
|
it { is_expected.to respond_to :report_vuln }
|
|
|
|
it { is_expected.to respond_to :report_vuln_attempt }
|
|
|
|
it { is_expected.to respond_to :report_vuln_details }
|
|
|
|
it { is_expected.to respond_to :report_web_form }
|
|
|
|
it { is_expected.to respond_to :report_web_page }
|
|
|
|
it { is_expected.to respond_to :report_web_site }
|
|
|
|
it { is_expected.to respond_to :report_web_vuln }
|
|
|
|
it { is_expected.to respond_to :reports }
|
|
|
|
it { is_expected.to respond_to :request_distinct_targets }
|
|
|
|
it { is_expected.to respond_to :request_sql }
|
|
|
|
it { is_expected.to respond_to :requests }
|
|
|
|
it { is_expected.to respond_to :rexmlify }
|
|
|
|
it { is_expected.to respond_to :rfc3330_reserved }
|
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context '#search_modules' do
|
2013-04-26 18:14:38 +00:00
|
|
|
subject(:search_modules) do
|
|
|
|
db_manager.search_modules(search_string)
|
|
|
|
end
|
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
let(:module_details) do
|
|
|
|
search_modules.to_a
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with app keyword' do
|
|
|
|
let(:search_string) do
|
|
|
|
"app:#{app}"
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
Mdm::Module::Detail::STANCES.each do |stance|
|
|
|
|
FactoryGirl.create(:mdm_module_detail, :stance => stance)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with client' do
|
|
|
|
let(:app) do
|
|
|
|
'client'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should match Mdm::Module::Detail#stance 'passive'" do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.stance == 'passive'
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with server' do
|
|
|
|
let(:app) do
|
|
|
|
'server'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "should match Mdm::Module::Detail#stance 'aggressive'" do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.stance == 'aggressive'
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with author keyword' do
|
|
|
|
let(:search_string) do
|
2013-04-25 14:46:53 +00:00
|
|
|
# us inspect so strings with spaces are quoted correctly
|
2013-09-30 18:47:53 +00:00
|
|
|
"author:#{author}"
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_authors) do
|
|
|
|
FactoryGirl.create_list(:mdm_module_author, 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:target_module_author) do
|
|
|
|
module_authors.first
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Author#email' do
|
|
|
|
let(:author) do
|
|
|
|
target_module_author.email
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Author#email' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.authors.any? { |module_author|
|
|
|
|
module_author.email == target_module_author.email
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Author#name' do
|
2013-04-25 14:46:53 +00:00
|
|
|
let(:author) do
|
|
|
|
# use inspect to quote space in name
|
|
|
|
target_module_author.name.inspect
|
|
|
|
end
|
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it 'should match Mdm::Module::Author#name' do
|
|
|
|
module_details.count.should > 0
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.authors.any? { |module_author|
|
|
|
|
module_author.name == target_module_author.name
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword', :bid
|
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword', :cve
|
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword', :edb
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with name keyword' do
|
|
|
|
let(:search_string) do
|
|
|
|
"name:#{name}"
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
let!(:existing_module_details) do
|
|
|
|
FactoryGirl.create_list(:mdm_module_detail, 2)
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
let(:target_module_detail) do
|
|
|
|
existing_module_details.first
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with Mdm::Module::Detail#fullname' do
|
|
|
|
let(:name) do
|
|
|
|
target_module_detail.fullname
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it 'should match Mdm::Module::Detail#fullname' do
|
|
|
|
module_details.count.should > 0
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.fullname == target_module_detail.fullname
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with Mdm::Module::Detail#name' do
|
|
|
|
let(:name) do
|
2013-04-26 18:14:38 +00:00
|
|
|
# use inspect so spaces are inside quotes
|
2013-09-30 18:47:53 +00:00
|
|
|
target_module_detail.name.inspect
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it 'should match Mdm::Module::Detail#name' do
|
|
|
|
module_details.count.should > 0
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.name == target_module_detail.name
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Platform#name or Mdm::Module::Target#name keyword', :os
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Ref#name keyword', :osvdb
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager#search_modules Mdm::Module::Platform#name or Mdm::Module::Target#name keyword', :platform
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context 'with ref keyword' do
|
|
|
|
let(:ref) do
|
|
|
|
FactoryGirl.generate :mdm_module_ref_name
|
|
|
|
end
|
2013-04-25 14:46:53 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
let(:search_string) do
|
2013-04-26 18:14:38 +00:00
|
|
|
# use inspect to quote spaces in string
|
2013-09-30 18:47:53 +00:00
|
|
|
"ref:#{ref.inspect}"
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_ref) do
|
|
|
|
FactoryGirl.create(:mdm_module_ref)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Ref#name' do
|
|
|
|
let(:ref) do
|
|
|
|
module_ref.name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Ref#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.refs.any? { |module_ref|
|
|
|
|
module_ref.name == ref
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without Mdm::Module::Ref#name' do
|
|
|
|
it 'should not match Mdm::Module::Ref#name' do
|
|
|
|
module_details.count.should == 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with type keyword' do
|
|
|
|
let(:type) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_mtype
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:search_string) do
|
|
|
|
"type:#{type}"
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:target_module_detail) do
|
|
|
|
all_module_details.first
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:all_module_details) do
|
|
|
|
FactoryGirl.create_list(:mdm_module_detail, 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Ref#name' do
|
|
|
|
let(:type) do
|
|
|
|
target_module_detail.mtype
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Detail#mtype' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.mtype == type
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without Mdm::Module::Detail#mtype' do
|
|
|
|
it 'should not match Mdm::Module::Detail#mtype' do
|
|
|
|
module_details.count.should == 0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without keyword' do
|
|
|
|
context 'with Mdm::Module::Action#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_action.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_action) do
|
|
|
|
FactoryGirl.create(:mdm_module_action)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Action#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.actions.any? { |module_action|
|
|
|
|
module_action.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Arch#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_arch.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_arch) do
|
|
|
|
FactoryGirl.create(:mdm_module_arch)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Arch#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.archs.any? { |module_arch|
|
|
|
|
module_arch.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Author#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_author.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_author) do
|
|
|
|
FactoryGirl.create(:mdm_module_author)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Author#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.authors.any? { |module_author|
|
|
|
|
module_author.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Detail' do
|
|
|
|
let(:target_module_detail) do
|
|
|
|
all_module_details.first
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:all_module_details) do
|
|
|
|
FactoryGirl.create_list(:mdm_module_detail, 3)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with #description' do
|
|
|
|
let(:search_string) do
|
2013-04-26 18:14:38 +00:00
|
|
|
# use inspect to quote spaces in string
|
2013-09-30 18:47:53 +00:00
|
|
|
target_module_detail.description.inspect
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Detail#description' do
|
|
|
|
module_details.count.should == 1
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.description == target_module_detail.description
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with #fullname' do
|
|
|
|
let(:search_string) do
|
|
|
|
target_module_detail.fullname
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Detail#fullname' do
|
|
|
|
module_details.count.should == 1
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.fullname == search_string
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with #name' do
|
|
|
|
let(:search_string) do
|
2013-04-26 18:14:38 +00:00
|
|
|
# use inspect to quote spaces in string
|
2013-09-30 18:47:53 +00:00
|
|
|
target_module_detail.name.inspect
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Detail#name' do
|
|
|
|
module_details.count.should == 1
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.name == target_module_detail.name
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Platform#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_platform.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_platform) do
|
|
|
|
FactoryGirl.create(:mdm_module_platform)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Platform#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.platforms.any? { |module_platform|
|
|
|
|
module_platform.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Ref#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_ref.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_ref) do
|
|
|
|
FactoryGirl.create(:mdm_module_ref)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Ref#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.refs.any? { |module_ref|
|
|
|
|
module_ref.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Target#name' do
|
|
|
|
let(:search_string) do
|
|
|
|
module_target.name
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_target) do
|
|
|
|
FactoryGirl.create(:mdm_module_target)
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should match Mdm::Module::Target#name' do
|
|
|
|
module_details.count.should > 0
|
|
|
|
|
|
|
|
module_details.all? { |module_detail|
|
|
|
|
module_detail.targets.any? { |module_target|
|
|
|
|
module_target.name == search_string
|
|
|
|
}
|
2014-08-25 23:13:38 +00:00
|
|
|
}.should be_truthy
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :selected_host }
|
|
|
|
it { is_expected.to respond_to :selected_id }
|
|
|
|
it { is_expected.to respond_to :selected_port }
|
|
|
|
it { is_expected.to respond_to :selected_ssl }
|
|
|
|
it { is_expected.to respond_to :selected_wmap_target }
|
|
|
|
it { is_expected.to respond_to :service_name_map }
|
|
|
|
it { is_expected.to respond_to :services }
|
|
|
|
it { is_expected.to respond_to :sql_query }
|
|
|
|
it { is_expected.to respond_to :target_requests }
|
|
|
|
it { is_expected.to respond_to :targets }
|
|
|
|
it { is_expected.to respond_to :tasks }
|
|
|
|
it { is_expected.to respond_to :unserialize_object }
|
2014-10-07 20:49:42 +00:00
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context '#update_all_module_details' do
|
|
|
|
def update_all_module_details
|
|
|
|
db_manager.update_all_module_details
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:migrated) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:migrated => migrated)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with migrated' do
|
|
|
|
let(:migrated) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:modules_caching) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:modules_caching => modules_caching)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with modules_caching' do
|
|
|
|
it 'should not update module details' do
|
|
|
|
db_manager.should_not_receive(:update_module_details)
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without modules_caching' do
|
|
|
|
let(:modules_caching) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2014-06-19 21:24:53 +00:00
|
|
|
it 'should set framework.cache_thread to current thread and then nil' do
|
2013-09-30 18:47:53 +00:00
|
|
|
framework.should_receive(:cache_thread=).with(Thread.current).ordered
|
|
|
|
framework.should_receive(:cache_thread=).with(nil).ordered
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
|
2014-06-19 21:24:53 +00:00
|
|
|
it 'should set modules_cached to false and then true' do
|
2013-09-30 18:47:53 +00:00
|
|
|
db_manager.should_receive(:modules_cached=).with(false).ordered
|
|
|
|
db_manager.should_receive(:modules_cached=).with(true).ordered
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
|
2014-06-19 21:24:53 +00:00
|
|
|
it 'should set modules_caching to true and then false' do
|
2013-09-30 18:47:53 +00:00
|
|
|
db_manager.should_receive(:modules_caching=).with(true).ordered
|
|
|
|
db_manager.should_receive(:modules_caching=).with(false).ordered
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with Mdm::Module::Details' do
|
|
|
|
let(:module_pathname) do
|
|
|
|
parent_pathname.join(
|
|
|
|
'exploits',
|
|
|
|
"#{reference_name}.rb"
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:modification_time) do
|
|
|
|
module_pathname.mtime
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_pathname) do
|
|
|
|
Metasploit::Framework.root.join('modules')
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:reference_name) do
|
|
|
|
'windows/smb/ms08_067_netapi'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:type) do
|
|
|
|
'exploit'
|
|
|
|
end
|
|
|
|
|
|
|
|
let!(:module_detail) do
|
|
|
|
# needs to reference a real module so that it can be loaded
|
|
|
|
FactoryGirl.create(
|
|
|
|
:mdm_module_detail,
|
|
|
|
:file => module_pathname.to_path,
|
|
|
|
:mtime => modification_time,
|
|
|
|
:mtype => type,
|
|
|
|
:ready => ready,
|
|
|
|
:refname => reference_name
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
context '#ready' do
|
|
|
|
context 'false' do
|
|
|
|
let(:ready) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_all_module_details refresh'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'true' do
|
|
|
|
let(:ready) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with existing Mdm::Module::Detail#file' do
|
|
|
|
context 'with same Mdm::Module::Detail#mtime and File.mtime' do
|
|
|
|
it 'should not update module details' do
|
|
|
|
db_manager.should_not_receive(:update_module_details)
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without same Mdm::Module::Detail#mtime and File.mtime' do
|
|
|
|
let(:modification_time) do
|
|
|
|
# +1 as rand can return 0 and the time must be different for
|
|
|
|
# this context.
|
|
|
|
super() - (rand(1.day) + 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_all_module_details refresh'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Emulates a module being removed or renamed
|
|
|
|
context 'without existing Mdm::Module::Detail#file' do
|
|
|
|
# have to compute modification manually since the
|
|
|
|
# `module_pathname` refers to a non-existent file and
|
|
|
|
# `module_pathname.mtime` would error.
|
|
|
|
let(:modification_time) do
|
|
|
|
Time.now.utc - 1.day
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_pathname) do
|
|
|
|
parent_pathname.join('exploits', 'deleted.rb')
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should not update module details' do
|
|
|
|
db_manager.should_not_receive(:update_module_details)
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without migrated' do
|
|
|
|
it 'should not update module details' do
|
|
|
|
db_manager.should_not_receive(:update_module_details)
|
|
|
|
|
|
|
|
update_all_module_details
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :update_host_via_sysinfo }
|
|
|
|
|
2013-09-30 18:47:53 +00:00
|
|
|
context '#update_module_details' do
|
|
|
|
def update_module_details
|
|
|
|
db_manager.update_module_details(module_instance)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:loader) do
|
|
|
|
loader = framework.modules.send(:loaders).find { |loader|
|
|
|
|
loader.loadable?(parent_path)
|
|
|
|
}
|
|
|
|
|
|
|
|
# Override load_error so that rspec will print it instead of going to framework log
|
|
|
|
def loader.load_error(module_path, error)
|
|
|
|
raise error
|
|
|
|
end
|
|
|
|
|
|
|
|
loader
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:migrated) do
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_instance) do
|
|
|
|
# make sure the module is loaded into the module_set
|
|
|
|
loaded = loader.load_module(parent_path, module_type, module_reference_name)
|
|
|
|
|
|
|
|
unless loaded
|
|
|
|
module_path = loader.module_path(parent_path, type, module_reference_name)
|
|
|
|
|
|
|
|
fail "#{description} failed to load: #{module_path}"
|
|
|
|
end
|
|
|
|
|
|
|
|
module_set.create(module_reference_name)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_set) do
|
|
|
|
framework.modules.module_set(module_type)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_type) do
|
|
|
|
'exploit'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_reference_name) do
|
|
|
|
'windows/smb/ms08_067_netapi'
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_path) do
|
|
|
|
parent_pathname.to_path
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:parent_pathname) do
|
|
|
|
Metasploit::Framework.root.join('modules')
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:type_directory) do
|
|
|
|
'exploits'
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(:migrated => migrated)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with migrated' do
|
|
|
|
let(:migrated) do
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should call module_to_details_hash to get Mdm::Module::Detail attributes and association attributes' do
|
|
|
|
db_manager.should_receive(:module_to_details_hash).and_call_original
|
|
|
|
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Detail' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Detail, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
context 'module_to_details_hash' do
|
|
|
|
let(:module_to_details_hash) do
|
|
|
|
{
|
|
|
|
:mtype => module_type,
|
|
|
|
:privileged => privileged,
|
|
|
|
:rank => rank,
|
|
|
|
:refname => module_reference_name,
|
|
|
|
:stance => stance
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:privileged) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_privileged
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:rank) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_rank
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:stance) do
|
|
|
|
FactoryGirl.generate :mdm_module_detail_stance
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
db_manager.stub(
|
|
|
|
:module_to_details_hash
|
|
|
|
).with(
|
|
|
|
module_instance
|
|
|
|
).and_return(
|
|
|
|
module_to_details_hash
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Detail' do
|
|
|
|
subject(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.mtype).to eq(module_type) }
|
|
|
|
it { expect(subject.privileged).to eq(privileged) }
|
|
|
|
it { expect(subject.rank).to eq(rank) }
|
|
|
|
it { expect(subject.ready).to be_truthy }
|
|
|
|
it { expect(subject.refname).to eq(module_reference_name) }
|
|
|
|
it { expect(subject.stance).to eq(stance) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :bits' do
|
|
|
|
let(:bits) do
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
module_to_details_hash[:bits] = bits
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :action' do
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_action_name
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:action,
|
|
|
|
{
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Action' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Action, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Action' do
|
|
|
|
subject(:module_action) do
|
|
|
|
module_detail.actions.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.name).to eq(name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :arch' do
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_arch_name
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:arch,
|
|
|
|
{
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Arch' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Arch, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Arch' do
|
|
|
|
subject(:module_arch) do
|
|
|
|
module_detail.archs.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.name).to eq(name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :author' do
|
|
|
|
let(:email) do
|
|
|
|
FactoryGirl.generate :mdm_module_author_email
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_author_name
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:author,
|
|
|
|
{
|
|
|
|
:email => email,
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Author' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Author, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Author' do
|
|
|
|
subject(:module_author) do
|
|
|
|
module_detail.authors.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.name).to eq(name) }
|
|
|
|
it { expect(subject.email).to eq(email) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :platform' do
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:platform,
|
|
|
|
{
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_platform_name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Platform' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Platform, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Platform' do
|
|
|
|
subject(:module_platform) do
|
|
|
|
module_detail.platforms.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.name).to eq(name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :ref' do
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:ref,
|
|
|
|
{
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_ref_name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Ref' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Ref, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Ref' do
|
|
|
|
subject(:module_ref) do
|
|
|
|
module_detail.refs.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.name).to eq(name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'with :target' do
|
|
|
|
let(:bits) do
|
|
|
|
super() << [
|
|
|
|
:target,
|
|
|
|
{
|
|
|
|
:index => index,
|
|
|
|
:name => name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:index) do
|
|
|
|
FactoryGirl.generate :mdm_module_target_index
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:name) do
|
|
|
|
FactoryGirl.generate :mdm_module_target_name
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should create an Mdm::Module::Target' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to change(Mdm::Module::Target, :count).by(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'Mdm::Module::Target' do
|
|
|
|
subject(:module_target) do
|
|
|
|
module_detail.targets.last
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:module_detail) do
|
|
|
|
Mdm::Module::Detail.last
|
|
|
|
end
|
|
|
|
|
|
|
|
before(:each) do
|
|
|
|
update_module_details
|
|
|
|
end
|
|
|
|
|
2014-09-02 17:46:50 +00:00
|
|
|
it { expect(subject.index).to eq(index) }
|
|
|
|
it { expect(subject.name).to eq(name) }
|
2013-09-30 18:47:53 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_module_details with module',
|
|
|
|
:reference_name => 'admin/2wire/xslt_password_reset',
|
|
|
|
:type => 'auxiliary'
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_module_details with module',
|
|
|
|
:reference_name => 'generic/none',
|
|
|
|
:type => 'encoder'
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_module_details with module',
|
|
|
|
:reference_name => 'windows/smb/ms08_067_netapi',
|
|
|
|
:type => 'exploit'
|
|
|
|
|
|
|
|
it_should_behave_like 'Msf::DBManager#update_module_details with module',
|
|
|
|
:reference_name => 'x64/simple',
|
|
|
|
:type => 'nop'
|
|
|
|
|
|
|
|
# @todo determine how to load a single payload to test payload type outside of msfconsole
|
2013-05-17 16:53:08 +00:00
|
|
|
|
2014-08-26 20:24:08 +00:00
|
|
|
it_should_behave_like 'Msf::DBManager#update_module_details with module',
|
2013-09-30 18:47:53 +00:00
|
|
|
:reference_name => 'windows/escalate/screen_unlock',
|
|
|
|
:type => 'post'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'without migrated' do
|
|
|
|
it 'should not create an Mdm::Module::Detail' do
|
|
|
|
expect {
|
|
|
|
update_module_details
|
|
|
|
}.to_not change(Mdm::Module::Detail, :count)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2014-10-07 20:49:42 +00:00
|
|
|
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :update_vuln_details }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :usable }
|
|
|
|
it { is_expected.to respond_to :usable= }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :validate_import_file }
|
|
|
|
it { is_expected.to respond_to :validate_ips }
|
|
|
|
it { is_expected.to respond_to :vulns }
|
2014-10-07 20:49:42 +00:00
|
|
|
it { is_expected.to respond_to :warn_about_rubies }
|
|
|
|
it { is_expected.to respond_to :workspace }
|
|
|
|
it { is_expected.to respond_to :workspace= }
|
2014-10-08 16:07:15 +00:00
|
|
|
it { is_expected.to respond_to :workspaces }
|
2013-04-01 21:06:40 +00:00
|
|
|
end
|