metasploit_data_models 0.23.1 → 0.23.2

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/mdm/host.rb +42 -33
  3. data/app/models/mdm/loot.rb +9 -0
  4. data/app/models/mdm/module/detail.rb +28 -7
  5. data/app/models/mdm/module/ref.rb +4 -4
  6. data/app/models/mdm/ref.rb +5 -5
  7. data/app/models/mdm/session.rb +18 -1
  8. data/app/models/mdm/user.rb +13 -0
  9. data/app/models/mdm/vuln.rb +16 -7
  10. data/app/models/mdm/workspace.rb +16 -8
  11. data/app/models/metasploit_data_models/automatic_exploitation.rb +5 -0
  12. data/app/models/metasploit_data_models/automatic_exploitation/match.rb +42 -0
  13. data/app/models/metasploit_data_models/automatic_exploitation/match_result.rb +40 -0
  14. data/app/models/metasploit_data_models/automatic_exploitation/match_set.rb +30 -0
  15. data/app/models/metasploit_data_models/automatic_exploitation/run.rb +27 -0
  16. data/app/models/metasploit_data_models/module_run.rb +213 -0
  17. data/app/validators/password_is_strong_validator.rb +5 -5
  18. data/db/migrate/20131002004641_create_automatic_exploitation_matches.rb +13 -0
  19. data/db/migrate/20131002164449_create_automatic_exploitation_match_sets.rb +12 -0
  20. data/db/migrate/20131008213344_create_automatic_exploitation_runs.rb +11 -0
  21. data/db/migrate/20131011184338_module_detail_on_automatic_exploitation_match.rb +10 -0
  22. data/db/migrate/20131017150735_create_automatic_exploitation_match_results.rb +11 -0
  23. data/db/migrate/20131021185657_make_match_polymorphic.rb +11 -0
  24. data/db/migrate/20150219173821_create_module_runs.rb +23 -0
  25. data/db/migrate/20150219215039_add_module_run_to_session.rb +8 -0
  26. data/db/migrate/20150226151459_add_module_run_fk_to_loot.rb +8 -0
  27. data/db/migrate/20150312155312_add_module_full_name_to_match.rb +6 -0
  28. data/db/migrate/20150326183742_add_missing_ae_indices.rb +13 -0
  29. data/lib/metasploit_data_models/version.rb +1 -1
  30. data/spec/app/models/mdm/host_spec.rb +28 -27
  31. data/spec/app/models/mdm/loot_spec.rb +1 -0
  32. data/spec/app/models/mdm/module/detail_spec.rb +2 -2
  33. data/spec/app/models/mdm/session_spec.rb +21 -18
  34. data/spec/app/models/mdm/vuln_spec.rb +9 -10
  35. data/spec/app/models/metasploit_data_models/automatic_exploitation/match_result_spec.rb +88 -0
  36. data/spec/app/models/metasploit_data_models/automatic_exploitation/match_set_spec.rb +48 -0
  37. data/spec/app/models/metasploit_data_models/automatic_exploitation/match_spec.rb +25 -0
  38. data/spec/app/models/metasploit_data_models/automatic_exploitation/run_spec.rb +40 -0
  39. data/spec/app/models/metasploit_data_models/module_run_spec.rb +136 -0
  40. data/spec/dummy/db/structure.sql +369 -2
  41. data/spec/factories/mdm/module/details.rb +21 -21
  42. data/spec/factories/metasploit_data_models/automatic_exploitation/match_results.rb +7 -0
  43. data/spec/factories/metasploit_data_models/automatic_exploitation/match_sets.rb +8 -0
  44. data/spec/factories/metasploit_data_models/automatic_exploitation/matches.rb +6 -0
  45. data/spec/factories/metasploit_data_models/automatic_exploitation/runs.rb +6 -0
  46. data/spec/factories/module_runs.rb +40 -0
  47. metadata +30 -172
@@ -0,0 +1,12 @@
1
+ class CreateAutomaticExploitationMatchSets < ActiveRecord::Migration
2
+ def change
3
+ create_table :automatic_exploitation_match_sets do |t|
4
+ t.integer :workspace_id
5
+ t.integer :user_id
6
+
7
+ t.timestamps
8
+ end
9
+ add_index :automatic_exploitation_match_sets, :user_id
10
+ add_index :automatic_exploitation_match_sets, :workspace_id
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateAutomaticExploitationRuns < ActiveRecord::Migration
2
+ def change
3
+ create_table :automatic_exploitation_runs do |t|
4
+ t.integer :workspace_id
5
+ t.integer :user_id
6
+ t.integer :match_set_id
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ class ModuleDetailOnAutomaticExploitationMatch < ActiveRecord::Migration
2
+ def up
3
+ rename_column :automatic_exploitation_matches, :ref_id, :module_detail_id
4
+ add_column :automatic_exploitation_matches, :match_set_id, :integer
5
+ end
6
+
7
+ def down
8
+ rename_column :automatic_exploitation_matches, :module_detail_id, :ref_id
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ class CreateAutomaticExploitationMatchResults < ActiveRecord::Migration
2
+ def change
3
+ create_table :automatic_exploitation_match_results do |t|
4
+ t.integer :match_id
5
+ t.integer :run_id
6
+ t.string :state, null: false
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class MakeMatchPolymorphic < ActiveRecord::Migration
2
+ def up
3
+ add_column :automatic_exploitation_matches, :matchable_type, :string
4
+ add_column :automatic_exploitation_matches, :matchable_id, :integer
5
+ end
6
+
7
+ def down
8
+ remove_column :automatic_exploitation_matches, :matchable_type
9
+ remove_column :automatic_exploitation_matches, :matchable_id
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ class CreateModuleRuns < ActiveRecord::Migration
2
+ def change
3
+ create_table :module_runs do |t|
4
+ t.datetime :attempted_at
5
+ t.text :fail_detail
6
+ t.string :fail_reason
7
+ t.text :module_fullname
8
+ t.integer :port
9
+ t.string :proto
10
+ t.integer :session_id
11
+ t.string :status
12
+ t.integer :trackable_id
13
+ t.string :trackable_type
14
+ t.integer :user_id
15
+ t.string :username
16
+
17
+ t.timestamps
18
+ end
19
+
20
+ add_index :module_runs, :session_id
21
+ add_index :module_runs, :user_id
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ class AddModuleRunToSession < ActiveRecord::Migration
2
+ def change
3
+ change_table :sessions do |t|
4
+ t.integer :module_run_id
5
+ end
6
+ add_index :sessions, :module_run_id
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class AddModuleRunFkToLoot < ActiveRecord::Migration
2
+ def change
3
+ change_table(:loots) do |t|
4
+ t.integer :module_run_id
5
+ t.index :module_run_id
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ class AddModuleFullNameToMatch < ActiveRecord::Migration
2
+ def change
3
+ add_column :automatic_exploitation_matches, :module_fullname, :text
4
+ add_index :automatic_exploitation_matches, :module_fullname
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ class AddMissingAeIndices < ActiveRecord::Migration
2
+ def up
3
+ add_index :automatic_exploitation_match_results, :match_id
4
+ add_index :automatic_exploitation_match_results, :run_id
5
+
6
+ add_index :automatic_exploitation_runs, :match_set_id
7
+ add_index :automatic_exploitation_runs, :user_id
8
+ add_index :automatic_exploitation_runs, :workspace_id
9
+ end
10
+
11
+ def down
12
+ end
13
+ end
@@ -6,7 +6,7 @@ module MetasploitDataModels
6
6
  # The minor version number, scoped to the {MAJOR} version number.
7
7
  MINOR = 23
8
8
  # The patch number, scoped to the {MAJOR} and {MINOR} version numbers.
9
- PATCH = 1
9
+ PATCH = 2
10
10
 
11
11
  # The full version string, including the {MAJOR}, {MINOR}, {PATCH}, and optionally, the `PRERELEASE` in the
12
12
  # {http://semver.org/spec/v2.0.0.html semantic versioning v2.0.0} format.
@@ -102,7 +102,7 @@ describe Mdm::Host do
102
102
  end
103
103
  end
104
104
 
105
- context 'associations' do
105
+ context 'associations' do
106
106
  it { should have_many(:creds).class_name('Mdm::Cred').through(:services) }
107
107
  it { should have_many(:clients).class_name('Mdm::Client').dependent(:destroy) }
108
108
  it { should have_many(:exploit_attempts).class_name('Mdm::ExploitAttempt').dependent(:destroy) }
@@ -110,6 +110,7 @@ describe Mdm::Host do
110
110
  it { should have_many(:host_details).class_name('Mdm::HostDetail').dependent(:destroy) }
111
111
  it { should have_many(:hosts_tags).class_name('Mdm::HostTag') }
112
112
  it { should have_many(:loots).class_name('Mdm::Loot').dependent(:destroy).order('loots.created_at DESC') }
113
+ it { should have_many(:module_runs).class_name('MetasploitDataModels::ModuleRun') }
113
114
  it { should have_many(:task_hosts).class_name('Mdm::TaskHost').dependent(:destroy) }
114
115
  it { should have_many(:tasks).class_name('Mdm::Task').through(:task_hosts) }
115
116
 
@@ -208,9 +209,9 @@ describe Mdm::Host do
208
209
  it { should have_many(:vuln_refs).class_name('Mdm::VulnRef') }
209
210
  it { should have_many(:web_sites).class_name('Mdm::WebSite').through(:services) }
210
211
  it { should belong_to(:workspace).class_name('Mdm::Workspace') }
211
- end
212
+ end
212
213
 
213
- context 'CONSTANTS' do
214
+ context 'CONSTANTS' do
214
215
  context 'ARCHITECTURES' do
215
216
  subject(:architectures) do
216
217
  described_class::ARCHITECTURES
@@ -285,30 +286,30 @@ describe Mdm::Host do
285
286
 
286
287
  end
287
288
 
288
- context 'SEARCH_FIELDS' do
289
- subject(:search_fields) do
290
- described_class::SEARCH_FIELDS
291
- end
292
-
293
- it 'should be an Array<String>' do
294
- search_fields.should be_an Array
295
-
296
- search_fields.each { |search_field|
297
- search_field.should be_a String
298
- }
299
- end
300
-
301
- it 'should cast address to text' do
302
- search_fields.should include('address::text')
303
- end
304
-
305
- it { should include('comments') }
306
- it { should include('mac') }
307
- it { should include('name') }
308
- it { should include('os_flavor') }
309
- it { should include('os_name') }
310
- it { should include('os_sp') }
311
- it { should include('purpose') }
289
+ context 'SEARCH_FIELDS' do
290
+ subject(:search_fields) do
291
+ described_class::SEARCH_FIELDS
292
+ end
293
+
294
+ it 'should be an Array<String>' do
295
+ search_fields.should be_an Array
296
+
297
+ search_fields.each { |search_field|
298
+ search_field.should be_a String
299
+ }
300
+ end
301
+
302
+ it 'should cast address to text' do
303
+ search_fields.should include('address::text')
304
+ end
305
+
306
+ it { should include('comments') }
307
+ it { should include('mac') }
308
+ it { should include('name') }
309
+ it { should include('os_flavor') }
310
+ it { should include('os_name') }
311
+ it { should include('os_sp') }
312
+ it { should include('purpose') }
312
313
  end
313
314
 
314
315
  it 'should define STATES in any order' do
@@ -7,6 +7,7 @@ describe Mdm::Loot do
7
7
  it { should belong_to(:workspace).class_name('Mdm::Workspace') }
8
8
  it { should belong_to(:service).class_name('Mdm::Service') }
9
9
  it { should belong_to(:host).class_name('Mdm::Host') }
10
+ it { should belong_to(:module_run).class_name('MetasploitDataModels::ModuleRun') }
10
11
  end
11
12
 
12
13
  context 'database' do
@@ -430,5 +430,5 @@ describe Mdm::Module::Detail do
430
430
  its(:name) { should == name }
431
431
  end
432
432
  end
433
- end
434
- end
433
+ end
434
+ end
@@ -25,31 +25,34 @@ describe Mdm::Session do
25
25
  context 'database' do
26
26
 
27
27
  context 'timestamps'do
28
- it { should have_db_column(:opened_at).of_type(:datetime).with_options(:null => false) }
29
- it { should have_db_column(:closed_at).of_type(:datetime) }
30
- it { should have_db_column(:last_seen).of_type(:datetime) }
28
+ it { is_expected.to have_db_column(:closed_at).of_type(:datetime) }
29
+ it { is_expected.to have_db_column(:last_seen).of_type(:datetime) }
30
+ it { is_expected.to have_db_column(:opened_at).of_type(:datetime).with_options(:null => false) }
31
31
  end
32
32
 
33
33
  context 'columns' do
34
- it { should have_db_column(:host_id).of_type(:integer) }
35
- it { should have_db_column(:stype).of_type(:string) }
36
- it { should have_db_column(:via_exploit).of_type(:string) }
37
- it { should have_db_column(:via_payload).of_type(:string) }
38
- it { should have_db_column(:desc).of_type(:string) }
39
- it { should have_db_column(:port).of_type(:integer) }
40
- it { should have_db_column(:platform).of_type(:string) }
41
- it { should have_db_column(:datastore).of_type(:text) }
42
- it { should have_db_column(:local_id).of_type(:integer) }
34
+ it { is_expected.to have_db_column(:datastore).of_type(:text) }
35
+ it { is_expected.to have_db_column(:desc).of_type(:string) }
36
+ it { is_expected.to have_db_column(:host_id).of_type(:integer) }
37
+ it { is_expected.to have_db_column(:local_id).of_type(:integer) }
38
+ it { is_expected.to have_db_column(:module_run_id).of_type(:integer) }
39
+ it { is_expected.to have_db_column(:platform).of_type(:string) }
40
+ it { is_expected.to have_db_column(:port).of_type(:integer) }
41
+ it { is_expected.to have_db_column(:stype).of_type(:string) }
42
+ it { is_expected.to have_db_column(:via_exploit).of_type(:string) }
43
+ it { is_expected.to have_db_column(:via_payload).of_type(:string) }
43
44
  end
44
45
  end
45
46
 
46
47
  context 'associations' do
47
- it { should belong_to(:host).class_name('Mdm::Host') }
48
- it { should have_many(:events).class_name('Mdm::SessionEvent').dependent(:delete_all) }
49
- it { should have_many(:routes).class_name('Mdm::Route').dependent(:delete_all) }
50
- it { should have_one(:workspace).class_name('Mdm::Workspace').through(:host) }
51
- it { should have_many(:task_sessions).class_name('Mdm::TaskSession').dependent(:destroy)}
52
- it { should have_many(:tasks).class_name('Mdm::Task').through(:task_sessions)}
48
+ it { is_expected.to have_many(:events).class_name('Mdm::SessionEvent').dependent(:delete_all) }
49
+ it { is_expected.to belong_to(:host).class_name('Mdm::Host') }
50
+ it { is_expected.to belong_to(:originating_module_run).class_name('MetasploitDataModels::ModuleRun') }
51
+ it { is_expected.to have_many(:routes).class_name('Mdm::Route').dependent(:delete_all) }
52
+ it { is_expected.to have_many(:target_module_runs).class_name('MetasploitDataModels::ModuleRun') }
53
+ it { is_expected.to have_many(:tasks).class_name('Mdm::Task').through(:task_sessions)}
54
+ it { is_expected.to have_many(:task_sessions).class_name('Mdm::TaskSession').dependent(:destroy) }
55
+ it { is_expected.to have_one(:workspace).class_name('Mdm::Workspace').through(:host) }
53
56
  end
54
57
 
55
58
  context 'scopes' do
@@ -33,16 +33,15 @@ describe Mdm::Vuln do
33
33
 
34
34
 
35
35
  context 'associations' do
36
- it { should belong_to(:host).class_name('Mdm::Host') }
37
- it { should belong_to(:service).class_name('Mdm::Service') }
38
- it { should have_many(:module_refs).class_name('Mdm::Module::Ref').through(:refs) }
39
- # @todo https://www.pivotaltracker.com/story/show/49004623
40
- it { should have_many(:refs).class_name('Mdm::Ref').through(:vulns_refs) }
41
- it { should have_many(:vuln_attempts).class_name('Mdm::VulnAttempt').dependent(:destroy) }
42
- it { should have_many(:vuln_details).class_name('Mdm::VulnDetail').dependent(:destroy) }
43
- # @todo https://www.pivotaltracker.com/story/show/49004623
44
- it { should have_many(:vulns_refs).class_name('Mdm::VulnRef').dependent(:destroy) }
45
- it { should have_many(:notes).class_name('Mdm::Note').dependent(:delete_all).order('notes.created_at') }
36
+ it { is_expected.to belong_to(:host).class_name('Mdm::Host') }
37
+ it { is_expected.to belong_to(:service).class_name('Mdm::Service') }
38
+ it { is_expected.to have_many(:module_refs).class_name('Mdm::Module::Ref').through(:refs) }
39
+ it { is_expected.to have_many(:module_runs).class_name('MetasploitDataModels::ModuleRun') }
40
+ it { is_expected.to have_many(:refs).class_name('Mdm::Ref').through(:vulns_refs) }
41
+ it { is_expected.to have_many(:vuln_attempts).class_name('Mdm::VulnAttempt').dependent(:destroy) }
42
+ it { is_expected.to have_many(:vuln_details).class_name('Mdm::VulnDetail').dependent(:destroy) }
43
+ it { is_expected.to have_many(:vulns_refs).class_name('Mdm::VulnRef').dependent(:destroy) }
44
+ it { is_expected.to have_many(:notes).class_name('Mdm::Note').dependent(:delete_all).order('notes.created_at') }
46
45
 
47
46
  context 'module_details' do
48
47
  it { should have_many(:module_details).class_name('Mdm::Module::Detail').through(:module_refs) }
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::AutomaticExploitation::MatchResult do
4
+ it_should_behave_like 'Metasploit::Concern.run'
5
+
6
+ context "database" do
7
+ it { is_expected.to have_db_column(:match_id).of_type(:integer) }
8
+ it { is_expected.to have_db_index(:match_id) }
9
+ it { is_expected.to have_db_column(:run_id).of_type(:integer) }
10
+ it { is_expected.to have_db_index(:run_id) }
11
+ end
12
+
13
+ context 'associations' do
14
+ it { should belong_to(:match).class_name('MetasploitDataModels::AutomaticExploitation::Match') }
15
+ it { should belong_to(:run).class_name('MetasploitDataModels::AutomaticExploitation::Run') }
16
+ end
17
+
18
+ context 'scopes' do
19
+ before do
20
+ match_failed = FactoryGirl.create(:automatic_exploitation_match)
21
+ match_succeeded = FactoryGirl.create(:automatic_exploitation_match)
22
+ run = FactoryGirl.create(:automatic_exploitation_run)
23
+
24
+ described_class.create do |match_result|
25
+ match_result.match = match_failed
26
+ match_result.run = run
27
+ match_result.state = MetasploitDataModels::AutomaticExploitation::MatchResult::SUCCEEDED
28
+ end
29
+
30
+ described_class.create do |match_result|
31
+ match_result.match = match_succeeded
32
+ match_result.run = run
33
+ match_result.state = MetasploitDataModels::AutomaticExploitation::MatchResult::FAILED
34
+ end
35
+ end
36
+
37
+ context 'succeeded' do
38
+ subject(:succeeded) do
39
+ described_class.succeeded
40
+ end
41
+
42
+ specify 'returns only successful results' do
43
+ expect(succeeded.count).to eq(1)
44
+ expect(succeeded.first.state).to eq(MetasploitDataModels::AutomaticExploitation::MatchResult::SUCCEEDED)
45
+ end
46
+ end
47
+
48
+ context 'failed' do
49
+ subject(:failed) do
50
+ described_class.failed
51
+ end
52
+
53
+ specify 'returns only failed results' do
54
+ expect(failed.count).to eq(1)
55
+ expect(failed.first.state).to eq(MetasploitDataModels::AutomaticExploitation::MatchResult::FAILED)
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'validations' do
61
+ context 'state' do
62
+ subject(:match_result) do
63
+ FactoryGirl.build(:automatic_exploitation_match_result, state: state)
64
+ end
65
+ context 'with nil' do
66
+ let(:state) { nil }
67
+ specify do
68
+ expect(match_result).not_to be_valid
69
+ expect(match_result.errors[:state]).to include("can't be blank")
70
+ end
71
+ end
72
+ context 'with "asdf"' do
73
+ let(:state) { "asdf" }
74
+ specify do
75
+ expect(match_result).not_to be_valid
76
+ expect(match_result.errors[:state]).to include("is not included in the list")
77
+ end
78
+ end
79
+ context 'with "succeeded"' do
80
+ let(:state) { MetasploitDataModels::AutomaticExploitation::MatchResult::SUCCEEDED }
81
+ specify do
82
+ expect(match_result).to be_valid
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe MetasploitDataModels::AutomaticExploitation::MatchSet do
4
+ describe "database" do
5
+ describe "foreign_keys" do
6
+ it { should have_db_column(:workspace_id).of_type(:integer) }
7
+ it { should have_db_column(:user_id).of_type(:integer) }
8
+ end
9
+
10
+ describe "indices" do
11
+ it { should have_db_index(:user_id) }
12
+ it { should have_db_index(:workspace_id) }
13
+ end
14
+ end
15
+
16
+ describe "associations" do
17
+ it { should have_many(:matches).class_name('MetasploitDataModels::AutomaticExploitation::Match') }
18
+ it { should have_many(:matches).inverse_of(:match_set) }
19
+ it { should have_many(:runs).class_name('MetasploitDataModels::AutomaticExploitation::Run') }
20
+ it { should have_many(:runs).inverse_of(:match_set) }
21
+ it { should belong_to(:user).class_name('Mdm::User') }
22
+ it { should belong_to(:user).inverse_of(:automatic_exploitation_match_sets) }
23
+ it { should belong_to(:workspace).class_name('Mdm::Workspace') }
24
+ it { should belong_to(:workspace).inverse_of(:automatic_exploitation_match_sets) }
25
+ end
26
+
27
+ describe "validations" do
28
+ subject(:match_set){ FactoryGirl.build(:automatic_exploitation_match_set)}
29
+
30
+ describe "missing user" do
31
+ before(:each) do
32
+ match_set.user = nil
33
+ end
34
+
35
+ it{ is_expected.to be_invalid }
36
+ end
37
+
38
+ describe "missing workspace" do
39
+ before(:each) do
40
+ match_set.workspace = nil
41
+ end
42
+
43
+ it{ is_expected.to be_invalid }
44
+ end
45
+
46
+ end
47
+
48
+ end