metasploit-runner 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/bin/exploit +13 -1
- data/lib/MetasploitPenTestScript/version.rb +1 -1
- data/lib/metasploit/constants.rb +2 -0
- data/lib/metasploit/exploit.rb +35 -11
- data/lib/metasploit/exploit_run_description.rb +25 -21
- data/spec/exploit_run_description_spec.rb +16 -11
- data/spec/exploit_spec.rb +349 -166
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73317964938841513e2416cfcc75a4ca3298d314
|
4
|
+
data.tar.gz: 735c44a012cf169362a164f20174eec6f89aa9c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 271fe1d83224bca7e1ed3a4e49e12c0940eaf402309c968d90c16789ea35f457f22f00e390bc3237703073a837193293c0788852ce2365b8f64920b248b70d91
|
7
|
+
data.tar.gz: d84c7f0fb8defdab950e6e550c89013ed84319f5919e0ba09489367cc4ec3ddcc77b8b0983a9f9af4dd0f662772424ec8a9ae4bcec0d793dec2e5df539ee5eae
|
data/README.md
CHANGED
@@ -29,15 +29,15 @@ This gem allows you to specify the Metasploit Connection URL, Metasploit Connect
|
|
29
29
|
The nexpose_console_name is optional, if you specify a nexpose console name it will use the workspace_name, and nexpose console name to pull scan data from a nexpose console.
|
30
30
|
IMPORTANT: Your "Site Name" in Nexpose, must match your "Workspace" name in Metasploit and you must add your Nexpose Console to Metasploit for this to work properly.
|
31
31
|
|
32
|
-
$ exploit "connection_url" "port" "uri" "use_ssl" "token" "workspace_name" "nexpose_console_name" "device_ip_to_scan" "os_filter" "module_filter"
|
32
|
+
$ exploit "connection_url" "port" "uri" "use_ssl" "token" "workspace_name" "nexpose_console_name" "device_ip_to_scan" "os_filter" "module_filter" "report_type"
|
33
33
|
|
34
34
|
Example WITH Nexpose Console Integration:
|
35
35
|
|
36
|
-
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "<true/false>" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "<true/false>" "exploit/windows/smb/psexec"
|
36
|
+
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "<true/false>" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "<true/false>" "exploit/windows/smb/psexec" "fisma"
|
37
37
|
|
38
38
|
Example WITHOUT Nexpose Console Integration:
|
39
39
|
|
40
|
-
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "" "10.0.0.1" "false" "exploit/windows/smb/psexec"
|
40
|
+
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "" "10.0.0.1" "false" "exploit/windows/smb/psexec" "fisma"
|
41
41
|
|
42
42
|
Additionally, an os filter may be passed in to determine which modules will be ran during an exploit. The os filter parameter will default to false (all modules will run) if you do not pass a value.
|
43
43
|
|
@@ -45,7 +45,7 @@ Additionally, an os filter may be passed in to determine which modules will be r
|
|
45
45
|
|
46
46
|
Example WITH OS Filter:
|
47
47
|
|
48
|
-
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "true"
|
48
|
+
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "true" "" "fisma"
|
49
49
|
|
50
50
|
The if you do not pass the following options they will default to the respective values:
|
51
51
|
|
@@ -56,7 +56,7 @@ The if you do not pass the following options they will default to the respective
|
|
56
56
|
|
57
57
|
Example using the defaults:
|
58
58
|
|
59
|
-
$ exploit "sploit.mydomain.com" "" "" "" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "" ""
|
59
|
+
$ exploit "sploit.mydomain.com" "" "" "" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "" "" ""
|
60
60
|
|
61
61
|
## Contributing
|
62
62
|
|
data/bin/exploit
CHANGED
@@ -3,4 +3,16 @@
|
|
3
3
|
require 'metasploit/exploit'
|
4
4
|
|
5
5
|
$stdout.sync = true
|
6
|
-
Metasploit::Exploit.start
|
6
|
+
Metasploit::Exploit.start({
|
7
|
+
'connection_url' => ARGV[0],
|
8
|
+
'port' => ARGV[1],
|
9
|
+
'uri' => ARGV[2],
|
10
|
+
'use_ssl' => ARGV[3],
|
11
|
+
'token' => ARGV[4],
|
12
|
+
'workspace_name' => ARGV[5],
|
13
|
+
'nexpose_console_name' => ARGV[6],
|
14
|
+
'device_ip_to_scan' => ARGV[7],
|
15
|
+
'use_os_filter' => ARGV[8],
|
16
|
+
'module_filter' => ARGV[9],
|
17
|
+
'report_type' => ARGV[10]
|
18
|
+
})
|
data/lib/metasploit/constants.rb
CHANGED
@@ -16,10 +16,12 @@ module CONSTANTS
|
|
16
16
|
SCANNING_MESSAGE = '[*] Scanning all your things with WebScan...'
|
17
17
|
AUDIT_MESSAGE = '[*] Performing web audit...'
|
18
18
|
EXPLOIT_MESSAGE = '[*] Exploiting all your things...'
|
19
|
+
REPORT_MESSAGE = '[*} Generating report...'
|
19
20
|
REQUIRED_WORKSPACE_MESSAGE = 'PWNED! Workspace Name is required'
|
20
21
|
SKIPPING_IMPORT_MESSAGE = '[*] Nexpose Console option was not passed, skipping Nexpose Import'
|
21
22
|
USING_OS_FILTER_MESSAGE = '[*] The OS Filter is set to TRUE so we are limiting the modules to just the ones applicable to this Operating System'
|
22
23
|
NO_OS_FILTER = '[*] We did not receive an option for the OS Filter or you set it to FALSE, either way we are backing the truck up and using all modules'
|
23
24
|
USING_MODULE_FILTER = '[*] Filtering exploits based on your desired modules'
|
24
25
|
NO_MODULE_FILTER = '[*] Not filtering any modules'
|
26
|
+
NO_REPORT_TYPE_MESSAGE = 'No report type specified - skipping report generation'
|
25
27
|
end
|
data/lib/metasploit/exploit.rb
CHANGED
@@ -4,17 +4,9 @@ require 'metasploit/exploit_run_description'
|
|
4
4
|
|
5
5
|
module Metasploit
|
6
6
|
module Exploit
|
7
|
-
def Exploit.start(
|
8
|
-
|
9
|
-
|
10
|
-
use_ssl,
|
11
|
-
token,
|
12
|
-
workspace_name,
|
13
|
-
nexpose_console_name,
|
14
|
-
device_ip_to_scan,
|
15
|
-
use_os_filter,
|
16
|
-
module_filter)
|
17
|
-
run_details = ExploitRunDescription.new connection_url, port, uri, use_ssl, token, workspace_name, nexpose_console_name, device_ip_to_scan, use_os_filter, module_filter
|
7
|
+
def Exploit.start(options)
|
8
|
+
|
9
|
+
run_details = ExploitRunDescription.new(options)
|
18
10
|
run_details.verify
|
19
11
|
|
20
12
|
rpc_client = get_new_metasploit_rpc_connection(run_details)
|
@@ -28,6 +20,8 @@ module Metasploit
|
|
28
20
|
do_metasploit_audit(rpc_client, run_details)
|
29
21
|
|
30
22
|
do_metasploit_exploit(rpc_client, run_details)
|
23
|
+
|
24
|
+
do_metasploit_report(rpc_client, run_details)
|
31
25
|
end
|
32
26
|
|
33
27
|
private
|
@@ -83,6 +77,18 @@ module Metasploit
|
|
83
77
|
wait_for_task_to_stop_running(rpc_client, CONSTANTS::EXPLOIT_MESSAGE, sploit['task_id'])
|
84
78
|
end
|
85
79
|
|
80
|
+
def self.do_metasploit_report(rpc_client, run_details)
|
81
|
+
if run_details.report_type.length > 0
|
82
|
+
puts "Generating a #{run_details.report_type} Report"
|
83
|
+
|
84
|
+
report = rpc_client.call('pro.start_report', run_details.get_report_options)
|
85
|
+
|
86
|
+
self.write_report_after_generation(rpc_client, run_details, report['report_id'])
|
87
|
+
else
|
88
|
+
puts CONSTANTS::NO_REPORT_TYPE_MESSAGE
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
86
92
|
def self.wait_for_task_to_stop_running(rpc_client, status_message, task_id)
|
87
93
|
loop do
|
88
94
|
sleep(3)
|
@@ -97,5 +103,23 @@ module Metasploit
|
|
97
103
|
break if status != CONSTANTS::RUNNING_IMPORT_STATUS
|
98
104
|
end
|
99
105
|
end
|
106
|
+
|
107
|
+
def self.write_report_after_generation(rpc_client, run_details, report_id)
|
108
|
+
(1..100).each do
|
109
|
+
download = rpc_client.call('pro.report_download', report_id)
|
110
|
+
if download && download['report_artifacts'] && download['report_artifacts'].length > 0
|
111
|
+
download['report_artifacts'].each_with_index do |artifact, index|
|
112
|
+
File.open("#{run_details.workspace_name}_#{index}#{File.extname(artifact['file_path'])}", "wb") do |fd|
|
113
|
+
fd.write(artifact['data'])
|
114
|
+
end
|
115
|
+
puts "Report File #{index} Written"
|
116
|
+
end
|
117
|
+
break
|
118
|
+
else
|
119
|
+
puts "Waiting for report to generate"
|
120
|
+
sleep(3)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
100
124
|
end
|
101
125
|
end
|
@@ -8,7 +8,8 @@ class ExploitRunDescription
|
|
8
8
|
:nexpose_console_name,
|
9
9
|
:device_ip_to_scan,
|
10
10
|
:use_os_filter,
|
11
|
-
:module_filter
|
11
|
+
:module_filter,
|
12
|
+
:report_type
|
12
13
|
|
13
14
|
@@port_value = ''
|
14
15
|
@@uri_value = ''
|
@@ -16,26 +17,18 @@ class ExploitRunDescription
|
|
16
17
|
@@device_ip_to_scan_value = ''
|
17
18
|
@@use_os_filter_value = ''
|
18
19
|
|
19
|
-
def initialize(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
self.
|
30
|
-
|
31
|
-
@@uri_value = uri
|
32
|
-
@@use_ssl_value = use_ssl
|
33
|
-
self.token = token
|
34
|
-
self.workspace_name = workspace_name
|
35
|
-
self.nexpose_console_name = nexpose_console_name
|
36
|
-
@@device_ip_to_scan_value = device_ip_to_scan
|
37
|
-
self.use_os_filter = use_os_filter
|
38
|
-
self.module_filter = module_filter
|
20
|
+
def initialize(options)
|
21
|
+
self.connection_url = options['connection_url']
|
22
|
+
@@port_value = options['port']
|
23
|
+
@@uri_value = options['uri']
|
24
|
+
@@use_ssl_value = options['use_ssl']
|
25
|
+
self.token = options['token']
|
26
|
+
self.workspace_name = options['workspace_name']
|
27
|
+
self.nexpose_console_name = options['nexpose_console_name']
|
28
|
+
@@device_ip_to_scan_value = options['device_ip_to_scan']
|
29
|
+
self.use_os_filter = options['use_os_filter']
|
30
|
+
self.module_filter = options['module_filter']
|
31
|
+
self.report_type = options['report_type']
|
39
32
|
end
|
40
33
|
|
41
34
|
def verify
|
@@ -81,6 +74,17 @@ class ExploitRunDescription
|
|
81
74
|
"DS_ModuleFilter" => self.module_filter}
|
82
75
|
end
|
83
76
|
|
77
|
+
def get_report_options
|
78
|
+
{
|
79
|
+
'workspace' => self.workspace_name,
|
80
|
+
'name' => self.workspace_name,
|
81
|
+
'report_type' => self.report_type,
|
82
|
+
'created_by' => self.workspace_name,
|
83
|
+
'file_formats' => [:pdf],
|
84
|
+
'DS_WHITELIST_HOSTS' => self.device_ip_to_scan
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
84
88
|
def device_ip_to_scan
|
85
89
|
"http://#{@@device_ip_to_scan_value}"
|
86
90
|
end
|
@@ -10,6 +10,7 @@ describe 'exploit_run_description' do
|
|
10
10
|
@expected_ssl = false
|
11
11
|
@expected_os_filter = false
|
12
12
|
@expected_module_filter = 'exploit/windows/smb/psexec'
|
13
|
+
@expected_report_type = :fisma
|
13
14
|
@expected_workspacename = 'workspacename'
|
14
15
|
@expected_nexpose_console_name = 'nexpose_console_name'
|
15
16
|
@expected_webscan_task_id = '12'
|
@@ -18,18 +19,21 @@ describe 'exploit_run_description' do
|
|
18
19
|
@mock_rpc_client = get_mock_rpc_client
|
19
20
|
@mock_device_ip_to_scan = '127.0.0.1'
|
20
21
|
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}"
|
22
|
+
@options = {
|
23
|
+
'connection_url' => @expected_connection,
|
24
|
+
'port' => @expected_port,
|
25
|
+
'uri' => @expected_uri,
|
26
|
+
'use_ssl' => @expected_ssl,
|
27
|
+
'token' => @expected_token,
|
28
|
+
'workspace_name' => @expected_workspace_name,
|
29
|
+
'nexpose_console_name' => @expected_nexpose_console_name,
|
30
|
+
'device_ip_to_scan' => @mock_device_ip_to_scan,
|
31
|
+
'use_os_filter' => @expected_use_os_filter,
|
32
|
+
'module_filter' => @expected_module_filter,
|
33
|
+
'report_type' => @expected_report_type
|
34
|
+
}
|
21
35
|
|
22
|
-
@exploit_run_description = ExploitRunDescription.new
|
23
|
-
@expected_port,
|
24
|
-
@expected_uri,
|
25
|
-
@expected_ssl,
|
26
|
-
@expected_token,
|
27
|
-
@expected_workspace_name,
|
28
|
-
@expected_nexpose_console_name,
|
29
|
-
@mock_device_ip_to_scan,
|
30
|
-
@expected_os_filter,
|
31
|
-
@expected_module_filter
|
32
|
-
|
36
|
+
@exploit_run_description = ExploitRunDescription.new(@options)
|
33
37
|
end
|
34
38
|
|
35
39
|
it 'should accept all of the needed parameters and persist them' do
|
@@ -43,6 +47,7 @@ describe 'exploit_run_description' do
|
|
43
47
|
expect(@exploit_run_description.device_ip_to_scan).to eq(@mock_device_url_to_scan)
|
44
48
|
expect(@exploit_run_description.use_os_filter).to eq(@expected_os_filter)
|
45
49
|
expect(@exploit_run_description.module_filter).to eq(@expected_module_filter)
|
50
|
+
expect(@exploit_run_description.report_type).to eq(@expected_report_type)
|
46
51
|
end
|
47
52
|
|
48
53
|
it 'should use 3790 as default if port is empty string' do
|
data/spec/exploit_spec.rb
CHANGED
@@ -20,6 +20,7 @@ describe 'exploit' do
|
|
20
20
|
@expected_import_task_id = '1'
|
21
21
|
@expected_exploit_task_id = '13'
|
22
22
|
@expected_audit_task_id = '14'
|
23
|
+
@expected_report_id = '15'
|
23
24
|
@expected_audit_max_requests = 1000
|
24
25
|
@expected_audit_max_minutes = 3
|
25
26
|
@expected_audit_max_threads = 5
|
@@ -31,10 +32,25 @@ describe 'exploit' do
|
|
31
32
|
@expected_match_vulns = true
|
32
33
|
@expected_match_ports = true
|
33
34
|
@expected_ssl_version ='TLS1'
|
35
|
+
@expected_report_type = :fisma
|
34
36
|
@expected_module_filter = 'exploit/windows/smb/psexec'
|
35
37
|
@mock_rpc_client = get_mock_rpc_client
|
36
38
|
@mock_device_ip_to_scan = '127.0.0.1'
|
37
39
|
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}"
|
40
|
+
|
41
|
+
@options = {
|
42
|
+
'connection_url' => @expected_connection,
|
43
|
+
'port' => @expected_port,
|
44
|
+
'uri' => @expected_uri,
|
45
|
+
'use_ssl' => @expected_ssl,
|
46
|
+
'token' => @expected_token,
|
47
|
+
'workspace_name' => @expected_workspace_name,
|
48
|
+
'nexpose_console_name' => @expected_nexpose_console_name,
|
49
|
+
'device_ip_to_scan' => @mock_device_ip_to_scan,
|
50
|
+
'use_os_filter' => @expected_use_os_filter,
|
51
|
+
'module_filter' => @expected_module_filter,
|
52
|
+
'report_type' => @expected_report_type
|
53
|
+
}
|
38
54
|
end
|
39
55
|
|
40
56
|
describe 'get connection' do
|
@@ -45,22 +61,31 @@ describe 'exploit' do
|
|
45
61
|
.with(expected_options)
|
46
62
|
.and_return(@mock_rpc_client)
|
47
63
|
|
48
|
-
Metasploit::Exploit.start(@
|
64
|
+
Metasploit::Exploit.start(@options)
|
49
65
|
end
|
50
66
|
|
51
67
|
it 'should throw an error if no token is passed' do
|
52
|
-
|
53
|
-
|
68
|
+
options = @options.clone
|
69
|
+
options['token'] = nil;
|
70
|
+
expect {
|
71
|
+
Metasploit::Exploit.start(options)
|
72
|
+
}.to raise_error(StandardError, 'PWNED! Token is required')
|
54
73
|
end
|
55
74
|
|
56
75
|
it 'should throw an error if no connection url is passed' do
|
57
|
-
|
58
|
-
|
76
|
+
options = @options.clone
|
77
|
+
options['connection_url'] = nil
|
78
|
+
expect {
|
79
|
+
Metasploit::Exploit.start(options)
|
80
|
+
}.to raise_error(StandardError, 'PWNED! Connection URL is required')
|
59
81
|
end
|
60
82
|
|
61
83
|
it 'should throw an error if no ip address is passed' do
|
62
|
-
|
63
|
-
|
84
|
+
options = @options.clone
|
85
|
+
options['device_ip_to_scan'] = nil;
|
86
|
+
expect {
|
87
|
+
Metasploit::Exploit.start(options)
|
88
|
+
}.to raise_error(StandardError, 'PWNED! Device IP to scan is required')
|
64
89
|
end
|
65
90
|
|
66
91
|
it 'should use 3790 as default if port is empty string' do
|
@@ -70,30 +95,41 @@ describe 'exploit' do
|
|
70
95
|
.with(expected_options)
|
71
96
|
.and_return(@mock_rpc_client)
|
72
97
|
|
73
|
-
|
98
|
+
run_options = @options.clone
|
99
|
+
run_options['port'] = nil
|
100
|
+
Metasploit::Exploit.start(run_options)
|
74
101
|
end
|
75
102
|
end
|
76
103
|
|
77
104
|
describe 'create workspace' do
|
78
105
|
it 'should create a workspace based on workspace name' do
|
79
106
|
expect(@mock_rpc_client).to receive(:call)
|
80
|
-
.with('pro.workspace_add', {
|
107
|
+
.with('pro.workspace_add', {
|
108
|
+
'name' => @expected_workspace_name
|
109
|
+
})
|
81
110
|
|
82
|
-
Metasploit::Exploit.start(@
|
111
|
+
Metasploit::Exploit.start(@options)
|
83
112
|
end
|
84
113
|
|
85
114
|
it 'should throw an error if workspace name is invalid' do
|
86
|
-
|
87
|
-
|
115
|
+
options = @options.clone
|
116
|
+
options['workspace_name'] = nil
|
117
|
+
expect {
|
118
|
+
Metasploit::Exploit.start(options)
|
119
|
+
}.to raise_error(StandardError, 'PWNED! Workspace Name is required')
|
88
120
|
end
|
89
121
|
end
|
90
122
|
|
91
123
|
describe 'should skip nexpose import' do
|
92
124
|
it 'should skip the import if nexpose_console variable is empty or nil' do
|
93
|
-
|
94
|
-
|
95
|
-
expect {
|
96
|
-
|
125
|
+
options = @options.clone
|
126
|
+
options['nexpose_console_name'] = nil
|
127
|
+
expect {
|
128
|
+
Metasploit::Exploit.start(options)
|
129
|
+
}.to output(/\[\*\] Nexpose Console option was not passed, skipping Nexpose Import/).to_stdout
|
130
|
+
expect {
|
131
|
+
Metasploit::Exploit.start(options)
|
132
|
+
}.to_not output(/\[\*\] Importing.../).to_stdout
|
97
133
|
end
|
98
134
|
end
|
99
135
|
|
@@ -101,61 +137,88 @@ describe 'exploit' do
|
|
101
137
|
|
102
138
|
it 'should start a import' do
|
103
139
|
expect(@mock_rpc_client).to receive(:call)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
140
|
+
.with('pro.start_import', {
|
141
|
+
'workspace' => @expected_workspace_name,
|
142
|
+
'DS_NEXPOSE_CONSOLE' => @expected_nexpose_console_name,
|
143
|
+
'DS_NEXPOSE_SITE' => @expected_workspace_name
|
144
|
+
})
|
145
|
+
|
146
|
+
Metasploit::Exploit.start(@options)
|
109
147
|
end
|
110
148
|
|
111
149
|
describe 'wait to be over' do
|
112
150
|
before(:each) do
|
113
151
|
expect(@mock_rpc_client).to receive(:call)
|
114
|
-
.with('pro.start_import', {
|
115
|
-
|
116
|
-
|
152
|
+
.with('pro.start_import', {
|
153
|
+
'workspace' => @expected_workspace_name,
|
154
|
+
'DS_NEXPOSE_CONSOLE' => @expected_nexpose_console_name,
|
155
|
+
'DS_NEXPOSE_SITE' => @expected_workspace_name
|
156
|
+
})
|
117
157
|
.and_return({'task_id' => @expected_import_task_id})
|
118
158
|
end
|
119
159
|
|
120
160
|
it 'should call to check the status of an import' do
|
121
161
|
expect(@mock_rpc_client).to receive(:call).with('pro.task_status', @expected_import_task_id)
|
122
|
-
|
123
|
-
Metasploit::Exploit.start(@
|
162
|
+
|
163
|
+
Metasploit::Exploit.start(@options)
|
124
164
|
end
|
125
165
|
|
126
166
|
it 'should call to check the status until it is not running' do
|
127
167
|
expect(@mock_rpc_client).to receive(:call)
|
128
168
|
.with('pro.task_status', @expected_import_task_id)
|
129
|
-
.and_return({
|
169
|
+
.and_return({
|
170
|
+
'1' => {
|
171
|
+
'status' => 'running',
|
172
|
+
'progress' => 25,
|
173
|
+
'info' => 'Generating the export data file'
|
174
|
+
}
|
175
|
+
})
|
130
176
|
.exactly(3).times
|
131
177
|
.ordered
|
132
178
|
|
133
179
|
expect(@mock_rpc_client).to receive(:call)
|
134
180
|
.with('pro.task_status', @expected_import_task_id)
|
135
|
-
.and_return({
|
181
|
+
.and_return({
|
182
|
+
'1' => {
|
183
|
+
'status' => 'not running',
|
184
|
+
'progress' => 100,
|
185
|
+
'info' => 'Complete'
|
186
|
+
}
|
187
|
+
})
|
136
188
|
.once
|
137
189
|
.ordered
|
138
190
|
|
139
|
-
Metasploit::Exploit.start(@
|
191
|
+
Metasploit::Exploit.start(@options)
|
140
192
|
end
|
141
193
|
|
142
194
|
it 'should sleep for 3 seconds if the status is still running' do
|
143
195
|
expect(@mock_rpc_client).to receive(:call)
|
144
196
|
.with('pro.task_status', @expected_import_task_id)
|
145
|
-
.and_return({
|
197
|
+
.and_return({
|
198
|
+
'1' => {
|
199
|
+
'status' => 'running',
|
200
|
+
'progress' => 25,
|
201
|
+
'info' => 'Generating the export data file'
|
202
|
+
}
|
203
|
+
})
|
146
204
|
.exactly(3).times
|
147
205
|
.ordered
|
148
206
|
|
149
207
|
expect(@mock_rpc_client).to receive(:call)
|
150
208
|
.with('pro.task_status', @expected_import_task_id)
|
151
|
-
.and_return({
|
209
|
+
.and_return({
|
210
|
+
'1' => {
|
211
|
+
'status' => 'not running',
|
212
|
+
'progress' => 100,
|
213
|
+
'info' => 'Complete'
|
214
|
+
}
|
215
|
+
})
|
152
216
|
.once
|
153
217
|
.ordered
|
154
|
-
|
155
218
|
#Expecting 7 because we are mocking 6 above and the global :call mock in get_mock_rpc_client
|
156
|
-
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(
|
157
|
-
|
158
|
-
Metasploit::Exploit.start(@
|
219
|
+
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(107).times
|
220
|
+
|
221
|
+
Metasploit::Exploit.start(@options)
|
159
222
|
end
|
160
223
|
end
|
161
224
|
end
|
@@ -163,77 +226,123 @@ describe 'exploit' do
|
|
163
226
|
describe 'start metasploit scan' do
|
164
227
|
it 'should kick off a scan' do
|
165
228
|
expect(@mock_rpc_client).to receive(:call)
|
166
|
-
.with('pro.start_webscan', {
|
167
|
-
|
229
|
+
.with('pro.start_webscan', {
|
230
|
+
'workspace' => @expected_workspace_name,
|
231
|
+
'DS_URLS' => @mock_device_url_to_scan
|
232
|
+
})
|
168
233
|
|
169
|
-
Metasploit::Exploit.start(@
|
234
|
+
Metasploit::Exploit.start(@options)
|
170
235
|
end
|
171
236
|
|
172
237
|
describe 'wait for scan to be over' do
|
173
238
|
before(:each) do
|
174
239
|
expect(@mock_rpc_client).to receive(:call)
|
175
|
-
.with('pro.start_webscan', {
|
176
|
-
|
177
|
-
|
240
|
+
.with('pro.start_webscan', {
|
241
|
+
'workspace' => @expected_workspace_name,
|
242
|
+
'DS_URLS' => @mock_device_url_to_scan
|
243
|
+
})
|
244
|
+
.and_return({
|
245
|
+
'task_id' => @expected_webscan_task_id
|
246
|
+
})
|
178
247
|
end
|
179
248
|
|
180
249
|
it 'should call to check the status of the scan' do
|
181
250
|
expect(@mock_rpc_client).to receive(:call).with('pro.task_status', @expected_webscan_task_id)
|
182
251
|
|
183
|
-
Metasploit::Exploit.start(@
|
252
|
+
Metasploit::Exploit.start(@options)
|
184
253
|
end
|
185
254
|
|
186
255
|
it 'should call to check the status until it is not running' do
|
187
256
|
expect(@mock_rpc_client).to receive(:call)
|
188
257
|
.with('pro.task_status', @expected_webscan_task_id)
|
189
|
-
.and_return({
|
258
|
+
.and_return({
|
259
|
+
'12' => {
|
260
|
+
'status' => 'running',
|
261
|
+
'progress' => 50,
|
262
|
+
'info' => 'Validating Target URLs'
|
263
|
+
}
|
264
|
+
})
|
190
265
|
.exactly(3).times
|
191
266
|
.ordered
|
192
267
|
|
193
268
|
expect(@mock_rpc_client).to receive(:call)
|
194
269
|
.with('pro.task_status', @expected_webscan_task_id)
|
195
|
-
.and_return({
|
270
|
+
.and_return({
|
271
|
+
'12' => {
|
272
|
+
'status' => 'not running',
|
273
|
+
'progress' => 100,
|
274
|
+
'info' => 'Complete'
|
275
|
+
}
|
276
|
+
})
|
196
277
|
.once
|
197
278
|
.ordered
|
198
279
|
|
199
|
-
Metasploit::Exploit.start(@
|
280
|
+
Metasploit::Exploit.start(@options)
|
200
281
|
end
|
201
282
|
|
202
283
|
it 'should sleep for 3 seconds if the status is still running' do
|
203
284
|
expect(@mock_rpc_client).to receive(:call)
|
204
285
|
.with('pro.task_status', @expected_webscan_task_id)
|
205
|
-
.and_return({
|
286
|
+
.and_return({
|
287
|
+
'12' => {
|
288
|
+
'status' => 'running',
|
289
|
+
'progress' => 50,
|
290
|
+
'info' => 'Validating Target URLs'
|
291
|
+
}
|
292
|
+
})
|
206
293
|
.exactly(3).times
|
207
294
|
.ordered
|
208
295
|
|
209
296
|
expect(@mock_rpc_client).to receive(:call)
|
210
297
|
.with('pro.task_status', @expected_webscan_task_id)
|
211
|
-
.and_return({
|
298
|
+
.and_return({
|
299
|
+
'12' => {
|
300
|
+
'status' => 'not running',
|
301
|
+
'progress' => 100,
|
302
|
+
'info' => 'Complete'
|
303
|
+
}
|
304
|
+
})
|
212
305
|
.once
|
213
306
|
.ordered
|
214
307
|
|
215
308
|
#Expecting 7 because we are mocking 6 above and the global :call mock in get_mock_rpc_client
|
216
|
-
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(
|
309
|
+
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(107).times
|
217
310
|
|
218
|
-
Metasploit::Exploit.start(@
|
311
|
+
Metasploit::Exploit.start(@options)
|
219
312
|
end
|
220
313
|
end
|
221
314
|
end
|
222
315
|
|
316
|
+
describe 'start generating report' do
|
317
|
+
it 'should start a report' do
|
318
|
+
expect(@mock_rpc_client).to receive(:call)
|
319
|
+
.with('pro.start_report', {
|
320
|
+
'workspace' => @expected_workspace_name,
|
321
|
+
'name' => @expected_workspace_name,
|
322
|
+
'report_type' => @expected_report_type,
|
323
|
+
'created_by' => @expected_workspace_name,
|
324
|
+
'file_formats' => [:pdf],
|
325
|
+
'DS_WHITELIST_HOSTS' => @mock_device_url_to_scan,
|
326
|
+
})
|
327
|
+
|
328
|
+
Metasploit::Exploit.start(@options)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
223
332
|
describe 'start an audit' do
|
224
333
|
|
225
334
|
it 'should kick off an audit' do
|
226
335
|
expect(@mock_rpc_client).to receive(:call)
|
227
336
|
.with('pro.start_webaudit', {
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
Metasploit::Exploit.start(@
|
337
|
+
'workspace' => @expected_workspace_name,
|
338
|
+
'DS_URLS' => @mock_device_url_to_scan,
|
339
|
+
'DS_MAX_REQUESTS' => @expected_audit_max_requests,
|
340
|
+
'DS_MAX_MINUTES' => @expected_audit_max_minutes,
|
341
|
+
'DS_MAX_THREADS' => @expected_audit_max_threads,
|
342
|
+
'DS_MAX_INSTANCES' => @expected_audit_max_instances
|
343
|
+
})
|
344
|
+
|
345
|
+
Metasploit::Exploit.start(@options)
|
237
346
|
end
|
238
347
|
|
239
348
|
describe 'wait for audit to be over' do
|
@@ -241,55 +350,82 @@ describe 'exploit' do
|
|
241
350
|
|
242
351
|
expect(@mock_rpc_client).to receive(:call)
|
243
352
|
.with('pro.start_webaudit', {
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
353
|
+
"workspace" => @expected_workspace_name,
|
354
|
+
"DS_URLS" => @mock_device_url_to_scan,
|
355
|
+
"DS_MAX_REQUESTS" => @expected_audit_max_requests,
|
356
|
+
"DS_MAX_MINUTES" => @expected_audit_max_minutes,
|
357
|
+
"DS_MAX_THREADS" => @expected_audit_max_threads,
|
358
|
+
"DS_MAX_INSTANCES" => @expected_audit_max_instances
|
359
|
+
})
|
251
360
|
.and_return({'task_id' => @expected_audit_task_id})
|
252
361
|
end
|
253
362
|
|
254
363
|
it 'should call to check the status of the audit' do
|
255
|
-
expect(@mock_rpc_client).to receive(:call)
|
364
|
+
expect(@mock_rpc_client).to receive(:call)
|
365
|
+
.with('pro.task_status', @expected_audit_task_id)
|
256
366
|
|
257
|
-
Metasploit::Exploit.start(@
|
367
|
+
Metasploit::Exploit.start(@options)
|
258
368
|
end
|
259
369
|
|
260
370
|
it 'should call to check the status until it is not running' do
|
261
371
|
expect(@mock_rpc_client).to receive(:call)
|
262
372
|
.with('pro.task_status', @expected_audit_task_id)
|
263
|
-
.and_return({
|
373
|
+
.and_return({
|
374
|
+
'14' => {
|
375
|
+
'status' => 'running',
|
376
|
+
'progress' => 3,
|
377
|
+
'info' => 'Auditing your website'
|
378
|
+
}
|
379
|
+
})
|
264
380
|
.exactly(3).times
|
265
381
|
.ordered
|
266
382
|
|
267
383
|
expect(@mock_rpc_client).to receive(:call)
|
268
384
|
.with('pro.task_status', @expected_audit_task_id)
|
269
|
-
.and_return({
|
385
|
+
.and_return({
|
386
|
+
'14' => {
|
387
|
+
'status' => 'not running',
|
388
|
+
'progress' => 100,
|
389
|
+
'info' => 'Complete'
|
390
|
+
}
|
391
|
+
})
|
270
392
|
.once
|
271
393
|
.ordered
|
272
394
|
|
273
|
-
Metasploit::Exploit.start(@
|
395
|
+
Metasploit::Exploit.start(@options)
|
274
396
|
end
|
275
397
|
|
276
398
|
it 'should sleep for 3 seconds if the status is still running' do
|
277
399
|
expect(@mock_rpc_client).to receive(:call)
|
278
400
|
.with('pro.task_status', @expected_audit_task_id)
|
279
|
-
.and_return({
|
401
|
+
.and_return({
|
402
|
+
'14' => {
|
403
|
+
'status' => 'running',
|
404
|
+
'progress' => 3,
|
405
|
+
'info' => 'Auditing your website'
|
406
|
+
}
|
407
|
+
})
|
280
408
|
.exactly(3).times
|
281
409
|
.ordered
|
282
410
|
|
283
411
|
expect(@mock_rpc_client).to receive(:call)
|
284
412
|
.with('pro.task_status', @expected_audit_task_id)
|
285
|
-
.and_return({
|
413
|
+
.and_return({
|
414
|
+
'14' => {
|
415
|
+
'status' => 'not running',
|
416
|
+
'progress' => 100,
|
417
|
+
'info' => 'Complete'
|
418
|
+
}
|
419
|
+
})
|
286
420
|
.once
|
287
421
|
.ordered
|
422
|
+
|
423
|
+
expect(Metasploit::Exploit).to receive(:sleep)
|
424
|
+
.with(3)
|
425
|
+
.exactly(107)
|
426
|
+
.times
|
288
427
|
|
289
|
-
|
290
|
-
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(7).times
|
291
|
-
|
292
|
-
Metasploit::Exploit.start(@expected_connection, @expected_port, @expected_uri, @expected_ssl, @expected_token, @expected_workspace_name, @expected_nexpose_console_name, @mock_device_ip_to_scan, @expected_use_os_filter, @expected_module_filter)
|
428
|
+
Metasploit::Exploit.start(@options)
|
293
429
|
end
|
294
430
|
end
|
295
431
|
end
|
@@ -299,163 +435,210 @@ describe 'exploit' do
|
|
299
435
|
it 'should kick off an exploit' do
|
300
436
|
expect(@mock_rpc_client).to receive(:call)
|
301
437
|
.with('pro.start_exploit', {
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
Metasploit::Exploit.start(@
|
438
|
+
"workspace" => @expected_workspace_name,
|
439
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
440
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
441
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
442
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
443
|
+
"DS_LimitSessions" => @expected_session_limit,
|
444
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
445
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
446
|
+
"DS_FilterByOS" => @expected_use_os_filter,
|
447
|
+
"DS_ModuleFilter" => @expected_module_filter
|
448
|
+
})
|
449
|
+
|
450
|
+
Metasploit::Exploit.start(@options)
|
315
451
|
end
|
316
452
|
|
317
453
|
it 'should use a operating system filter if its set to true' do
|
318
454
|
expect(@mock_rpc_client).to receive(:call)
|
319
455
|
.with('pro.start_exploit', {
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
Metasploit::Exploit.start(@
|
456
|
+
"workspace" => @expected_workspace_name,
|
457
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
458
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
459
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
460
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
461
|
+
"DS_LimitSessions" => @expected_session_limit,
|
462
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
463
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
464
|
+
"DS_FilterByOS" => @expected_use_os_filter,
|
465
|
+
"DS_ModuleFilter" => @expected_module_filter
|
466
|
+
})
|
467
|
+
|
468
|
+
Metasploit::Exploit.start(@options)
|
333
469
|
end
|
334
470
|
|
335
471
|
it 'should not use a operating system filter if its set to false' do
|
336
472
|
expect(@mock_rpc_client).to receive(:call)
|
337
|
-
.with('pro.start_exploit', {
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
473
|
+
.with('pro.start_exploit', {
|
474
|
+
"workspace" => @expected_workspace_name,
|
475
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
476
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
477
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
478
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
479
|
+
"DS_LimitSessions" => @expected_session_limit,
|
480
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
481
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
482
|
+
"DS_FilterByOS" => false,
|
483
|
+
"DS_ModuleFilter" => @expected_module_filter
|
484
|
+
})
|
485
|
+
|
486
|
+
options = @options.clone
|
487
|
+
options['use_os_filter'] = false
|
488
|
+
Metasploit::Exploit.start(options)
|
350
489
|
end
|
351
490
|
|
352
491
|
it 'should not use a module filter if no modules are passed' do
|
353
492
|
expect(@mock_rpc_client).to receive(:call)
|
354
|
-
.with('pro.start_exploit', {
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
493
|
+
.with('pro.start_exploit', {
|
494
|
+
"workspace" => @expected_workspace_name,
|
495
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
496
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
497
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
498
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
499
|
+
"DS_LimitSessions" => @expected_session_limit,
|
500
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
501
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
502
|
+
"DS_FilterByOS" => false,
|
503
|
+
"DS_ModuleFilter" => nil
|
504
|
+
})
|
505
|
+
|
506
|
+
options = @options.clone
|
507
|
+
options['module_filter'] = nil
|
508
|
+
options['use_os_filter'] = false
|
509
|
+
Metasploit::Exploit.start(options)
|
367
510
|
end
|
368
511
|
|
369
512
|
it 'should use a module filter if a module is passed' do
|
370
513
|
expect(@mock_rpc_client).to receive(:call)
|
371
|
-
.with('pro.start_exploit', {
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
514
|
+
.with('pro.start_exploit', {
|
515
|
+
"workspace" => @expected_workspace_name,
|
516
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
517
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
518
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
519
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
520
|
+
"DS_LimitSessions" => @expected_session_limit,
|
521
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
522
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
523
|
+
"DS_FilterByOS" => false,
|
524
|
+
"DS_ModuleFilter" => @expected_module_filter
|
525
|
+
})
|
526
|
+
options = @options.clone
|
527
|
+
options['use_os_filter'] = false
|
528
|
+
Metasploit::Exploit.start(options)
|
384
529
|
end
|
385
530
|
|
386
531
|
describe 'wait for exploit to be over' do
|
387
532
|
before(:each) do
|
388
533
|
|
389
534
|
expect(@mock_rpc_client).to receive(:call)
|
390
|
-
.with('pro.start_exploit', {
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
535
|
+
.with('pro.start_exploit', {
|
536
|
+
"workspace" => @expected_workspace_name,
|
537
|
+
"DS_WHITELIST_HOSTS" => @mock_device_ip_to_scan,
|
538
|
+
"DS_MinimumRank" => @expected_minimum_rank,
|
539
|
+
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
540
|
+
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
541
|
+
"DS_LimitSessions" => @expected_session_limit,
|
542
|
+
"DS_MATCH_VULNS" => @expected_match_vulns,
|
543
|
+
"DS_MATCH_PORTS" => @expected_match_ports,
|
544
|
+
"DS_FilterByOS" => @expected_use_os_filter,
|
545
|
+
"DS_ModuleFilter" => @expected_module_filter
|
546
|
+
})
|
547
|
+
.and_return({
|
548
|
+
'task_id' => @expected_exploit_task_id
|
549
|
+
})
|
402
550
|
end
|
403
551
|
|
404
552
|
it 'should call to check the status of the exploit' do
|
405
|
-
expect(@mock_rpc_client).to receive(:call)
|
553
|
+
expect(@mock_rpc_client).to receive(:call)
|
554
|
+
.with('pro.task_status', @expected_exploit_task_id)
|
406
555
|
|
407
|
-
Metasploit::Exploit.start(@
|
556
|
+
Metasploit::Exploit.start(@options)
|
408
557
|
end
|
409
558
|
|
410
559
|
it 'should call to check the status until it is not running' do
|
411
560
|
expect(@mock_rpc_client).to receive(:call)
|
412
561
|
.with('pro.task_status', @expected_exploit_task_id)
|
413
|
-
.and_return({
|
562
|
+
.and_return({
|
563
|
+
'13' => {
|
564
|
+
'status' => 'running',
|
565
|
+
'progress' => 3,
|
566
|
+
'info' => 'WordPress Asset-Manager PHP File Upload Vulnerability'
|
567
|
+
}
|
568
|
+
})
|
414
569
|
.exactly(3).times
|
415
570
|
.ordered
|
416
571
|
|
417
572
|
expect(@mock_rpc_client).to receive(:call)
|
418
573
|
.with('pro.task_status', @expected_exploit_task_id)
|
419
|
-
.and_return({
|
574
|
+
.and_return({
|
575
|
+
'13' => {
|
576
|
+
'status' => 'not running',
|
577
|
+
'progress' => 100,
|
578
|
+
'info' => 'Complete'
|
579
|
+
}
|
580
|
+
})
|
420
581
|
.once
|
421
582
|
.ordered
|
422
583
|
|
423
|
-
Metasploit::Exploit.start(@
|
584
|
+
Metasploit::Exploit.start(@options)
|
424
585
|
end
|
425
586
|
|
426
587
|
it 'should sleep for 3 seconds if the status is still running' do
|
427
588
|
expect(@mock_rpc_client).to receive(:call)
|
428
589
|
.with('pro.task_status', @expected_exploit_task_id)
|
429
|
-
.and_return({
|
590
|
+
.and_return({
|
591
|
+
'13' => {
|
592
|
+
'status' => 'running',
|
593
|
+
'progress' => 3,
|
594
|
+
'info' => 'WordPress Asset-Manager PHP File Upload Vulnerability'
|
595
|
+
}
|
596
|
+
})
|
430
597
|
.exactly(3).times
|
431
598
|
.ordered
|
432
599
|
|
433
600
|
expect(@mock_rpc_client).to receive(:call)
|
434
601
|
.with('pro.task_status', @expected_exploit_task_id)
|
435
|
-
.and_return({
|
602
|
+
.and_return({
|
603
|
+
'13' => {
|
604
|
+
'status' => 'not running',
|
605
|
+
'progress' => 100,
|
606
|
+
'info' => 'Complete'
|
607
|
+
}
|
608
|
+
})
|
436
609
|
.once
|
437
610
|
.ordered
|
438
611
|
|
439
|
-
|
440
|
-
|
612
|
+
expect(Metasploit::Exploit).to receive(:sleep)
|
613
|
+
.with(3)
|
614
|
+
.exactly(107)
|
615
|
+
.times
|
441
616
|
|
442
|
-
Metasploit::Exploit.start(@
|
617
|
+
Metasploit::Exploit.start(@options)
|
443
618
|
end
|
444
619
|
end
|
445
620
|
end
|
446
621
|
|
447
|
-
|
448
622
|
end
|
449
623
|
end
|
450
624
|
|
451
625
|
def get_default_options_and_override(override)
|
452
|
-
{
|
626
|
+
{
|
627
|
+
:host => @expected_connection,
|
628
|
+
:port => @expected_port,
|
629
|
+
:token => @expected_token,
|
630
|
+
:uri => @expected_uri,
|
631
|
+
:ssl => @expected_ssl,
|
632
|
+
:ssl_version => @expected_ssl_version
|
633
|
+
}.merge(override)
|
453
634
|
end
|
454
635
|
|
455
636
|
def get_mock_rpc_client
|
456
637
|
mock_rpc_client = double(Msf::RPC::Client)
|
457
638
|
|
458
|
-
allow(mock_rpc_client).to receive(:call)
|
639
|
+
allow(mock_rpc_client).to receive(:call)
|
640
|
+
.with(any_args)
|
641
|
+
.and_return({})
|
459
642
|
|
460
643
|
allow(Msf::RPC::Client).to receive(:new)
|
461
644
|
.and_return(mock_rpc_client)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metasploit-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Gibson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msfrpc-client
|