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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTI2NTNmNzJkMWE3MzRjMTYxZjk5NDE4YjFiOWVkM2I3YTZkYzE2OQ==
4
+ ODI2ZjA2Nzg2ODU2YmRlNDlmODA5N2UzYTcyNmVlM2FlMjQ1MjdkYQ==
5
5
  data.tar.gz: !binary |-
6
- N2IzZWIyZDk4NTUxMDJjMDY5NjFkZTBjM2I0YWY1OGZiZjE1ZGU5NA==
6
+ YmNjNWJkM2UyMDVkYzMwZTQxODU3YTRiMThhMjA1NGIwYjJjODNjMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzY4ZDdmYmVkYzM1NTAzNzU3OWU2NWQwYTA5ODQ5ODcyNzViNzUxNTQyOGM5
10
- Y2RjMjIwYjEwMDdkYTQwOTk2MzQ3ZWZmOWJhMTE5ODJlNDQxZDk3NTBiNjNm
11
- YWUwOGRmZjBlY2FhYWQ3OGJhMmFkMGVkNmYzOWQ3NmI3M2U2YzM=
9
+ Mjc3ODk2NTk3Mjg3NzZkODc0YzM4MmE1YTE5OTYxNzE1MDNiMjIxMGJjMmZl
10
+ Y2FhODdlOTllZThlOGMwZDhmNThhMDFlOWEzZTI4NDNmYjMzMTVjOWE5NjVk
11
+ YTk0YjcyZWNlZmUyZmEyNWViMTE1MGFmMzE1MjMzMmIzM2VjN2U=
12
12
  data.tar.gz: !binary |-
13
- OGQyMWQyOTNjMmI4ZGY1OWEwNGNjNWRmMGIyZGMwYmUxYjBkMmFjMGRiNzIw
14
- OWJmZjI4ODBhZWVkZmQ5NTI1YzQ4Yjg2ZjJjMjhjZThiYmQ4NzlmODczZmEz
15
- NDFiMTUxNzAyOGM3NjI1YjhkZWNiZDAxN2RkNWYwNzBmZDIwYTU=
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, :realm_key, :realm_value, :host_address, :service_port, :service_name, :service_protocol]
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 = row['host_address']
111
- service_port = row['service_port']
112
- service_protocol = row['service_protocol']
113
- service_name = row['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
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
- defaults: &defaults
2
+ development: &pgsql
3
3
  adapter: postgresql
4
- username: msf
5
- password: pass123
4
+ database: metasploit_credential_development
6
5
  host: localhost
7
6
  port: 5432
8
- pool: 50
7
+ pool: 5
9
8
  timeout: 5
10
9
 
11
- development:
12
- database: metasploit_cr
13
- <<: *defaults
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
- database: metasploit_cr_test
17
- min_messages: WARNING
18
- <<: *defaults
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
- origin {FactoryGirl.build :metasploit_credential_origin_import }
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- username,private_data
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
- username,private_type,private_data,realm_key,realm_value,host_address,service_port,service_name,service_protocol
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
- core_exporter.line_for_core(core).values.should == [core.public.username, core.private.type,
64
- core.private.data, core.realm.key, core.realm.value]
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
- core_exporter.line_for_login(login).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]
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 private type' do
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.10
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.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