metasploit_data_models 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/Gemfile +2 -0
  2. data/app/models/mdm/client.rb +0 -1
  3. data/app/models/mdm/cred.rb +1 -1
  4. data/app/models/mdm/exploited_host.rb +0 -1
  5. data/app/models/mdm/listener.rb +2 -1
  6. data/app/models/mdm/nexpose_console.rb +2 -2
  7. data/app/models/mdm/session.rb +5 -1
  8. data/app/models/mdm/workspace.rb +0 -1
  9. data/db/migrate/20130525015035_remove_campaign_id_from_clients.rb +9 -0
  10. data/db/migrate/20130525212420_drop_table_imported_creds.rb +14 -0
  11. data/db/migrate/20130531144949_making_host_tags_a_real_ar_model.rb +6 -0
  12. data/lib/mdm/host/operating_system_normalization.rb +4 -4
  13. data/lib/metasploit_data_models/version.rb +1 -1
  14. data/spec/app/models/mdm/client_spec.rb +43 -0
  15. data/spec/app/models/mdm/cred_spec.rb +211 -0
  16. data/spec/app/models/mdm/events_spec.rb +85 -0
  17. data/spec/app/models/mdm/exploit_attempt_spec.rb +60 -0
  18. data/spec/app/models/mdm/exploited_host_spec.rb +44 -0
  19. data/spec/app/models/mdm/host_detail_spec.rb +49 -0
  20. data/spec/app/models/mdm/host_spec.rb +468 -0
  21. data/spec/app/models/mdm/host_tag_spec.rb +26 -0
  22. data/spec/app/models/mdm/listener_spec.rb +108 -0
  23. data/spec/app/models/mdm/loot_spec.rb +77 -0
  24. data/spec/app/models/mdm/nexpose_console_spec.rb +128 -0
  25. data/spec/app/models/mdm/note_spec.rb +84 -0
  26. data/spec/app/models/mdm/ref_spec.rb +13 -0
  27. data/spec/app/models/mdm/report_spec.rb +104 -0
  28. data/spec/app/models/mdm/report_template_spec.rb +52 -0
  29. data/spec/app/models/mdm/route_spec.rb +36 -0
  30. data/spec/app/models/mdm/service_spec.rb +70 -15
  31. data/spec/app/models/mdm/session_event_spec.rb +42 -0
  32. data/spec/app/models/mdm/session_spec.rb +114 -0
  33. data/spec/app/models/mdm/tag_spec.rb +104 -0
  34. data/spec/app/models/mdm/task_creds_spec.rb +32 -0
  35. data/spec/app/models/mdm/task_host_spec.rb +33 -0
  36. data/spec/app/models/mdm/task_service_spec.rb +33 -0
  37. data/spec/app/models/mdm/task_spec.rb +59 -5
  38. data/spec/app/models/mdm/user_spec.rb +51 -0
  39. data/spec/app/models/mdm/vuln_attempt_spec.rb +54 -0
  40. data/spec/app/models/mdm/vuln_details_spec.rb +66 -0
  41. data/spec/app/models/mdm/vuln_ref_spec.rb +24 -0
  42. data/spec/app/models/mdm/vuln_spec.rb +25 -0
  43. data/spec/app/models/mdm/web_form_spec.rb +47 -0
  44. data/spec/app/models/mdm/web_page_spec.rb +55 -0
  45. data/spec/app/models/mdm/web_site_spec.rb +86 -0
  46. data/spec/app/models/mdm/web_vuln_spec.rb +12 -0
  47. data/spec/app/models/mdm/workspace_spec.rb +567 -0
  48. data/spec/dummy/db/schema.rb +5 -13
  49. data/spec/factories/mdm/addresses.rb +5 -0
  50. data/spec/factories/mdm/clients.rb +8 -0
  51. data/spec/factories/mdm/events.rb +15 -0
  52. data/spec/factories/mdm/exploit_attempts.rb +8 -0
  53. data/spec/factories/mdm/exploited_hosts.rb +7 -0
  54. data/spec/factories/mdm/fingerprints/nessus_fingerprints.rb +6 -0
  55. data/spec/factories/mdm/fingerprints/nexpose_fingerprints.rb +6 -0
  56. data/spec/factories/mdm/fingerprints/nmap_fingerprints.rb +6 -0
  57. data/spec/factories/mdm/fingerprints/retina_fingerprints.rb +6 -0
  58. data/spec/factories/mdm/fingerprints/session_fingerprints.rb +6 -0
  59. data/spec/factories/mdm/host_details.rb +8 -0
  60. data/spec/factories/mdm/listeners.rb +12 -0
  61. data/spec/factories/mdm/loots.rb +11 -0
  62. data/spec/factories/mdm/nexpose_consoles.rb +15 -0
  63. data/spec/factories/mdm/notes.rb +12 -0
  64. data/spec/factories/mdm/report_templates.rb +8 -0
  65. data/spec/factories/mdm/reports.rb +13 -0
  66. data/spec/factories/mdm/routes.rb +36 -0
  67. data/spec/factories/mdm/session_events.rb +8 -0
  68. data/spec/factories/mdm/sessions.rb +13 -0
  69. data/spec/factories/mdm/vuln_attempts.rb +8 -0
  70. data/spec/factories/mdm/vuln_details.rb +8 -0
  71. data/spec/factories/mdm/web_forms.rb +33 -0
  72. data/spec/factories/mdm/web_pages.rb +64 -0
  73. metadata +95 -5
  74. data/app/models/mdm/imported_cred.rb +0 -10
@@ -1,6 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mdm::HostTag do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:host).class_name('Mdm::Host') }
7
+ it { should belong_to(:tag).class_name('Mdm::Tag') }
8
+ end
9
+
10
+ context 'database' do
11
+ context 'columns' do
12
+ it { should have_db_column(:host_id).of_type(:integer) }
13
+ it { should have_db_column(:tag_id).of_type(:integer) }
14
+ end
15
+ end
16
+
4
17
  context 'factories' do
5
18
  context 'mdm_host_tag' do
6
19
  subject(:mdm_host_tag) do
@@ -10,4 +23,17 @@ describe Mdm::HostTag do
10
23
  it { should be_valid }
11
24
  end
12
25
  end
26
+
27
+ context '#destroy' do
28
+ it 'should successfully destroy the object' do
29
+ host_tag = FactoryGirl.create(:mdm_host_tag)
30
+ expect {
31
+ host_tag.destroy
32
+ }.to_not raise_error
33
+ expect {
34
+ host_tag.reload
35
+ }.to raise_error(ActiveRecord::RecordNotFound)
36
+ end
37
+ end
38
+
13
39
  end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Listener do
4
+
5
+ context 'associations' do
6
+ it { should belong_to(:workspace).class_name('Mdm::Workspace') }
7
+ it { should belong_to(:task).class_name('Mdm::Task') }
8
+ end
9
+
10
+ context 'database' do
11
+
12
+ context 'timestamps'do
13
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
14
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
15
+ end
16
+
17
+ context 'columns' do
18
+ it { should have_db_column(:workspace_id).of_type(:integer).with_options(:null => false, :default =>1) }
19
+ it { should have_db_column(:task_id).of_type(:integer) }
20
+ it { should have_db_column(:enabled).of_type(:boolean).with_options(:default => true) }
21
+ it { should have_db_column(:owner).of_type(:text) }
22
+ it { should have_db_column(:payload).of_type(:text) }
23
+ it { should have_db_column(:address).of_type(:text) }
24
+ it { should have_db_column(:port).of_type(:integer) }
25
+ it { should have_db_column(:options).of_type(:binary) }
26
+ it { should have_db_column(:macro).of_type(:text) }
27
+ end
28
+ end
29
+
30
+ context 'factory' do
31
+ it 'should be valid' do
32
+ listener = FactoryGirl.build(:mdm_listener)
33
+ listener.should be_valid
34
+ end
35
+ end
36
+
37
+ context '#destroy' do
38
+ it 'should successfully destroy the object' do
39
+ listener = FactoryGirl.create(:mdm_listener)
40
+ expect {
41
+ listener.destroy
42
+ }.to_not raise_error
43
+ expect {
44
+ listener.reload
45
+ }.to raise_error(ActiveRecord::RecordNotFound)
46
+ end
47
+ end
48
+
49
+ context 'validations' do
50
+ context 'port' do
51
+ it 'should require a port' do
52
+ portless_listener = FactoryGirl.build(:mdm_listener, :port => nil)
53
+ portless_listener.should_not be_valid
54
+ portless_listener.errors[:port].should include("can't be blank")
55
+ end
56
+
57
+ it 'should not be valid for out-of-range numbers' do
58
+ out_of_range = FactoryGirl.build(:mdm_listener, :port => 70000)
59
+ out_of_range.should_not be_valid
60
+ out_of_range.errors[:port].should include("is not included in the list")
61
+ end
62
+
63
+ it 'should not be valid for port 0' do
64
+ out_of_range = FactoryGirl.build(:mdm_listener, :port => 0)
65
+ out_of_range.should_not be_valid
66
+ out_of_range.errors[:port].should include("is not included in the list")
67
+ end
68
+
69
+ it 'should not be valid for decimal numbers' do
70
+ out_of_range = FactoryGirl.build(:mdm_listener, :port => 5.67)
71
+ out_of_range.should_not be_valid
72
+ out_of_range.errors[:port].should include("must be an integer")
73
+ end
74
+
75
+ it 'should not be valid for a negative number' do
76
+ out_of_range = FactoryGirl.build(:mdm_listener, :port => -8)
77
+ out_of_range.should_not be_valid
78
+ out_of_range.errors[:port].should include("is not included in the list")
79
+ end
80
+ end
81
+
82
+ context 'address' do
83
+ it 'should require an address' do
84
+ addressless_listener = FactoryGirl.build(:mdm_listener, :address => nil)
85
+ addressless_listener.should_not be_valid
86
+ addressless_listener.errors[:address].should include("can't be blank")
87
+ end
88
+
89
+ it 'should be valid for IPv4 format' do
90
+ ipv4_listener = FactoryGirl.build(:mdm_listener, :address => '192.168.1.120')
91
+ ipv4_listener.should be_valid
92
+ end
93
+
94
+ it 'should be valid for IPv6 format' do
95
+ ipv6_listener = FactoryGirl.build(:mdm_listener, :address => '2001:0db8:85a3:0000:0000:8a2e:0370:7334')
96
+ ipv6_listener.should be_valid
97
+ end
98
+
99
+ it 'should not be valid for strings not conforming to IPv4 or IPv6' do
100
+ invalid_listener = FactoryGirl.build(:mdm_listener, :address => '1234-fark')
101
+ invalid_listener.should_not be_valid
102
+ end
103
+
104
+ end
105
+ end
106
+
107
+
108
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Loot do
4
+ context 'associations' do
5
+ it { should belong_to(:workspace).class_name('Mdm::Workspace') }
6
+ it { should belong_to(:service).class_name('Mdm::Service') }
7
+ it { should belong_to(:host).class_name('Mdm::Host') }
8
+ end
9
+
10
+ context 'database' do
11
+
12
+ context 'timestamps'do
13
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
14
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
15
+ end
16
+
17
+ context 'columns' do
18
+ it { should have_db_column(:workspace_id).of_type(:integer).with_options(:null => false, :default =>1) }
19
+ it { should have_db_column(:host_id).of_type(:integer) }
20
+ it { should have_db_column(:service_id).of_type(:integer) }
21
+ it { should have_db_column(:ltype).of_type(:string) }
22
+ it { should have_db_column(:path).of_type(:string) }
23
+ it { should have_db_column(:data).of_type(:text) }
24
+ it { should have_db_column(:content_type).of_type(:string) }
25
+ it { should have_db_column(:name).of_type(:text) }
26
+ it { should have_db_column(:info).of_type(:text) }
27
+ end
28
+ end
29
+
30
+ context 'factory' do
31
+ it 'should be valid' do
32
+ loot = FactoryGirl.build(:mdm_loot)
33
+ loot.should be_valid
34
+ end
35
+ end
36
+
37
+ context '#destroy' do
38
+ it 'should successfully destroy the object' do
39
+ loot = FactoryGirl.create(:mdm_loot)
40
+ expect {
41
+ loot.destroy
42
+ }.to_not raise_error
43
+ expect {
44
+ loot.reload
45
+ }.to raise_error(ActiveRecord::RecordNotFound)
46
+ end
47
+ end
48
+
49
+ context 'scopes' do
50
+ context 'search' do
51
+ it 'should match on ltype' do
52
+ myloot = FactoryGirl.create(:mdm_loot, :ltype => 'find.this.ltype')
53
+ Mdm::Loot.search('find.this.ltype').should include(myloot)
54
+ end
55
+
56
+ it 'should match on name' do
57
+ myloot = FactoryGirl.create(:mdm_loot, :name => 'Find This')
58
+ Mdm::Loot.search('Find This').should include(myloot)
59
+ end
60
+
61
+ it 'should match on info' do
62
+ myloot = FactoryGirl.create(:mdm_loot, :info => 'Find This')
63
+ Mdm::Loot.search('Find This').should include(myloot)
64
+ end
65
+ end
66
+ end
67
+
68
+ context 'callbacks' do
69
+ context 'before_destroy' do
70
+ it 'should call #delete_file' do
71
+ myloot = FactoryGirl.create(:mdm_loot)
72
+ myloot.should_receive(:delete_file)
73
+ myloot.destroy
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::NexposeConsole do
4
+
5
+ context 'factory' do
6
+ it 'should be valid' do
7
+ nexpose_console = FactoryGirl.build(:mdm_nexpose_console)
8
+ nexpose_console.should be_valid
9
+ end
10
+ end
11
+
12
+ context 'database' do
13
+
14
+ context 'timestamps'do
15
+ it { should have_db_column(:created_at).of_type(:datetime).with_options(:null => false) }
16
+ it { should have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) }
17
+ end
18
+
19
+ context 'columns' do
20
+ it { should have_db_column(:enabled).of_type(:boolean).with_options(:default => true) }
21
+ it { should have_db_column(:owner).of_type(:text) }
22
+ it { should have_db_column(:address).of_type(:text) }
23
+ it { should have_db_column(:port).of_type(:integer).with_options(:default => 3780) }
24
+ it { should have_db_column(:username).of_type(:text) }
25
+ it { should have_db_column(:password).of_type(:text) }
26
+ it { should have_db_column(:status).of_type(:text) }
27
+ it { should have_db_column(:version).of_type(:text) }
28
+ it { should have_db_column(:cert).of_type(:text) }
29
+ it { should have_db_column(:cached_sites).of_type(:binary) }
30
+ it { should have_db_column(:name).of_type(:text) }
31
+ end
32
+ end
33
+
34
+ context '#destroy' do
35
+ it 'should successfully destroy the object' do
36
+ nexpose_console = FactoryGirl.create(:mdm_nexpose_console)
37
+ expect {
38
+ nexpose_console.destroy
39
+ }.to_not raise_error
40
+ expect {
41
+ nexpose_console.reload
42
+ }.to raise_error(ActiveRecord::RecordNotFound)
43
+ end
44
+ end
45
+
46
+ context 'validations' do
47
+ context 'address' do
48
+ it 'should require an address' do
49
+ addressless_nexpose_console = FactoryGirl.build(:mdm_nexpose_console, :address => nil)
50
+ addressless_nexpose_console.should_not be_valid
51
+ addressless_nexpose_console.errors[:address].should include("can't be blank")
52
+ end
53
+
54
+ it 'should be valid for IPv4 format' do
55
+ ipv4_nexpose_console = FactoryGirl.build(:mdm_nexpose_console, :address => '192.168.1.120')
56
+ ipv4_nexpose_console.should be_valid
57
+ end
58
+
59
+ it 'should be valid for IPv6 format' do
60
+ ipv6_nexpose_console = FactoryGirl.build(:mdm_nexpose_console, :address => '2001:0db8:85a3:0000:0000:8a2e:0370:7334')
61
+ ipv6_nexpose_console.should be_valid
62
+ end
63
+
64
+ it 'should not be valid for strings not conforming to IPv4 or IPv6' do
65
+ invalid_nexpose_console = FactoryGirl.build(:mdm_nexpose_console, :address => '1234-fark')
66
+ invalid_nexpose_console.should_not be_valid
67
+ end
68
+ end
69
+
70
+ context 'port' do
71
+ it 'should require a port' do
72
+ portless_nexpose_console = FactoryGirl.build(:mdm_nexpose_console, :port => nil)
73
+ portless_nexpose_console.should_not be_valid
74
+ portless_nexpose_console.errors[:port].should include("is not included in the list")
75
+ end
76
+
77
+ it 'should not be valid for out-of-range numbers' do
78
+ out_of_range = FactoryGirl.build(:mdm_nexpose_console, :port => 70000)
79
+ out_of_range.should_not be_valid
80
+ out_of_range.errors[:port].should include("is not included in the list")
81
+ end
82
+
83
+ it 'should not be valid for port 0' do
84
+ out_of_range = FactoryGirl.build(:mdm_nexpose_console, :port => 0)
85
+ out_of_range.should_not be_valid
86
+ out_of_range.errors[:port].should include("is not included in the list")
87
+ end
88
+
89
+ it 'should not be valid for decimal numbers' do
90
+ out_of_range = FactoryGirl.build(:mdm_nexpose_console, :port => 5.67)
91
+ out_of_range.should_not be_valid
92
+ out_of_range.errors[:port].should include("must be an integer")
93
+ end
94
+
95
+ it 'should not be valid for a negative number' do
96
+ out_of_range = FactoryGirl.build(:mdm_nexpose_console, :port => -8)
97
+ out_of_range.should_not be_valid
98
+ out_of_range.errors[:port].should include("is not included in the list")
99
+ end
100
+ end
101
+
102
+ context 'name' do
103
+ it 'should require a name' do
104
+ unnamed_console = FactoryGirl.build(:mdm_nexpose_console, :name => nil)
105
+ unnamed_console.should_not be_valid
106
+ unnamed_console.errors[:name].should include("can't be blank")
107
+ end
108
+ end
109
+
110
+ context 'username' do
111
+ it 'should require a name' do
112
+ console = FactoryGirl.build(:mdm_nexpose_console, :username => nil)
113
+ console.should_not be_valid
114
+ console.errors[:username].should include("can't be blank")
115
+ end
116
+ end
117
+
118
+ context 'password' do
119
+ it 'should require a password' do
120
+ console = FactoryGirl.build(:mdm_nexpose_console, :password => nil)
121
+ console.should_not be_valid
122
+ console.errors[:password].should include("can't be blank")
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mdm::Note do
4
+
5
+ context 'factory' do
6
+ it 'should be valid' do
7
+ note = FactoryGirl.build(:mdm_note)
8
+ note.should be_valid
9
+ end
10
+ end
11
+
12
+ context 'database' do
13
+
14
+ context 'timestamps'do
15
+ it { should have_db_column(:created_at).of_type(:datetime) }
16
+ it { should have_db_column(:updated_at).of_type(:datetime) }
17
+ end
18
+
19
+ context 'columns' do
20
+ it { should have_db_column(:workspace_id).of_type(:integer).with_options(:null => false, :default =>1) }
21
+ it { should have_db_column(:host_id).of_type(:integer) }
22
+ it { should have_db_column(:service_id).of_type(:integer) }
23
+ it { should have_db_column(:ntype).of_type(:string) }
24
+ it { should have_db_column(:critical).of_type(:boolean) }
25
+ it { should have_db_column(:seen).of_type(:boolean) }
26
+ it { should have_db_column(:data).of_type(:text) }
27
+ end
28
+ end
29
+
30
+ context '#destroy' do
31
+ it 'should successfully destroy the object' do
32
+ note = FactoryGirl.create(:mdm_note)
33
+ expect {
34
+ note.destroy
35
+ }.to_not raise_error
36
+ expect {
37
+ note.reload
38
+ }.to raise_error(ActiveRecord::RecordNotFound)
39
+ end
40
+ end
41
+
42
+ context 'associations' do
43
+ it { should belong_to(:workspace).class_name('Mdm::Workspace') }
44
+ it { should belong_to(:host).class_name('Mdm::Host') }
45
+ it { should belong_to(:service).class_name('Mdm::Service') }
46
+ end
47
+
48
+ context 'scopes' do
49
+ context 'flagged' do
50
+ it 'should exclude non-critical note' do
51
+ flagged_note = FactoryGirl.create(:mdm_note, :critical => true, :seen => false)
52
+ non_critical_note = FactoryGirl.create(:mdm_note, :critical => false, :seen => false)
53
+ flagged_set = Mdm::Note.flagged
54
+ flagged_set.should include(flagged_note)
55
+ flagged_set.should_not include(non_critical_note)
56
+ end
57
+
58
+ it 'should exclude seen notes' do
59
+ flagged_note = FactoryGirl.create(:mdm_note, :critical => true, :seen => false)
60
+ non_critical_note = FactoryGirl.create(:mdm_note, :critical => false, :seen => true)
61
+ flagged_set = Mdm::Note.flagged
62
+ flagged_set.should include(flagged_note)
63
+ flagged_set.should_not include(non_critical_note)
64
+ end
65
+ end
66
+
67
+ context 'visible' do
68
+ it 'should only include visible notes' do
69
+ flagged_note = FactoryGirl.create(:mdm_note, :ntype => 'flag.me', :critical => true, :seen => false)
70
+ webform_note = FactoryGirl.create(:mdm_note, :ntype => 'web.form', :critical => true, :seen => false)
71
+ visible_set = Mdm::Note.visible
72
+ visible_set.should include(flagged_note)
73
+ visible_set.should_not include(webform_note)
74
+ end
75
+ end
76
+
77
+ context 'search' do
78
+ it 'should match on ntype' do
79
+ flagged_note = FactoryGirl.create(:mdm_note, :ntype => 'flag.me', :critical => true, :seen => false)
80
+ Mdm::Note.search('flag.me').should include(flagged_note)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -28,6 +28,7 @@ describe Mdm::Ref do
28
28
 
29
29
  # @todo https://www.pivotaltracker.com/story/show/48915453
30
30
  it { should have_many(:vulns_refs).class_name('Mdm::VulnRef') }
31
+ it { should have_many(:vulns).class_name('Mdm::Vuln').through(:vulns_refs) }
31
32
  end
32
33
 
33
34
  context 'database' do
@@ -56,6 +57,18 @@ describe Mdm::Ref do
56
57
  end
57
58
  end
58
59
 
60
+ context '#destroy' do
61
+ it 'should successfully destroy the object' do
62
+ mdm_ref = FactoryGirl.create(:mdm_ref)
63
+ expect {
64
+ mdm_ref.destroy
65
+ }.to_not raise_error
66
+ expect {
67
+ mdm_ref.reload
68
+ }.to raise_error(ActiveRecord::RecordNotFound)
69
+ end
70
+ end
71
+
59
72
  context 'mass assignment security' do
60
73
  it { should allow_mass_assignment_of(:name) }
61
74
  end