metasploit_data_models 0.7.0 → 0.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +1 -0
  3. data/app/models/mdm/host.rb +352 -26
  4. data/app/models/mdm/loot.rb +72 -7
  5. data/app/models/mdm/{module_action.rb → module/action.rb} +3 -3
  6. data/app/models/mdm/{module_arch.rb → module/arch.rb} +3 -3
  7. data/app/models/mdm/{module_author.rb → module/author.rb} +3 -3
  8. data/app/models/mdm/module/detail.rb +280 -0
  9. data/app/models/mdm/{module_mixin.rb → module/mixin.rb} +3 -3
  10. data/app/models/mdm/{module_platform.rb → module/platform.rb} +3 -3
  11. data/app/models/mdm/module/ref.rb +48 -0
  12. data/app/models/mdm/{module_target.rb → module/target.rb} +3 -3
  13. data/app/models/mdm/note.rb +61 -6
  14. data/app/models/mdm/ref.rb +39 -1
  15. data/app/models/mdm/service.rb +85 -7
  16. data/app/models/mdm/session.rb +100 -6
  17. data/app/models/mdm/vuln.rb +104 -24
  18. data/db/migrate/20130228214900_change_required_columns_to_null_false_in_web_vulns.rb +1 -17
  19. data/db/migrate/20130412154159_change_foreign_key_in_module_actions.rb +25 -0
  20. data/db/migrate/20130412171844_change_foreign_key_in_module_archs.rb +25 -0
  21. data/db/migrate/20130412173121_change_foreign_key_in_module_authors.rb +25 -0
  22. data/db/migrate/20130412173640_change_foreign_key_in_module_mixins.rb +25 -0
  23. data/db/migrate/20130412174254_change_foreign_key_in_module_platforms.rb +25 -0
  24. data/db/migrate/20130412174719_change_foreign_key_in_module_refs.rb +25 -0
  25. data/db/migrate/20130412175040_change_foreign_key_in_module_targets.rb +25 -0
  26. data/db/migrate/20130430151353_change_required_columns_to_null_false_in_hosts.rb +11 -0
  27. data/db/migrate/20130430162145_enforce_address_uniqueness_in_workspace_in_hosts.rb +23 -0
  28. data/lib/mdm/module.rb +4 -0
  29. data/lib/metasploit_data_models.rb +1 -0
  30. data/lib/metasploit_data_models/change_required_columns_to_null_false.rb +23 -0
  31. data/lib/metasploit_data_models/version.rb +1 -1
  32. data/spec/app/models/mdm/host_spec.rb +411 -0
  33. data/spec/app/models/mdm/host_tag_spec.rb +13 -0
  34. data/spec/app/models/mdm/{module_action_spec.rb → module/action_spec.rb} +6 -6
  35. data/spec/app/models/mdm/{module_arch_spec.rb → module/arch_spec.rb} +6 -6
  36. data/spec/app/models/mdm/{module_author_spec.rb → module/author_spec.rb} +6 -6
  37. data/spec/app/models/mdm/{module_detail_spec.rb → module/detail_spec.rb} +101 -11
  38. data/spec/app/models/mdm/{module_mixin_spec.rb → module/mixin_spec.rb} +6 -6
  39. data/spec/app/models/mdm/{module_platform_spec.rb → module/platform_spec.rb} +6 -6
  40. data/spec/app/models/mdm/module/ref_spec.rb +62 -0
  41. data/spec/app/models/mdm/{module_target_spec.rb → module/target_spec.rb} +6 -6
  42. data/spec/app/models/mdm/ref_spec.rb +62 -0
  43. data/spec/app/models/mdm/tag_spec.rb +13 -0
  44. data/spec/app/models/mdm/vuln_ref_spec.rb +13 -0
  45. data/spec/app/models/mdm/vuln_spec.rb +231 -0
  46. data/spec/dummy/db/schema.rb +20 -20
  47. data/spec/factories/mdm/host_tags.rb +9 -0
  48. data/spec/factories/mdm/hosts.rb +65 -0
  49. data/spec/factories/mdm/module/actions.rb +14 -0
  50. data/spec/factories/mdm/module/archs.rb +14 -0
  51. data/spec/factories/mdm/{module_authors.rb → module/authors.rb} +4 -4
  52. data/spec/factories/mdm/module/details.rb +66 -0
  53. data/spec/factories/mdm/module/mixins.rb +14 -0
  54. data/spec/factories/mdm/module/platforms.rb +14 -0
  55. data/spec/factories/mdm/module/refs.rb +14 -0
  56. data/spec/factories/mdm/{module_targets.rb → module/targets.rb} +3 -3
  57. data/spec/factories/mdm/refs.rb +9 -0
  58. data/spec/factories/mdm/tags.rb +14 -0
  59. data/spec/factories/mdm/vuln_refs.rb +4 -0
  60. data/spec/factories/mdm/vulns.rb +20 -0
  61. metadata +78 -45
  62. data/app/models/mdm/module_detail.rb +0 -59
  63. data/app/models/mdm/module_ref.rb +0 -24
  64. data/spec/app/models/mdm/module_ref_spec.rb +0 -38
  65. data/spec/factories/mdm/module_actions.rb +0 -14
  66. data/spec/factories/mdm/module_archs.rb +0 -14
  67. data/spec/factories/mdm/module_details.rb +0 -9
  68. data/spec/factories/mdm/module_mixins.rb +0 -14
  69. data/spec/factories/mdm/module_platforms.rb +0 -14
  70. data/spec/factories/mdm/module_refs.rb +0 -14
data/.gitignore CHANGED
@@ -8,6 +8,9 @@
8
8
  .idea
9
9
  # logs
10
10
  *.log
11
+ # Don't check in new rvm version and gemset files
12
+ .ruby-gemset
13
+ .ruby-version
11
14
  # Don't check in rvmrc since this is a gem
12
15
  .rvmrc
13
16
  # YARD database
data/.travis.yml CHANGED
@@ -4,3 +4,4 @@ before_script:
4
4
  language: ruby
5
5
  rvm:
6
6
  - '1.9.3'
7
+ - 'jruby-19mode'
@@ -1,57 +1,355 @@
1
-
1
+ # A system with an {#address IP address} on the network that has been discovered in some way.
2
2
  class Mdm::Host < ActiveRecord::Base
3
3
  include Mdm::Host::OperatingSystemNormalization
4
4
 
5
5
  #
6
- # Callbacks
6
+ # CONSTANTS
7
7
  #
8
8
 
9
- before_destroy :cleanup_tags
9
+ # Either the CPU architecture for native code or the programming language name for exploits that run code in the
10
+ # programming language's virtual machine.
11
+ ARCHITECTURES = [
12
+ 'armbe',
13
+ 'armle',
14
+ 'cbea',
15
+ 'cbea64',
16
+ 'cmd',
17
+ 'java',
18
+ 'mips',
19
+ 'mipsbe',
20
+ 'mipsle',
21
+ 'php',
22
+ 'ppc',
23
+ 'ppc64',
24
+ 'ruby',
25
+ 'sparc',
26
+ 'tty',
27
+ # To be used for compatability with 'X86_64'
28
+ 'x64',
29
+ 'x86',
30
+ 'x86_64'
31
+ ]
10
32
 
11
- #
12
- # CONSTANTS
13
- #
33
+ # Valid values for {#os_name}.
34
+ OPERATING_SYSTEM_NAMES = [
35
+ 'FreeBSD',
36
+ 'Linux',
37
+ 'Mac OS X',
38
+ 'Microsoft Windows',
39
+ 'NetBSD',
40
+ 'OpenBSD',
41
+ 'Unknown',
42
+ 'VMWare'
43
+ ]
14
44
 
15
45
  # Fields searched for the search scope
16
46
  SEARCH_FIELDS = [
17
47
  'address::text',
18
- 'hosts.name',
19
- 'os_name',
48
+ 'comments',
49
+ 'mac',
50
+ 'name',
20
51
  'os_flavor',
52
+ 'os_name',
21
53
  'os_sp',
22
- 'mac',
23
- 'purpose',
24
- 'comments'
54
+ 'purpose'
55
+ ]
56
+
57
+ # Valid values for {#state}.
58
+ STATES = [
59
+ 'alive',
60
+ 'down',
61
+ 'unknown'
25
62
  ]
26
63
 
27
64
  #
28
- # Relations
65
+ # Associations
29
66
  #
30
67
 
31
- has_many :exploit_attempts, :dependent => :destroy, :class_name => 'Mdm::ExploitAttempt'
32
- has_many :exploited_hosts, :dependent => :destroy, :class_name => 'Mdm::ExploitedHost'
33
- has_many :clients, :dependent => :delete_all, :class_name => 'Mdm::Client'
34
- has_many :host_details, :dependent => :destroy, :class_name => 'Mdm::HostDetail'
35
- # hosts_tags are cleaned up in before_destroy:
68
+ # @!attribute [rw] exploit_attempts
69
+ # Attempts to run exploits against this host.
70
+ #
71
+ # @return [Array<Mdm::ExploitAttempt]
72
+ has_many :exploit_attempts,
73
+ :class_name => 'Mdm::ExploitAttempt',
74
+ :dependent => :destroy
75
+
76
+ # @!attribute [rw] exploited_hosts
77
+ # @todo https://www.pivotaltracker.com/story/show/48993731
78
+ # @return [Array<Mdm::ExploitedHost>]
79
+ has_many :exploited_hosts, :class_name => 'Mdm::ExploitedHost', :dependent => :destroy
80
+
81
+ # @!attribute [rw] host_details
82
+ # @return [Array<Mdm::HostDetail>]
83
+ has_many :host_details, :class_name => 'Mdm::HostDetail', :dependent => :destroy
84
+
85
+ # @!attribute [rw] hosts_tags
86
+ # A join model between {Mdm::Tag} and {Mdm::Host}. Use {#tags} to get the actual {Mdm::Tag Mdm::Tags} on this host.
87
+ # {#hosts_tags} are cleaned up in a before_destroy: {#cleanup_tags}.
88
+ #
89
+ # @todo https://www.pivotaltracker.com/story/show/48923201
90
+ # @return [Array<Mdm::HostTag>]
36
91
  has_many :hosts_tags, :class_name => 'Mdm::HostTag'
37
- has_many :loots, :dependent => :destroy, :class_name => 'Mdm::Loot', :order => 'loots.created_at desc'
38
- has_many :notes, :dependent => :delete_all, :class_name => 'Mdm::Note', :order => 'notes.created_at'
39
- has_many :services, :dependent => :destroy, :class_name => 'Mdm::Service', :order => 'services.port, services.proto'
40
- has_many :sessions, :dependent => :destroy, :class_name => 'Mdm::Session', :order => 'sessions.opened_at'
41
- has_many :vulns, :dependent => :delete_all, :class_name => 'Mdm::Vuln'
92
+
93
+ # @!attribute [rw] loots
94
+ # Loot gathered from the host with {Mdm::Loot#created_at newest loot} first.
95
+ #
96
+ # @todo https://www.pivotaltracker.com/story/show/48991525
97
+ # @return [Array<Mdm::Loot>]
98
+ has_many :loots, :class_name => 'Mdm::Loot', :dependent => :destroy, :order => 'loots.created_at DESC'
99
+
100
+ # @!attribute [rw] notes
101
+ # Notes about the host entered by a user with {Mdm::Note#created_at oldest notes} first.
102
+ #
103
+ # @return [Array<Mdm::Note>]
104
+ has_many :notes, :class_name => 'Mdm::Note', :dependent => :delete_all, :order => 'notes.created_at'
105
+
106
+ # @!attribute [rw] services
107
+ # The services running on {Mdm::Service#port ports} on the host with services ordered by {Mdm::Service#port port}
108
+ # and {Mdm::Service#proto protocol}.
109
+ #
110
+ # @return [Array<Mdm::Service>]
111
+ has_many :services, :class_name => 'Mdm::Service', :dependent => :destroy, :order => 'services.port, services.proto'
112
+
113
+ # @!attribute [rw] sessions
114
+ # Sessions that are open or previously were open on the host ordered by {Mdm::Session#opened_at when the session was
115
+ # opened}
116
+ #
117
+ # @return [Array<Mdm::Session]
118
+ has_many :sessions, :class_name => 'Mdm::Session', :dependent => :destroy, :order => 'sessions.opened_at'
119
+
120
+ # @!attribute [rw] vulns
121
+ # Vulnerabilities found on the host.
122
+ #
123
+ # @return [Array<Mdm::Vuln>]
124
+ has_many :vulns, :class_name => 'Mdm::Vuln', :dependent => :delete_all
125
+
126
+ # @!attribute [rw] workspace
127
+ # The workspace in which this host was found.
128
+ #
129
+ # @return [Mdm::Workspace]
42
130
  belongs_to :workspace, :class_name => 'Mdm::Workspace'
43
131
 
44
132
  #
45
133
  # Through host_tags
46
134
  #
47
- has_many :tags, :through => :hosts_tags, :class_name => 'Mdm::Tag'
135
+
136
+ # @!attribute [r] tags
137
+ # The tags on this host. Tags are used to filter hosts.
138
+ #
139
+ # @return [Array<Mdm::Tag>]
140
+ # @see #hosts_tags
141
+ has_many :tags, :class_name => 'Mdm::Tag', :through => :hosts_tags
48
142
 
49
143
  #
50
144
  # Through services
51
145
  #
52
- has_many :creds, :through => :services, :class_name => 'Mdm::Cred'
53
- has_many :service_notes, :through => :services
54
- has_many :web_sites, :through => :services, :class_name => 'Mdm::WebSite'
146
+
147
+ # @!attribute [r] creds
148
+ # Credentials captured from {#services}.
149
+ #
150
+ # @return [Array<Mdm::Cred>]
151
+ # @see #services
152
+ has_many :creds, :class_name => 'Mdm::Cred', :through => :services
153
+
154
+ # @!attribute [r] service_notes
155
+ # {Mdm::Note Notes} about {#services} running on this host.
156
+ #
157
+ # @return [Array<Mdm::Note>]
158
+ # @see #services
159
+ has_many :service_notes, :class_name => 'Mdm::Note', :through => :services
160
+
161
+ # @!attribute [r] web_sites
162
+ # {Mdm::WebSite Web sites} running on top of {#services} on this host.
163
+ #
164
+ # @return [Array<Mdm::WebSite>]
165
+ # @see services
166
+ has_many :web_sites, :class_name => 'Mdm::WebSite', :through => :services
167
+
168
+ #
169
+ # Through vulns
170
+ #
171
+
172
+ # @!attribute [r] vuln_refs
173
+ # Join model between {#vulns} and {#refs}. Use either of those asssociations instead of this join model.
174
+ #
175
+ # @todo https://www.pivotaltracker.com/story/show/49004623
176
+ # @return [Array<Mdm::VulnRef>]
177
+ # @see #refs
178
+ # @see #vulns
179
+ has_many :vuln_refs, :class_name => 'Mdm::VulnRef', :source => :vulns_refs, :through => :vulns
180
+
181
+ #
182
+ # Through vuln_refs
183
+ #
184
+
185
+ # @!attribute [r] refs
186
+ # External references, such as CVE, to vulnerabilities found on this host.
187
+ #
188
+ # @return [Array<Mdm::Ref>]
189
+ # @see #vuln_refs
190
+ has_many :refs, :class_name => 'Mdm::Ref', :through => :vuln_refs
191
+
192
+ #
193
+ # Through refs
194
+ #
195
+
196
+ # @!attribute [r] module_refs
197
+ # {Mdm::Module::Ref References for modules} for {Mdm::Ref references for vulnerabilities}.
198
+ #
199
+ # @return [Array<Mdm::Module::Ref>]
200
+ has_many :module_refs, :class_name => 'Mdm::Module::Ref', :through => :refs
201
+
202
+ #
203
+ # Through module_refs
204
+ #
205
+
206
+ # @!attribute [r] module_details
207
+ # {Mdm::Module::Detail Details about modules} that were used to find {#vulns vulnerabilities} on this host.
208
+ #
209
+ # @return [Array<Mdm::Module::Detail]
210
+ has_many :module_details,
211
+ :class_name => 'Mdm::Module::Detail',
212
+ :source =>:detail,
213
+ :through => :module_refs,
214
+ :uniq => true
215
+
216
+ #
217
+ # Attributes
218
+ #
219
+
220
+ # @!attribute [rw] address
221
+ # The IP address of this host.
222
+ #
223
+ # @return [String]
224
+
225
+ # @!attribute [rw] arch
226
+ # The architecture of the host's CPU OR the programming language for virtual machine programming language like
227
+ # Ruby, PHP, and Java.
228
+ #
229
+ # @return [String] an element of {ARCHITECTURES}
230
+
231
+ # @!attribute [rw] comm
232
+ # @todo https://www.pivotaltracker.com/story/show/49722411
233
+ #
234
+ # @return [String]
235
+
236
+ # @!attribute [rw] comments
237
+ # User supplied comments about host.
238
+ #
239
+ # @return [String]
240
+
241
+ # @!attribute [rw] created_at
242
+ # When this host was created in the database.
243
+ #
244
+ # @return [DateTime]
245
+
246
+ # @!attribute [rw] cred_count
247
+ # Counter cache for {#creds}.
248
+ #
249
+ # @return [Integer]
250
+
251
+ # @!attribute [rw] exploit_attempt_count
252
+ # Counter cache for {#exploit_attempts}.
253
+ #
254
+ # @return [Integer]
255
+
256
+ # @!attribute [rw] host_detail_count
257
+ # Counter cache for {#host_details}.
258
+ #
259
+ # @return [Integer]
260
+
261
+ # @!attribute [rw] info
262
+ # Information about this host gathered from the host.
263
+ #
264
+ # @return [String]
265
+
266
+ # @!attribute [rw] mac
267
+ # The MAC address of this host.
268
+ #
269
+ # @return [String]
270
+ # @see http://en.wikipedia.org/wiki/Mac_address
271
+
272
+ # @!attribute [rw] name
273
+ # The name of the host. If the host name is not available, then it will just be the IP address.
274
+ #
275
+ # @return [String]
276
+
277
+ # @!attribute [rw] note_count
278
+ # Counter cache for {#notes}.
279
+ #
280
+ # @return [Integer]
281
+
282
+ # @!attribute [rw] os_flavor
283
+ # The flavor of {#os_name}.
284
+ #
285
+ # @example Windows XP
286
+ # host.os_name = 'Microsoft Windows'
287
+ # host.os_flavor = 'XP'
288
+ #
289
+ # @return [String]
290
+
291
+ # @!attribute [rw] os_lang
292
+ # Free-form language of operating system. Usually either spelled out like 'English' or an
293
+ # {http://en.wikipedia.org/wiki/IETF_language_tag IETF language tag} like 'en' or 'en-US'.
294
+ #
295
+ # @return [String]
296
+
297
+ # @!attribute [rw] os_name
298
+ # The name of the operating system.
299
+ #
300
+ # @return [String] an element of {OPERATING_SYSTEM_NAMES}.
301
+
302
+ # @!attribute [rw] os_sp
303
+ # The service pack of the {#os_flavor} of the {#os_name}.
304
+ #
305
+ # @example Windows XP SP2
306
+ # host.os_name = 'Microsoft Windows'
307
+ # host.os_flavor = 'XP'
308
+ # host.os_sp = 'SP2'
309
+ #
310
+ # @return [String]
311
+
312
+ # @!attribute [rw] purpose
313
+ # The purpose of the host on the network, such as 'client' or 'firewall'.
314
+ #
315
+ # @return [String]
316
+
317
+ # @!attribute [rw] scope
318
+ # Interface identifier for link-local IPv6
319
+ #
320
+ # @return [String]
321
+ # @see http://en.wikipedia.org/wiki/IPv6_address#Link-local_addresses_and_zone_indices
322
+
323
+ # @!attribute [rw] service_count
324
+ # Counter cache for {#services}.
325
+ #
326
+ # @return [Integer]
327
+
328
+ # @!attribute [rw] state
329
+ # Whether the host is alive, down, or in an unknown state.
330
+ #
331
+ # @return [String] element of {STATES}.
332
+
333
+ # @!attribute [rw] updated_at
334
+ # The last time this host was updated in the database.
335
+ #
336
+ # @return [DateTime]
337
+
338
+ # @!attribute [rw] virtual_host
339
+ # The name of the virtual machine host software, such as 'VMWare', 'QEMU', 'XEN', etc.
340
+ #
341
+ # @return [String]
342
+
343
+ # @!attribute [rw] vuln_count
344
+ # Counter cache for {#vulns}.
345
+ #
346
+ # @return [Integer]
347
+
348
+ #
349
+ # Callbacks
350
+ #
351
+
352
+ before_destroy :cleanup_tags
55
353
 
56
354
  #
57
355
  # Nested Attributes
@@ -74,6 +372,21 @@ class Mdm::Host < ActiveRecord::Base
74
372
  :scope => :workspace_id,
75
373
  :unless => :ip_address_invalid?
76
374
  }
375
+ validates :arch,
376
+ :allow_nil => true,
377
+ :inclusion => {
378
+ :in => ARCHITECTURES
379
+ }
380
+ validates :os_name,
381
+ :allow_nil => true,
382
+ :inclusion => {
383
+ :in => OPERATING_SYSTEM_NAMES
384
+ }
385
+ validates :state,
386
+ :allow_nil => true,
387
+ :inclusion => {
388
+ :in => STATES
389
+ }
77
390
  validates :workspace, :presence => true
78
391
 
79
392
  #
@@ -100,11 +413,18 @@ class Mdm::Host < ActiveRecord::Base
100
413
  scope :tag_search,
101
414
  lambda { |*args| where("tags.name" => args[0]).includes(:tags) }
102
415
 
416
+ # Returns whether 'host.updated.<attr>' {#notes note} is {Mdm::Note#data locked}.
417
+ #
418
+ # @return [true] if Mdm::Note with 'host.updated.<attr>' as {Mdm::Note#name} exists and data[:locked] is `true`.
419
+ # @return [false] otherwise.
103
420
  def attribute_locked?(attr)
104
421
  n = notes.find_by_ntype("host.updated.#{attr}")
105
422
  n && n.data[:locked]
106
423
  end
107
424
 
425
+ # Destroys any {Mdm::Tag Mdm::Tags} that will have no {Mdm::Tag#hosts} left after this host is deleted.
426
+ #
427
+ # @return [void]
108
428
  def cleanup_tags
109
429
  # No need to keep tags with no hosts
110
430
  tags.each do |tag|
@@ -116,6 +436,8 @@ class Mdm::Host < ActiveRecord::Base
116
436
 
117
437
  # This is replicated by the IpAddressValidator class. Had to put it here as well to avoid
118
438
  # SQL errors when checking address uniqueness.
439
+ #
440
+ # @return [void]
119
441
  def ip_address_invalid?
120
442
  begin
121
443
  potential_ip = IPAddr.new(address)
@@ -125,6 +447,10 @@ class Mdm::Host < ActiveRecord::Base
125
447
  end
126
448
  end
127
449
 
450
+ # Returns whether this host is a virtual machine.
451
+ #
452
+ # @return [true] unless {#virtual_host} is `nil`.
453
+ # @return [false] otherwise.
128
454
  def is_vm?
129
455
  !!self.virtual_host
130
456
  end