metasploit-runner 0.2.1 → 0.2.3
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/.gitignore +2 -0
- data/README.md +16 -15
- data/bin/exploit +13 -12
- data/config/exploit.yml.example +11 -0
- data/lib/MetasploitPenTestScript/version.rb +1 -1
- data/lib/metasploit/exploit.rb +2 -2
- data/lib/metasploit/exploit_run_description.rb +34 -14
- data/spec/exploit_config_spec.rb +54 -0
- data/spec/exploit_run_description_spec.rb +16 -4
- data/spec/exploit_spec.rb +67 -65
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7e2d2dec14bd740b81ca421a7a055a7532c52dc
|
4
|
+
data.tar.gz: 82b61166b05fac46c87965cc3bf479305d45e0c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa4689843ef2cd354dd0c735c0ddcf44f4ab2c9e8b249c14e90c0c08f74263dfeb6f821f17be7152138637ed4a6963c238f4b6f6a909c7b02e5e1780718a0ff6
|
7
|
+
data.tar.gz: e4cd97fa3a0bfcbf178e8c7e4a4e02b2361c54dc5db4359f29d214340bc9b6062a3895f9af29c6c2a8bbab72423ce64cc98f611ba7ba70b785bfb9482ca237c0
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# MetasploitPenTestScript
|
2
2
|
|
3
|
-
This is a ruby gem that basically wraps the msfrpc-client gem.
|
3
|
+
This is a ruby gem that basically wraps the msfrpc-client gem.
|
4
4
|
|
5
|
-
It was primarily created to automate workspace creation and automatic import of
|
6
|
-
a Jenkins automated CI/CD environment.
|
5
|
+
It was primarily created to automate workspace creation and automatic import of Nexpose scan data from use in
|
6
|
+
a Jenkins automated CI/CD environment.
|
7
7
|
|
8
|
-
Basically this allows you to attach
|
9
|
-
Though it can be used for other purposes.
|
8
|
+
Basically this allows you to attach Metasploit to your Continuous Delivery/Continuous Integration pipeline, though it can be used for other purposes.
|
10
9
|
|
11
10
|
## Installation
|
12
11
|
|
@@ -24,28 +23,28 @@ Or install it yourself as:
|
|
24
23
|
|
25
24
|
## Usage
|
26
25
|
|
27
|
-
This gem allows you to specify the Metasploit Connection URL, Metasploit Connection Port, Metasploit URI, SSL true/false, Token, Workspace Name, Nexpose Console Name, Device/Target IP,
|
26
|
+
This gem allows you to specify the Metasploit Connection URL, Metasploit Connection Port, Metasploit URI, SSL true/false, Token, Workspace Name, Nexpose Console Name, Device/Target IP, Exploit Module OS Filter, report type, and Whitelist CIDR block for exploits..
|
28
27
|
|
29
|
-
The nexpose_console_name is optional, if you specify a
|
28
|
+
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
29
|
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
30
|
|
32
|
-
$ exploit "connection_url" "port" "uri" "use_ssl" "token" "workspace_name" "nexpose_console_name" "device_ip_to_scan" "os_filter" "module_filter" "report_type"
|
31
|
+
$ exploit "connection_url" "port" "uri" "use_ssl" "token" "workspace_name" "nexpose_console_name" "device_ip_to_scan" "os_filter" "module_filter" "report_type" "whitelist_hosts"
|
33
32
|
|
34
33
|
Example WITH Nexpose Console Integration:
|
35
34
|
|
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"
|
35
|
+
$ 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" "10.0.0.0/8"
|
37
36
|
|
38
37
|
Example WITHOUT Nexpose Console Integration:
|
39
38
|
|
40
|
-
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "" "10.0.0.1" "false" "exploit/windows/smb/psexec" "fisma"
|
39
|
+
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "" "10.0.0.1" "false" "exploit/windows/smb/psexec" "fisma" "10.0.0.0/8"
|
41
40
|
|
42
|
-
Additionally, an
|
41
|
+
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
42
|
|
44
|
-
Note: at the time of publishing this version of the gem, that was over 6,000 modules, which is
|
43
|
+
Note: at the time of publishing this version of the gem, that was over 6,000 modules, which is A LOT. This option will only work of metasploit has a high confidence in your O/S type.
|
45
44
|
|
46
45
|
Example WITH OS Filter:
|
47
46
|
|
48
|
-
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "true" "" "fisma"
|
47
|
+
$ exploit "sploit.mydomain.com" "3790" "/api/1.0" "true" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "true" "" "fisma" "10.0.0.0/8"
|
49
48
|
|
50
49
|
The if you do not pass the following options they will default to the respective values:
|
51
50
|
|
@@ -56,11 +55,13 @@ The if you do not pass the following options they will default to the respective
|
|
56
55
|
|
57
56
|
Example using the defaults:
|
58
57
|
|
59
|
-
$ exploit "sploit.mydomain.com" "" "" "" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "" "" ""
|
58
|
+
$ exploit "sploit.mydomain.com" "" "" "" "asdlkjhsdfuw1228340asdasf8" "mycoolsoftware-build-28" "nexpose-console-1" "10.0.0.1" "" "" "" "10.0.0.0/8"
|
59
|
+
|
60
|
+
It is possible to use a YAML file to drive the configuration of this module. An example YAML file is included in config/exploit.yml.example. Simply copy it to config/exploit.yml and modify it to work with your environment.
|
60
61
|
|
61
62
|
## Contributing
|
62
63
|
|
63
|
-
1. Fork it ( https://github.com/
|
64
|
+
1. Fork it ( https://github.com/amngibson/metasploit-runner/fork )
|
64
65
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
66
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
67
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/bin/exploit
CHANGED
@@ -3,16 +3,17 @@
|
|
3
3
|
require 'metasploit/exploit'
|
4
4
|
|
5
5
|
$stdout.sync = true
|
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]
|
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
|
+
'whitelist_hosts' => ARGV[11]
|
18
19
|
})
|
@@ -0,0 +1,11 @@
|
|
1
|
+
connection_url: 'sploit.mydomain.com'
|
2
|
+
port: '3790'
|
3
|
+
uri: '/api/1.0'
|
4
|
+
use_ssl: 'true'
|
5
|
+
token: 'asdlkjhsdfuw1228340asdasf8'
|
6
|
+
workspace_name: 'mycoolsoftware-build-28'
|
7
|
+
nexpose_console_name: 'nexpose-console-1'
|
8
|
+
device_ip_to_scan: '10.0.0.1'
|
9
|
+
use_os_filter: 'true'
|
10
|
+
module_filter: 'exploit/windows/smb/psexec'
|
11
|
+
report_type: 'fisma'
|
data/lib/metasploit/exploit.rb
CHANGED
@@ -41,7 +41,7 @@ module Metasploit
|
|
41
41
|
wait_for_task_to_stop_running(rpc_client, CONSTANTS::IMPORTING_DATA_MESSAGE, import['task_id'])
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def self.create_workspace(rpc_client, workspace_name)
|
46
46
|
rpc_client.call('pro.workspace_add', {'name' => workspace_name})
|
47
47
|
end
|
@@ -105,7 +105,7 @@ module Metasploit
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def self.write_report_after_generation(rpc_client, run_details, report_id)
|
108
|
-
(1..100).each do
|
108
|
+
(1..100).each do
|
109
109
|
download = rpc_client.call('pro.report_download', report_id)
|
110
110
|
if download && download['report_artifacts'] && download['report_artifacts'].length > 0
|
111
111
|
download['report_artifacts'].each_with_index do |artifact, index|
|
@@ -1,15 +1,18 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
class ExploitRunDescription
|
2
|
-
attr_accessor :connection_url,
|
3
|
-
:port,
|
4
|
-
:uri,
|
5
|
-
:use_ssl,
|
6
|
-
:token,
|
7
|
-
:workspace_name,
|
8
|
-
:nexpose_console_name,
|
9
|
-
:device_ip_to_scan,
|
10
|
-
:use_os_filter,
|
4
|
+
attr_accessor :connection_url,
|
5
|
+
:port,
|
6
|
+
:uri,
|
7
|
+
:use_ssl,
|
8
|
+
:token,
|
9
|
+
:workspace_name,
|
10
|
+
:nexpose_console_name,
|
11
|
+
:device_ip_to_scan,
|
12
|
+
:use_os_filter,
|
11
13
|
:module_filter,
|
12
|
-
:report_type
|
14
|
+
:report_type,
|
15
|
+
:whitelist_hosts
|
13
16
|
|
14
17
|
@@port_value = ''
|
15
18
|
@@uri_value = ''
|
@@ -18,6 +21,9 @@ class ExploitRunDescription
|
|
18
21
|
@@use_os_filter_value = ''
|
19
22
|
|
20
23
|
def initialize(options)
|
24
|
+
if File.file?('config/exploit.yml')
|
25
|
+
options = YAML.load_file('config/exploit.yml')
|
26
|
+
end
|
21
27
|
self.connection_url = options['connection_url']
|
22
28
|
@@port_value = options['port']
|
23
29
|
@@uri_value = options['uri']
|
@@ -29,12 +35,13 @@ class ExploitRunDescription
|
|
29
35
|
self.use_os_filter = options['use_os_filter']
|
30
36
|
self.module_filter = options['module_filter']
|
31
37
|
self.report_type = options['report_type']
|
38
|
+
self.whitelist_hosts = options['whitelist_hosts']
|
32
39
|
end
|
33
40
|
|
34
41
|
def verify
|
35
42
|
raise StandardError, CONSTANTS::REQUIRED_TOKEN_MESSAGE if token.nil? || token.empty?
|
36
43
|
raise StandardError, CONSTANTS::REQUIRED_CONNECTION_URL_MESSAGE if connection_url.nil? || connection_url.empty?
|
37
|
-
raise StandardError, CONSTANTS::REQUIRED_DEVICE_IP_TO_SCAN_MESSAGE if
|
44
|
+
raise StandardError, CONSTANTS::REQUIRED_DEVICE_IP_TO_SCAN_MESSAGE if device_ip_to_scan.nil? || device_ip_to_scan.empty?
|
38
45
|
raise StandardError, CONSTANTS::REQUIRED_WORKSPACE_MESSAGE if workspace_name.nil? || workspace_name.empty?
|
39
46
|
end
|
40
47
|
|
@@ -49,7 +56,9 @@ class ExploitRunDescription
|
|
49
56
|
end
|
50
57
|
|
51
58
|
def device_ip_to_scan=(value)
|
52
|
-
|
59
|
+
if !@@device_ip_to_scan_value.nil?
|
60
|
+
@@device_ip_to_scan_value = value.strip!
|
61
|
+
end
|
53
62
|
end
|
54
63
|
|
55
64
|
def get_audit_options
|
@@ -63,7 +72,7 @@ class ExploitRunDescription
|
|
63
72
|
|
64
73
|
def get_exploit_options
|
65
74
|
{ "workspace" => self.workspace_name,
|
66
|
-
"DS_WHITELIST_HOSTS" =>
|
75
|
+
"DS_WHITELIST_HOSTS" => self.whitelist_hosts,
|
67
76
|
"DS_MinimumRank" => "great",
|
68
77
|
"DS_EXPLOIT_SPEED" => 5,
|
69
78
|
"DS_EXPLOIT_TIMEOUT" => 2,
|
@@ -86,7 +95,18 @@ class ExploitRunDescription
|
|
86
95
|
end
|
87
96
|
|
88
97
|
def device_ip_to_scan
|
89
|
-
|
98
|
+
if @@device_ip_to_scan_value.nil? || @@device_ip_to_scan_value.empty?
|
99
|
+
return nil
|
100
|
+
end
|
101
|
+
values = @@device_ip_to_scan_value.split(' ')
|
102
|
+
if values.nil? || values.length == 0
|
103
|
+
return nil
|
104
|
+
end
|
105
|
+
ret = []
|
106
|
+
values.each do |value|
|
107
|
+
ret.push("http://#{value}/")
|
108
|
+
end
|
109
|
+
ret.join(' ')
|
90
110
|
end
|
91
111
|
|
92
112
|
def port=(value)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'metasploit/exploit_run_description'
|
2
|
+
|
3
|
+
file_path = 'config/exploit.yml'
|
4
|
+
describe 'exploit_user_config_file_tests' do
|
5
|
+
if File.file?('config/exploit.yml')
|
6
|
+
File.rename('config/exploit.yml','config/exploit.yml.bak')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'start' do
|
10
|
+
before(:each) do
|
11
|
+
config_file = File.new(file_path, 'w')
|
12
|
+
config_file.puts("connection_url: 'mydomain.wat'")
|
13
|
+
config_file.close
|
14
|
+
@exploit_run_description = ExploitRunDescription.new({})
|
15
|
+
end
|
16
|
+
|
17
|
+
after(:each) do
|
18
|
+
File.delete(file_path) if File.exist?(file_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should get configuration from the config/exploit.yaml when provided' do
|
22
|
+
expect(@exploit_run_description.connection_url).to eq('mydomain.wat')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if File.file?('config/exploit.yml.bak')
|
27
|
+
File.rename('config/exploit.yml.bak', 'config/exploit.yml')
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'exploit_default_config_tests' do
|
33
|
+
if File.file?('config/exploit.yml')
|
34
|
+
File.rename('config/exploit.yml', 'config/exploit.yml.bak')
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'start' do
|
38
|
+
before(:each) do
|
39
|
+
@options = {
|
40
|
+
'connection_url' => 'foo.bar'
|
41
|
+
}
|
42
|
+
@exploit_run_description = ExploitRunDescription.new(@options)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should get configuration from the command line options' do
|
46
|
+
expect(@exploit_run_description.connection_url).to eq('foo.bar')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if File.file?('config/exploit.yml.bak')
|
51
|
+
File.rename('config/exploit.yml.bak', 'config/exploit.yml')
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'metasploit/exploit_run_description'
|
2
2
|
|
3
3
|
describe 'exploit_run_description' do
|
4
|
+
if File.file?('config/exploit.yml')
|
5
|
+
File.rename('config/exploit.yml', 'config/exploit.yml.bak')
|
6
|
+
end
|
7
|
+
|
4
8
|
describe 'start' do
|
5
9
|
before(:each) do
|
6
10
|
@expected_connection = 'http://test.connection'
|
@@ -18,7 +22,9 @@ describe 'exploit_run_description' do
|
|
18
22
|
@expected_tls ='TLS1'
|
19
23
|
@mock_rpc_client = get_mock_rpc_client
|
20
24
|
@mock_device_ip_to_scan = '127.0.0.1'
|
21
|
-
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}"
|
25
|
+
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}/"
|
26
|
+
@mock_whitelist_hosts = "10.0.0.0/8"
|
27
|
+
|
22
28
|
@options = {
|
23
29
|
'connection_url' => @expected_connection,
|
24
30
|
'port' => @expected_port,
|
@@ -30,10 +36,11 @@ describe 'exploit_run_description' do
|
|
30
36
|
'device_ip_to_scan' => @mock_device_ip_to_scan,
|
31
37
|
'use_os_filter' => @expected_use_os_filter,
|
32
38
|
'module_filter' => @expected_module_filter,
|
33
|
-
'report_type' => @expected_report_type
|
39
|
+
'report_type' => @expected_report_type,
|
40
|
+
'whitelist_hosts' => @mock_whitelist_hosts
|
34
41
|
}
|
35
|
-
|
36
|
-
@exploit_run_description = ExploitRunDescription.new(@options)
|
42
|
+
|
43
|
+
@exploit_run_description = ExploitRunDescription.new(@options)
|
37
44
|
end
|
38
45
|
|
39
46
|
it 'should accept all of the needed parameters and persist them' do
|
@@ -48,6 +55,7 @@ describe 'exploit_run_description' do
|
|
48
55
|
expect(@exploit_run_description.use_os_filter).to eq(@expected_os_filter)
|
49
56
|
expect(@exploit_run_description.module_filter).to eq(@expected_module_filter)
|
50
57
|
expect(@exploit_run_description.report_type).to eq(@expected_report_type)
|
58
|
+
expect(@exploit_run_description.whitelist_hosts).to eq(@mock_whitelist_hosts)
|
51
59
|
end
|
52
60
|
|
53
61
|
it 'should use 3790 as default if port is empty string' do
|
@@ -172,4 +180,8 @@ describe 'exploit_run_description' do
|
|
172
180
|
end
|
173
181
|
end
|
174
182
|
end
|
183
|
+
|
184
|
+
if File.file?('config/exploit.yml.bak')
|
185
|
+
File.rename('config/exploit.yml.bak', 'config/exploit.yml')
|
186
|
+
end
|
175
187
|
end
|
data/spec/exploit_spec.rb
CHANGED
@@ -36,7 +36,8 @@ describe 'exploit' do
|
|
36
36
|
@expected_module_filter = 'exploit/windows/smb/psexec'
|
37
37
|
@mock_rpc_client = get_mock_rpc_client
|
38
38
|
@mock_device_ip_to_scan = '127.0.0.1'
|
39
|
-
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}"
|
39
|
+
@mock_device_url_to_scan = "http://#{@mock_device_ip_to_scan}/"
|
40
|
+
@mock_whitelist_hosts = "10.0.0.0/8"
|
40
41
|
|
41
42
|
@options = {
|
42
43
|
'connection_url' => @expected_connection,
|
@@ -49,7 +50,8 @@ describe 'exploit' do
|
|
49
50
|
'device_ip_to_scan' => @mock_device_ip_to_scan,
|
50
51
|
'use_os_filter' => @expected_use_os_filter,
|
51
52
|
'module_filter' => @expected_module_filter,
|
52
|
-
'report_type' => @expected_report_type
|
53
|
+
'report_type' => @expected_report_type,
|
54
|
+
'whitelist_hosts' => @mock_whitelist_hosts
|
53
55
|
}
|
54
56
|
end
|
55
57
|
|
@@ -67,24 +69,24 @@ describe 'exploit' do
|
|
67
69
|
it 'should throw an error if no token is passed' do
|
68
70
|
options = @options.clone
|
69
71
|
options['token'] = nil;
|
70
|
-
expect {
|
71
|
-
Metasploit::Exploit.start(options)
|
72
|
+
expect {
|
73
|
+
Metasploit::Exploit.start(options)
|
72
74
|
}.to raise_error(StandardError, 'PWNED! Token is required')
|
73
75
|
end
|
74
76
|
|
75
77
|
it 'should throw an error if no connection url is passed' do
|
76
78
|
options = @options.clone
|
77
79
|
options['connection_url'] = nil
|
78
|
-
expect {
|
79
|
-
Metasploit::Exploit.start(options)
|
80
|
+
expect {
|
81
|
+
Metasploit::Exploit.start(options)
|
80
82
|
}.to raise_error(StandardError, 'PWNED! Connection URL is required')
|
81
83
|
end
|
82
84
|
|
83
85
|
it 'should throw an error if no ip address is passed' do
|
84
86
|
options = @options.clone
|
85
87
|
options['device_ip_to_scan'] = nil;
|
86
|
-
expect {
|
87
|
-
Metasploit::Exploit.start(options)
|
88
|
+
expect {
|
89
|
+
Metasploit::Exploit.start(options)
|
88
90
|
}.to raise_error(StandardError, 'PWNED! Device IP to scan is required')
|
89
91
|
end
|
90
92
|
|
@@ -114,8 +116,8 @@ describe 'exploit' do
|
|
114
116
|
it 'should throw an error if workspace name is invalid' do
|
115
117
|
options = @options.clone
|
116
118
|
options['workspace_name'] = nil
|
117
|
-
expect {
|
118
|
-
Metasploit::Exploit.start(options)
|
119
|
+
expect {
|
120
|
+
Metasploit::Exploit.start(options)
|
119
121
|
}.to raise_error(StandardError, 'PWNED! Workspace Name is required')
|
120
122
|
end
|
121
123
|
end
|
@@ -142,7 +144,7 @@ describe 'exploit' do
|
|
142
144
|
'DS_NEXPOSE_CONSOLE' => @expected_nexpose_console_name,
|
143
145
|
'DS_NEXPOSE_SITE' => @expected_workspace_name
|
144
146
|
})
|
145
|
-
|
147
|
+
|
146
148
|
Metasploit::Exploit.start(@options)
|
147
149
|
end
|
148
150
|
|
@@ -159,17 +161,17 @@ describe 'exploit' do
|
|
159
161
|
|
160
162
|
it 'should call to check the status of an import' do
|
161
163
|
expect(@mock_rpc_client).to receive(:call).with('pro.task_status', @expected_import_task_id)
|
162
|
-
|
164
|
+
|
163
165
|
Metasploit::Exploit.start(@options)
|
164
166
|
end
|
165
167
|
|
166
168
|
it 'should call to check the status until it is not running' do
|
167
169
|
expect(@mock_rpc_client).to receive(:call)
|
168
170
|
.with('pro.task_status', @expected_import_task_id)
|
169
|
-
.and_return({
|
171
|
+
.and_return({
|
170
172
|
'1' => {
|
171
|
-
'status' => 'running',
|
172
|
-
'progress' => 25,
|
173
|
+
'status' => 'running',
|
174
|
+
'progress' => 25,
|
173
175
|
'info' => 'Generating the export data file'
|
174
176
|
}
|
175
177
|
})
|
@@ -180,8 +182,8 @@ describe 'exploit' do
|
|
180
182
|
.with('pro.task_status', @expected_import_task_id)
|
181
183
|
.and_return({
|
182
184
|
'1' => {
|
183
|
-
'status' => 'not running',
|
184
|
-
'progress' => 100,
|
185
|
+
'status' => 'not running',
|
186
|
+
'progress' => 100,
|
185
187
|
'info' => 'Complete'
|
186
188
|
}
|
187
189
|
})
|
@@ -196,8 +198,8 @@ describe 'exploit' do
|
|
196
198
|
.with('pro.task_status', @expected_import_task_id)
|
197
199
|
.and_return({
|
198
200
|
'1' => {
|
199
|
-
'status' => 'running',
|
200
|
-
'progress' => 25,
|
201
|
+
'status' => 'running',
|
202
|
+
'progress' => 25,
|
201
203
|
'info' => 'Generating the export data file'
|
202
204
|
}
|
203
205
|
})
|
@@ -208,8 +210,8 @@ describe 'exploit' do
|
|
208
210
|
.with('pro.task_status', @expected_import_task_id)
|
209
211
|
.and_return({
|
210
212
|
'1' => {
|
211
|
-
'status' => 'not running',
|
212
|
-
'progress' => 100,
|
213
|
+
'status' => 'not running',
|
214
|
+
'progress' => 100,
|
213
215
|
'info' => 'Complete'
|
214
216
|
}
|
215
217
|
})
|
@@ -217,7 +219,7 @@ describe 'exploit' do
|
|
217
219
|
.ordered
|
218
220
|
#Expecting 7 because we are mocking 6 above and the global :call mock in get_mock_rpc_client
|
219
221
|
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(107).times
|
220
|
-
|
222
|
+
|
221
223
|
Metasploit::Exploit.start(@options)
|
222
224
|
end
|
223
225
|
end
|
@@ -231,7 +233,7 @@ describe 'exploit' do
|
|
231
233
|
'DS_URLS' => @mock_device_url_to_scan
|
232
234
|
})
|
233
235
|
|
234
|
-
Metasploit::Exploit.start(@options)
|
236
|
+
Metasploit::Exploit.start(@options)
|
235
237
|
end
|
236
238
|
|
237
239
|
describe 'wait for scan to be over' do
|
@@ -249,7 +251,7 @@ describe 'exploit' do
|
|
249
251
|
it 'should call to check the status of the scan' do
|
250
252
|
expect(@mock_rpc_client).to receive(:call).with('pro.task_status', @expected_webscan_task_id)
|
251
253
|
|
252
|
-
Metasploit::Exploit.start(@options)
|
254
|
+
Metasploit::Exploit.start(@options)
|
253
255
|
end
|
254
256
|
|
255
257
|
it 'should call to check the status until it is not running' do
|
@@ -257,8 +259,8 @@ describe 'exploit' do
|
|
257
259
|
.with('pro.task_status', @expected_webscan_task_id)
|
258
260
|
.and_return({
|
259
261
|
'12' => {
|
260
|
-
'status' => 'running',
|
261
|
-
'progress' => 50,
|
262
|
+
'status' => 'running',
|
263
|
+
'progress' => 50,
|
262
264
|
'info' => 'Validating Target URLs'
|
263
265
|
}
|
264
266
|
})
|
@@ -269,24 +271,24 @@ describe 'exploit' do
|
|
269
271
|
.with('pro.task_status', @expected_webscan_task_id)
|
270
272
|
.and_return({
|
271
273
|
'12' => {
|
272
|
-
'status' => 'not running',
|
273
|
-
'progress' => 100,
|
274
|
+
'status' => 'not running',
|
275
|
+
'progress' => 100,
|
274
276
|
'info' => 'Complete'
|
275
277
|
}
|
276
278
|
})
|
277
279
|
.once
|
278
280
|
.ordered
|
279
281
|
|
280
|
-
Metasploit::Exploit.start(@options)
|
282
|
+
Metasploit::Exploit.start(@options)
|
281
283
|
end
|
282
284
|
|
283
285
|
it 'should sleep for 3 seconds if the status is still running' do
|
284
286
|
expect(@mock_rpc_client).to receive(:call)
|
285
287
|
.with('pro.task_status', @expected_webscan_task_id)
|
286
|
-
.and_return({
|
288
|
+
.and_return({
|
287
289
|
'12' => {
|
288
|
-
'status' => 'running',
|
289
|
-
'progress' => 50,
|
290
|
+
'status' => 'running',
|
291
|
+
'progress' => 50,
|
290
292
|
'info' => 'Validating Target URLs'
|
291
293
|
}
|
292
294
|
})
|
@@ -297,8 +299,8 @@ describe 'exploit' do
|
|
297
299
|
.with('pro.task_status', @expected_webscan_task_id)
|
298
300
|
.and_return({
|
299
301
|
'12' => {
|
300
|
-
'status' => 'not running',
|
301
|
-
'progress' => 100,
|
302
|
+
'status' => 'not running',
|
303
|
+
'progress' => 100,
|
302
304
|
'info' => 'Complete'
|
303
305
|
}
|
304
306
|
})
|
@@ -308,7 +310,7 @@ describe 'exploit' do
|
|
308
310
|
#Expecting 7 because we are mocking 6 above and the global :call mock in get_mock_rpc_client
|
309
311
|
expect(Metasploit::Exploit).to receive(:sleep).with(3).exactly(107).times
|
310
312
|
|
311
|
-
Metasploit::Exploit.start(@options)
|
313
|
+
Metasploit::Exploit.start(@options)
|
312
314
|
end
|
313
315
|
end
|
314
316
|
end
|
@@ -316,13 +318,13 @@ describe 'exploit' do
|
|
316
318
|
describe 'start generating report' do
|
317
319
|
it 'should start a report' do
|
318
320
|
expect(@mock_rpc_client).to receive(:call)
|
319
|
-
.with('pro.start_report', {
|
320
|
-
'workspace' => @expected_workspace_name,
|
321
|
+
.with('pro.start_report', {
|
322
|
+
'workspace' => @expected_workspace_name,
|
321
323
|
'name' => @expected_workspace_name,
|
322
324
|
'report_type' => @expected_report_type,
|
323
325
|
'created_by' => @expected_workspace_name,
|
324
326
|
'file_formats' => [:pdf],
|
325
|
-
'DS_WHITELIST_HOSTS' => @mock_device_url_to_scan,
|
327
|
+
'DS_WHITELIST_HOSTS' => @mock_device_url_to_scan,
|
326
328
|
})
|
327
329
|
|
328
330
|
Metasploit::Exploit.start(@options)
|
@@ -373,7 +375,7 @@ describe 'exploit' do
|
|
373
375
|
.and_return({
|
374
376
|
'14' => {
|
375
377
|
'status' => 'running',
|
376
|
-
'progress' => 3,
|
378
|
+
'progress' => 3,
|
377
379
|
'info' => 'Auditing your website'
|
378
380
|
}
|
379
381
|
})
|
@@ -384,8 +386,8 @@ describe 'exploit' do
|
|
384
386
|
.with('pro.task_status', @expected_audit_task_id)
|
385
387
|
.and_return({
|
386
388
|
'14' => {
|
387
|
-
'status' => 'not running',
|
388
|
-
'progress' => 100,
|
389
|
+
'status' => 'not running',
|
390
|
+
'progress' => 100,
|
389
391
|
'info' => 'Complete'
|
390
392
|
}
|
391
393
|
})
|
@@ -400,8 +402,8 @@ describe 'exploit' do
|
|
400
402
|
.with('pro.task_status', @expected_audit_task_id)
|
401
403
|
.and_return({
|
402
404
|
'14' => {
|
403
|
-
'status' => 'running',
|
404
|
-
'progress' => 3,
|
405
|
+
'status' => 'running',
|
406
|
+
'progress' => 3,
|
405
407
|
'info' => 'Auditing your website'
|
406
408
|
}
|
407
409
|
})
|
@@ -412,14 +414,14 @@ describe 'exploit' do
|
|
412
414
|
.with('pro.task_status', @expected_audit_task_id)
|
413
415
|
.and_return({
|
414
416
|
'14' => {
|
415
|
-
'status' => 'not running',
|
416
|
-
'progress' => 100,
|
417
|
+
'status' => 'not running',
|
418
|
+
'progress' => 100,
|
417
419
|
'info' => 'Complete'
|
418
420
|
}
|
419
421
|
})
|
420
422
|
.once
|
421
423
|
.ordered
|
422
|
-
|
424
|
+
|
423
425
|
expect(Metasploit::Exploit).to receive(:sleep)
|
424
426
|
.with(3)
|
425
427
|
.exactly(107)
|
@@ -436,7 +438,7 @@ describe 'exploit' do
|
|
436
438
|
expect(@mock_rpc_client).to receive(:call)
|
437
439
|
.with('pro.start_exploit', {
|
438
440
|
"workspace" => @expected_workspace_name,
|
439
|
-
"DS_WHITELIST_HOSTS" => @
|
441
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
440
442
|
"DS_MinimumRank" => @expected_minimum_rank,
|
441
443
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
442
444
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -454,7 +456,7 @@ describe 'exploit' do
|
|
454
456
|
expect(@mock_rpc_client).to receive(:call)
|
455
457
|
.with('pro.start_exploit', {
|
456
458
|
"workspace" => @expected_workspace_name,
|
457
|
-
"DS_WHITELIST_HOSTS" => @
|
459
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
458
460
|
"DS_MinimumRank" => @expected_minimum_rank,
|
459
461
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
460
462
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -472,7 +474,7 @@ describe 'exploit' do
|
|
472
474
|
expect(@mock_rpc_client).to receive(:call)
|
473
475
|
.with('pro.start_exploit', {
|
474
476
|
"workspace" => @expected_workspace_name,
|
475
|
-
"DS_WHITELIST_HOSTS" => @
|
477
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
476
478
|
"DS_MinimumRank" => @expected_minimum_rank,
|
477
479
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
478
480
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -492,7 +494,7 @@ describe 'exploit' do
|
|
492
494
|
expect(@mock_rpc_client).to receive(:call)
|
493
495
|
.with('pro.start_exploit', {
|
494
496
|
"workspace" => @expected_workspace_name,
|
495
|
-
"DS_WHITELIST_HOSTS" => @
|
497
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
496
498
|
"DS_MinimumRank" => @expected_minimum_rank,
|
497
499
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
498
500
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -513,7 +515,7 @@ describe 'exploit' do
|
|
513
515
|
expect(@mock_rpc_client).to receive(:call)
|
514
516
|
.with('pro.start_exploit', {
|
515
517
|
"workspace" => @expected_workspace_name,
|
516
|
-
"DS_WHITELIST_HOSTS" => @
|
518
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
517
519
|
"DS_MinimumRank" => @expected_minimum_rank,
|
518
520
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
519
521
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -534,7 +536,7 @@ describe 'exploit' do
|
|
534
536
|
expect(@mock_rpc_client).to receive(:call)
|
535
537
|
.with('pro.start_exploit', {
|
536
538
|
"workspace" => @expected_workspace_name,
|
537
|
-
"DS_WHITELIST_HOSTS" => @
|
539
|
+
"DS_WHITELIST_HOSTS" => @mock_whitelist_hosts,
|
538
540
|
"DS_MinimumRank" => @expected_minimum_rank,
|
539
541
|
"DS_EXPLOIT_SPEED" => @expected_exploit_speed,
|
540
542
|
"DS_EXPLOIT_TIMEOUT" => @expected_exploit_timeout,
|
@@ -561,8 +563,8 @@ describe 'exploit' do
|
|
561
563
|
.with('pro.task_status', @expected_exploit_task_id)
|
562
564
|
.and_return({
|
563
565
|
'13' => {
|
564
|
-
'status' => 'running',
|
565
|
-
'progress' => 3,
|
566
|
+
'status' => 'running',
|
567
|
+
'progress' => 3,
|
566
568
|
'info' => 'WordPress Asset-Manager PHP File Upload Vulnerability'
|
567
569
|
}
|
568
570
|
})
|
@@ -573,8 +575,8 @@ describe 'exploit' do
|
|
573
575
|
.with('pro.task_status', @expected_exploit_task_id)
|
574
576
|
.and_return({
|
575
577
|
'13' => {
|
576
|
-
'status' => 'not running',
|
577
|
-
'progress' => 100,
|
578
|
+
'status' => 'not running',
|
579
|
+
'progress' => 100,
|
578
580
|
'info' => 'Complete'
|
579
581
|
}
|
580
582
|
})
|
@@ -589,8 +591,8 @@ describe 'exploit' do
|
|
589
591
|
.with('pro.task_status', @expected_exploit_task_id)
|
590
592
|
.and_return({
|
591
593
|
'13' => {
|
592
|
-
'status' => 'running',
|
593
|
-
'progress' => 3,
|
594
|
+
'status' => 'running',
|
595
|
+
'progress' => 3,
|
594
596
|
'info' => 'WordPress Asset-Manager PHP File Upload Vulnerability'
|
595
597
|
}
|
596
598
|
})
|
@@ -601,8 +603,8 @@ describe 'exploit' do
|
|
601
603
|
.with('pro.task_status', @expected_exploit_task_id)
|
602
604
|
.and_return({
|
603
605
|
'13' => {
|
604
|
-
'status' => 'not running',
|
605
|
-
'progress' => 100,
|
606
|
+
'status' => 'not running',
|
607
|
+
'progress' => 100,
|
606
608
|
'info' => 'Complete'
|
607
609
|
}
|
608
610
|
})
|
@@ -624,11 +626,11 @@ end
|
|
624
626
|
|
625
627
|
def get_default_options_and_override(override)
|
626
628
|
{
|
627
|
-
:host => @expected_connection,
|
628
|
-
:port => @expected_port,
|
629
|
-
:token => @expected_token,
|
630
|
-
:uri => @expected_uri,
|
631
|
-
:ssl => @expected_ssl,
|
629
|
+
:host => @expected_connection,
|
630
|
+
:port => @expected_port,
|
631
|
+
:token => @expected_token,
|
632
|
+
:uri => @expected_uri,
|
633
|
+
:ssl => @expected_ssl,
|
632
634
|
:ssl_version => @expected_ssl_version
|
633
635
|
}.merge(override)
|
634
636
|
end
|
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.2.
|
4
|
+
version: 0.2.3
|
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-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msfrpc-client
|
@@ -83,11 +83,13 @@ files:
|
|
83
83
|
- README.md
|
84
84
|
- Rakefile
|
85
85
|
- bin/exploit
|
86
|
+
- config/exploit.yml.example
|
86
87
|
- lib/MetasploitPenTestScript.rb
|
87
88
|
- lib/MetasploitPenTestScript/version.rb
|
88
89
|
- lib/metasploit/constants.rb
|
89
90
|
- lib/metasploit/exploit.rb
|
90
91
|
- lib/metasploit/exploit_run_description.rb
|
92
|
+
- spec/exploit_config_spec.rb
|
91
93
|
- spec/exploit_run_description_spec.rb
|
92
94
|
- spec/exploit_spec.rb
|
93
95
|
- spec/spec_helper.rb
|
@@ -111,11 +113,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
113
|
version: '0'
|
112
114
|
requirements: []
|
113
115
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
116
|
+
rubygems_version: 2.4.8
|
115
117
|
signing_key:
|
116
118
|
specification_version: 4
|
117
119
|
summary: Script to run automated Metaspolit Penetration Tests.
|
118
120
|
test_files:
|
121
|
+
- spec/exploit_config_spec.rb
|
119
122
|
- spec/exploit_run_description_spec.rb
|
120
123
|
- spec/exploit_spec.rb
|
121
124
|
- spec/spec_helper.rb
|