metasploit-credential 0.13.10 → 0.13.11
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 +8 -8
- data/lib/metasploit/credential/creation.rb +2 -2
- data/lib/metasploit/credential/exporter/core.rb +7 -1
- data/lib/metasploit/credential/importer/core.rb +19 -6
- data/lib/metasploit/credential/version.rb +1 -1
- data/spec/dummy/config/database.yml +11 -11
- data/spec/factories/metasploit/credential/importer/cores.rb +28 -22
- data/spec/lib/metasploit/credential/exporter/core_spec.rb +24 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODI2ZjA2Nzg2ODU2YmRlNDlmODA5N2UzYTcyNmVlM2FlMjQ1MjdkYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YmNjNWJkM2UyMDVkYzMwZTQxODU3YTRiMThhMjA1NGIwYjJjODNjMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
Mjc3ODk2NTk3Mjg3NzZkODc0YzM4MmE1YTE5OTYxNzE1MDNiMjIxMGJjMmZl
|
10
|
+
Y2FhODdlOTllZThlOGMwZDhmNThhMDFlOWEzZTI4NDNmYjMzMTVjOWE5NjVk
|
11
|
+
YTk0YjcyZWNlZmUyZmEyNWViMTE1MGFmMzE1MjMzMmIzM2VjN2U=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTYzMzIzMTNmNGNlODU4NjU4ZTVhNmEzMTU5N2EyNWFkOTgyZWVmNWEyNzQ3
|
14
|
+
YzhlY2IxYjU3OGVjNjFiOTcwZGFlNzY5Y2NiOTI3YTI5M2E0OWM0MDZmMTEw
|
15
|
+
ZmI2YTVjZWI4NjA0NGM4MDc2YjNkYTBmZjA2NmNkM2NlMmJhMDg=
|
@@ -208,10 +208,10 @@ module Metasploit
|
|
208
208
|
opts[:task_id] ||= self[:task].record.id
|
209
209
|
end
|
210
210
|
|
211
|
-
access_level = opts.fetch(:access_level, nil)
|
212
211
|
core = opts.fetch(:core)
|
212
|
+
access_level = opts.fetch(:access_level, nil)
|
213
213
|
last_attempted_at = opts.fetch(:last_attempted_at, nil)
|
214
|
-
status = opts.fetch(:status)
|
214
|
+
status = opts.fetch(:status, Metasploit::Model::Login::Status::UNTRIED)
|
215
215
|
|
216
216
|
login_object = nil
|
217
217
|
retry_transaction do
|
@@ -122,6 +122,9 @@ class Metasploit::Credential::Exporter::Core
|
|
122
122
|
# The hashes returned by this method will contain credentials for
|
123
123
|
# networked devices which may or may not successfully authenticate to those
|
124
124
|
# devices.
|
125
|
+
# Note that the order of columns here must match the order in
|
126
|
+
# Metasploit::Credential::Importer::Core::VALID_LONG_CSV_HEADERS or
|
127
|
+
# the headers and row values will be mismatched and break import.
|
125
128
|
# @param login [Metasploit::Credential::Login]
|
126
129
|
# @return [Hash]
|
127
130
|
def line_for_login(login)
|
@@ -130,7 +133,10 @@ class Metasploit::Credential::Exporter::Core
|
|
130
133
|
host_address: login.service.host.address,
|
131
134
|
service_port: login.service.port,
|
132
135
|
service_name: login.service.try(:name),
|
133
|
-
service_protocol: login.service.proto
|
136
|
+
service_protocol: login.service.proto,
|
137
|
+
status: login.status,
|
138
|
+
access_level: login.access_level,
|
139
|
+
last_attempted_at: login.last_attempted_at
|
134
140
|
})
|
135
141
|
end
|
136
142
|
|
@@ -21,7 +21,12 @@ class Metasploit::Credential::Importer::Core
|
|
21
21
|
BLANK_TOKEN = "<BLANK>"
|
22
22
|
|
23
23
|
# Valid headers for a CSV containing heterogenous {Metasploit::Credential::Private} types and values for {Metasploit::Credential::Realm}
|
24
|
-
VALID_LONG_CSV_HEADERS = [:username, :private_type, :private_data,
|
24
|
+
VALID_LONG_CSV_HEADERS = [:username, :private_type, :private_data,
|
25
|
+
:realm_key, :realm_value, :host_address,
|
26
|
+
:service_port, :service_name,
|
27
|
+
:service_protocol, :status, :access_level,
|
28
|
+
:last_attempted_at
|
29
|
+
]
|
25
30
|
|
26
31
|
# Valid headers for a "short" CSV containing only data for {Metasploit::Credential::Public} and {Metasploit::Credential::Private} objects
|
27
32
|
VALID_SHORT_CSV_HEADERS = [:username, :private_data]
|
@@ -107,10 +112,15 @@ class Metasploit::Credential::Importer::Core
|
|
107
112
|
private_data = row['private_data'].present? ? row['private_data'] : ''
|
108
113
|
|
109
114
|
# Host and Service information for Logins
|
110
|
-
host_address
|
111
|
-
service_port
|
112
|
-
service_protocol
|
113
|
-
service_name
|
115
|
+
host_address = row['host_address']
|
116
|
+
service_port = row['service_port']
|
117
|
+
service_protocol = row['service_protocol']
|
118
|
+
service_name = row['service_name']
|
119
|
+
# These were not initially included in the export, so handle
|
120
|
+
# legacy cases:
|
121
|
+
access_level = row['access_level'].present? ? row['access_level'] : ''
|
122
|
+
last_attempted_at = row['last_attempted_at'].present? ? row['last_attempted_at'] : ''
|
123
|
+
status = row['status'].present? ? row['status'] : ''
|
114
124
|
|
115
125
|
|
116
126
|
if realms[realm_value].nil?
|
@@ -140,13 +150,16 @@ class Metasploit::Credential::Importer::Core
|
|
140
150
|
if host_address.present? && service_port.present? && service_protocol.present?
|
141
151
|
login_opts = {
|
142
152
|
core: core,
|
143
|
-
status: Metasploit::Model::Login::Status::UNTRIED, # don't trust creds on import
|
144
153
|
address: host_address,
|
145
154
|
port: service_port,
|
146
155
|
protocol: service_protocol,
|
147
156
|
workspace_id: workspace.id,
|
148
157
|
service_name: service_name.present? ? service_name : ""
|
149
158
|
}
|
159
|
+
login_opts[:last_attempted_at] = last_attempted_at unless status.blank?
|
160
|
+
login_opts[:status] = status unless status.blank?
|
161
|
+
login_opts[:access_level] = access_level unless access_level.blank?
|
162
|
+
|
150
163
|
create_credential_login(login_opts)
|
151
164
|
end
|
152
165
|
end
|
@@ -7,7 +7,7 @@ module Metasploit
|
|
7
7
|
# The minor version number, scoped to the {MAJOR} version number.
|
8
8
|
MINOR = 13
|
9
9
|
# The patch number, scoped to the {MINOR} version number.
|
10
|
-
PATCH =
|
10
|
+
PATCH = 11
|
11
11
|
|
12
12
|
# The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the {PRERELEASE} in the
|
13
13
|
# {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# Please only use postgresql bound to a TCP port.
|
2
|
-
|
2
|
+
development: &pgsql
|
3
3
|
adapter: postgresql
|
4
|
-
|
5
|
-
password: pass123
|
4
|
+
database: metasploit_credential_development
|
6
5
|
host: localhost
|
7
6
|
port: 5432
|
8
|
-
pool:
|
7
|
+
pool: 5
|
9
8
|
timeout: 5
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
# Warning: The database defined as "test" will be erased and
|
11
|
+
# re-generated from your development database when you run "rake".
|
12
|
+
# Do not set this db to the same as development or production.
|
13
|
+
#
|
14
|
+
# Note also, sqlite3 is totally unsupported by Metasploit now.
|
15
15
|
test:
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
<<: *pgsql
|
17
|
+
database: metasploit_credential_test
|
18
|
+
|
@@ -1,20 +1,26 @@
|
|
1
1
|
FactoryGirl.define do
|
2
|
+
long_form_headers = 'username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol,status,access_level,last_attempted_at'
|
3
|
+
short_form_headers = 'username,private_data'
|
4
|
+
login_status = Metasploit::Model::Login::Status::ALL.select {|x| x != Metasploit::Model::Login::Status::UNTRIED }.sample
|
5
|
+
access_level = ['Admin', 'Foo'].sample
|
6
|
+
last_attempted_at = Time.now - 10
|
7
|
+
|
2
8
|
factory :metasploit_credential_core_importer,
|
3
9
|
class: Metasploit::Credential::Importer::Core do
|
4
|
-
|
5
|
-
|
6
|
-
input { generate(:well_formed_csv_compliant_header)}
|
10
|
+
origin { FactoryGirl.build :metasploit_credential_origin_import }
|
11
|
+
input { generate(:well_formed_csv_compliant_header) }
|
7
12
|
end
|
8
13
|
|
14
|
+
|
9
15
|
# Well-formed CSV
|
10
16
|
# Has a compliant header as defined by Metasploit::Credential::Importer::Core
|
11
17
|
# Contains 2 realms
|
12
18
|
sequence :well_formed_csv_compliant_header do |n|
|
13
19
|
csv_string =<<-eos
|
14
|
-
|
15
|
-
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
16
|
-
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
17
|
-
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins
|
20
|
+
#{long_form_headers}
|
21
|
+
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
22
|
+
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
23
|
+
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
18
24
|
eos
|
19
25
|
StringIO.new(csv_string)
|
20
26
|
end
|
@@ -24,10 +30,10 @@ lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit:
|
|
24
30
|
# Contains 2 logins
|
25
31
|
sequence :well_formed_csv_compliant_header_with_service_info do |n|
|
26
32
|
csv_string =<<-eos
|
27
|
-
|
28
|
-
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,10.0.1.1,1234,smb,tcp
|
29
|
-
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,10.0.1.2,1234,smb,tcp
|
30
|
-
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins
|
33
|
+
#{long_form_headers}
|
34
|
+
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,10.0.1.1,1234,smb,tcp,#{login_status},#{access_level},#{last_attempted_at}
|
35
|
+
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,10.0.1.2,1234,smb,tcp,#{login_status},#{access_level},#{last_attempted_at}
|
36
|
+
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins,#{login_status},#{access_level},#{last_attempted_at}
|
31
37
|
eos
|
32
38
|
StringIO.new(csv_string)
|
33
39
|
end
|
@@ -37,10 +43,10 @@ lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit:
|
|
37
43
|
# Contains no realm data
|
38
44
|
sequence :well_formed_csv_compliant_header_no_realm do |n|
|
39
45
|
csv_string =<<-eos
|
40
|
-
|
41
|
-
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief
|
42
|
-
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head
|
43
|
-
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun
|
46
|
+
#{long_form_headers}
|
47
|
+
han_solo-#{n},#{Metasploit::Credential::Password.name},falcon_chief,,,,,,#{login_status},#{access_level},#{last_attempted_at},,,,,#{login_status},#{access_level},#{last_attempted_at}
|
48
|
+
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,,,,,,#{login_status},#{access_level},#{last_attempted_at},,,,,#{login_status},#{access_level},#{last_attempted_at}
|
49
|
+
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,,,,,,#{login_status},#{access_level},#{last_attempted_at},,,,,#{login_status},#{access_level},#{last_attempted_at}
|
44
50
|
eos
|
45
51
|
StringIO.new(csv_string)
|
46
52
|
end
|
@@ -51,10 +57,10 @@ lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,,
|
|
51
57
|
# Contains core with a blank Public
|
52
58
|
sequence :well_formed_csv_compliant_header_missing_public do |n|
|
53
59
|
csv_string =<<-eos
|
54
|
-
|
55
|
-
,#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
56
|
-
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
57
|
-
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins
|
60
|
+
#{long_form_headers}
|
61
|
+
,#{Metasploit::Credential::Password.name},falcon_chief,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
62
|
+
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
63
|
+
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins,,,,,#{login_status},#{access_level},#{last_attempted_at}
|
58
64
|
eos
|
59
65
|
StringIO.new(csv_string)
|
60
66
|
end
|
@@ -65,7 +71,7 @@ lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit:
|
|
65
71
|
# Contains core with a blank Private
|
66
72
|
sequence :well_formed_csv_compliant_header_missing_private do |n|
|
67
73
|
csv_string =<<-eos
|
68
|
-
|
74
|
+
#{long_form_headers}
|
69
75
|
han_solo,,,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
70
76
|
princessl-#{n},#{Metasploit::Credential::Password.name},bagel_head,#{Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN},Rebels
|
71
77
|
lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit::Model::Realm::Key::ORACLE_SYSTEM_IDENTIFIER},dstar_admins
|
@@ -78,7 +84,7 @@ lord_vader-#{n},#{Metasploit::Credential::Password.name},evilisfun,#{Metasploit:
|
|
78
84
|
# Conforms to "short" form, in which only username and private_data are specified in the file
|
79
85
|
sequence :short_well_formed_csv do |n|
|
80
86
|
csv_string =<<-eos
|
81
|
-
|
87
|
+
#{short_form_headers}
|
82
88
|
han_solo-#{n},falC0nBaws
|
83
89
|
princessl-#{n},bagelHead
|
84
90
|
eos
|
@@ -116,7 +122,7 @@ foo,{"""}
|
|
116
122
|
# We have a header row but nothing else
|
117
123
|
sequence :empty_core_csv do |n|
|
118
124
|
csv_string =<<-eos
|
119
|
-
|
125
|
+
#{long_form_headers}
|
120
126
|
eos
|
121
127
|
StringIO.new(csv_string)
|
122
128
|
end
|
@@ -59,69 +59,76 @@ describe Metasploit::Credential::Exporter::Core do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
describe "#line_for_core" do
|
62
|
+
let(:result_hash) { core_exporter.line_for_core(core) }
|
63
|
+
|
62
64
|
it 'should produce values in the proper order' do
|
63
|
-
|
64
|
-
|
65
|
+
result_hash.values.should == [core.public.username, core.private.type,
|
66
|
+
core.private.data, core.realm.key, core.realm.value]
|
65
67
|
end
|
66
68
|
|
67
69
|
it 'should produce a hash with the public username' do
|
68
|
-
result_hash = core_exporter.line_for_core(core)
|
69
70
|
result_hash[:username].should == core.public.username
|
70
71
|
end
|
71
72
|
|
72
73
|
it 'should produce a hash with the private data' do
|
73
|
-
result_hash = core_exporter.line_for_core(core)
|
74
74
|
result_hash[:private_data].should == core.private.data
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'should produce a hash with the name of the private type' do
|
78
|
-
result_hash = core_exporter.line_for_core(core)
|
79
78
|
result_hash[:private_type].should == core.private.type
|
80
79
|
end
|
81
80
|
end
|
82
81
|
|
83
82
|
describe "#line_for_login" do
|
84
83
|
let(:login){ FactoryGirl.create(:metasploit_credential_login, core: core, service: service) }
|
84
|
+
let(:result_hash) { core_exporter.line_for_login(login) }
|
85
85
|
|
86
86
|
it 'should produce values in the proper order' do
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
87
|
+
result_hash.values.should == [core.public.username, core.private.type,
|
88
|
+
core.private.data, core.realm.key, core.realm.value,
|
89
|
+
login.service.host.address, login.service.port,
|
90
|
+
login.service.name, login.service.proto,
|
91
|
+
login.status, login.access_level, login.last_attempted_at
|
92
|
+
]
|
91
93
|
end
|
92
94
|
|
93
95
|
it 'should produce a hash with the service host address' do
|
94
|
-
result_hash = core_exporter.line_for_login(login)
|
95
96
|
result_hash[:host_address].should == login.service.host.address
|
96
97
|
end
|
97
98
|
|
98
99
|
it 'should produce a hash with the service port' do
|
99
|
-
result_hash = core_exporter.line_for_login(login)
|
100
100
|
result_hash[:service_port].should == login.service.port
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'should produce a hash with the service name' do
|
104
|
-
result_hash = core_exporter.line_for_login(login)
|
105
104
|
result_hash[:service_name].should == login.service.name
|
106
105
|
end
|
107
106
|
|
108
107
|
it 'should produce a hash with the service protocol' do
|
109
|
-
result_hash = core_exporter.line_for_login(login)
|
110
108
|
result_hash[:service_protocol].should == login.service.proto
|
111
109
|
end
|
112
110
|
|
111
|
+
it 'should produce a hash with the login status' do
|
112
|
+
result_hash[:status].should == login.status
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should produce a hash with the login access_level' do
|
116
|
+
result_hash[:access_level].should == login.access_level
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should produce a hash with the login last_attempted_at' do
|
120
|
+
result_hash[:last_attempted_at].should == login.last_attempted_at
|
121
|
+
end
|
122
|
+
|
113
123
|
it 'should produce a hash with the public information' do
|
114
|
-
result_hash = core_exporter.line_for_login(login)
|
115
124
|
result_hash[:username].should == login.core.public.username
|
116
125
|
end
|
117
126
|
|
118
127
|
it 'should produce a hash with the private data' do
|
119
|
-
result_hash = core_exporter.line_for_login(login)
|
120
128
|
result_hash[:private_data].should == login.core.private.data
|
121
129
|
end
|
122
130
|
|
123
|
-
it 'should produce a hash with the demodulized name of the
|
124
|
-
result_hash = core_exporter.line_for_login(login)
|
131
|
+
it 'should produce a hash with the demodulized name of the private type' do
|
125
132
|
result_hash[:private_type].should == login.core.private.type
|
126
133
|
end
|
127
134
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metasploit-credential
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.13.
|
4
|
+
version: 0.13.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Imhoff
|
@@ -310,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
310
310
|
version: '0'
|
311
311
|
requirements: []
|
312
312
|
rubyforge_project:
|
313
|
-
rubygems_version: 2.4.
|
313
|
+
rubygems_version: 2.4.5
|
314
314
|
signing_key:
|
315
315
|
specification_version: 4
|
316
316
|
summary: Credential models for metasploit-framework and Metasploit Pro
|