metasploit_data_models 0.6.13

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 (211) hide show
  1. data/.gitignore +24 -0
  2. data/.rspec +3 -0
  3. data/.simplecov +38 -0
  4. data/.yardopts +4 -0
  5. data/Gemfile +27 -0
  6. data/LICENSE +27 -0
  7. data/README.md +72 -0
  8. data/Rakefile +53 -0
  9. data/app/models/mdm/api_key.rb +20 -0
  10. data/app/models/mdm/client.rb +9 -0
  11. data/app/models/mdm/cred.rb +80 -0
  12. data/app/models/mdm/event.rb +30 -0
  13. data/app/models/mdm/exploit_attempt.rb +14 -0
  14. data/app/models/mdm/exploited_host.rb +11 -0
  15. data/app/models/mdm/host.rb +134 -0
  16. data/app/models/mdm/host_detail.rb +15 -0
  17. data/app/models/mdm/host_tag.rb +13 -0
  18. data/app/models/mdm/imported_cred.rb +10 -0
  19. data/app/models/mdm/listener.rb +24 -0
  20. data/app/models/mdm/loot.rb +63 -0
  21. data/app/models/mdm/macro.rb +20 -0
  22. data/app/models/mdm/mod_ref.rb +3 -0
  23. data/app/models/mdm/module_action.rb +24 -0
  24. data/app/models/mdm/module_arch.rb +24 -0
  25. data/app/models/mdm/module_author.rb +25 -0
  26. data/app/models/mdm/module_detail.rb +59 -0
  27. data/app/models/mdm/module_mixin.rb +24 -0
  28. data/app/models/mdm/module_platform.rb +24 -0
  29. data/app/models/mdm/module_ref.rb +24 -0
  30. data/app/models/mdm/module_target.rb +26 -0
  31. data/app/models/mdm/nexpose_console.rb +20 -0
  32. data/app/models/mdm/note.rb +49 -0
  33. data/app/models/mdm/profile.rb +9 -0
  34. data/app/models/mdm/ref.rb +14 -0
  35. data/app/models/mdm/report.rb +50 -0
  36. data/app/models/mdm/report_template.rb +27 -0
  37. data/app/models/mdm/route.rb +9 -0
  38. data/app/models/mdm/service.rb +56 -0
  39. data/app/models/mdm/session.rb +48 -0
  40. data/app/models/mdm/session_event.rb +9 -0
  41. data/app/models/mdm/tag.rb +46 -0
  42. data/app/models/mdm/task.rb +41 -0
  43. data/app/models/mdm/user.rb +25 -0
  44. data/app/models/mdm/vuln.rb +60 -0
  45. data/app/models/mdm/vuln_attempt.rb +15 -0
  46. data/app/models/mdm/vuln_detail.rb +14 -0
  47. data/app/models/mdm/vuln_ref.rb +13 -0
  48. data/app/models/mdm/web_form.rb +16 -0
  49. data/app/models/mdm/web_page.rb +16 -0
  50. data/app/models/mdm/web_site.rb +47 -0
  51. data/app/models/mdm/web_vuln.rb +190 -0
  52. data/app/models/mdm/wmap_request.rb +3 -0
  53. data/app/models/mdm/wmap_target.rb +3 -0
  54. data/app/models/mdm/workspace.rb +196 -0
  55. data/bin/mdm_console +68 -0
  56. data/console_db.yml +9 -0
  57. data/db/migrate/000_create_tables.rb +79 -0
  58. data/db/migrate/001_add_wmap_tables.rb +35 -0
  59. data/db/migrate/002_add_workspaces.rb +36 -0
  60. data/db/migrate/003_move_notes.rb +20 -0
  61. data/db/migrate/004_add_events_table.rb +16 -0
  62. data/db/migrate/005_expand_info.rb +58 -0
  63. data/db/migrate/006_add_timestamps.rb +26 -0
  64. data/db/migrate/007_add_loots.rb +20 -0
  65. data/db/migrate/008_create_users.rb +16 -0
  66. data/db/migrate/009_add_loots_ctype.rb +10 -0
  67. data/db/migrate/010_add_alert_fields.rb +16 -0
  68. data/db/migrate/011_add_reports.rb +19 -0
  69. data/db/migrate/012_add_tasks.rb +24 -0
  70. data/db/migrate/013_add_tasks_result.rb +10 -0
  71. data/db/migrate/014_add_loots_fields.rb +12 -0
  72. data/db/migrate/015_rename_user.rb +16 -0
  73. data/db/migrate/016_add_host_purpose.rb +10 -0
  74. data/db/migrate/017_expand_info2.rb +58 -0
  75. data/db/migrate/018_add_workspace_user_info.rb +29 -0
  76. data/db/migrate/019_add_workspace_desc.rb +23 -0
  77. data/db/migrate/020_add_user_preferences.rb +11 -0
  78. data/db/migrate/021_standardize_info_and_data.rb +18 -0
  79. data/db/migrate/022_enlarge_event_info.rb +10 -0
  80. data/db/migrate/023_add_report_downloaded_at.rb +10 -0
  81. data/db/migrate/024_convert_service_info_to_text.rb +12 -0
  82. data/db/migrate/025_add_user_admin.rb +19 -0
  83. data/db/migrate/026_add_creds_table.rb +19 -0
  84. data/db/migrate/20100819123300_migrate_cred_data.rb +154 -0
  85. data/db/migrate/20100824151500_add_exploited_table.rb +16 -0
  86. data/db/migrate/20100908001428_add_owner_to_workspaces.rb +9 -0
  87. data/db/migrate/20100911122000_add_report_templates.rb +18 -0
  88. data/db/migrate/20100916151530_require_admin_flag.rb +15 -0
  89. data/db/migrate/20100916175000_add_campaigns_and_templates.rb +61 -0
  90. data/db/migrate/20100920012100_add_generate_exe_column.rb +8 -0
  91. data/db/migrate/20100926214000_add_template_prefs.rb +11 -0
  92. data/db/migrate/20101001000000_add_web_tables.rb +57 -0
  93. data/db/migrate/20101002000000_add_query.rb +10 -0
  94. data/db/migrate/20101007000000_add_vuln_info.rb +15 -0
  95. data/db/migrate/20101008111800_add_clients_to_campaigns.rb +10 -0
  96. data/db/migrate/20101009023300_add_campaign_attachments.rb +15 -0
  97. data/db/migrate/20101104135100_add_imported_creds.rb +17 -0
  98. data/db/migrate/20101203000000_fix_web_tables.rb +34 -0
  99. data/db/migrate/20101203000001_expand_host_comment.rb +12 -0
  100. data/db/migrate/20101206212033_add_limit_to_network_to_workspaces.rb +9 -0
  101. data/db/migrate/20110112154300_add_module_uuid_to_tasks.rb +9 -0
  102. data/db/migrate/20110204112800_add_host_tags.rb +28 -0
  103. data/db/migrate/20110317144932_add_session_table.rb +110 -0
  104. data/db/migrate/20110414180600_add_local_id_to_session_table.rb +11 -0
  105. data/db/migrate/20110415175705_add_routes_table.rb +18 -0
  106. data/db/migrate/20110422000000_convert_binary.rb +72 -0
  107. data/db/migrate/20110425095900_add_last_seen_to_sessions.rb +8 -0
  108. data/db/migrate/20110513143900_track_successful_exploits.rb +31 -0
  109. data/db/migrate/20110517160800_rename_and_prune_nessus_vulns.rb +26 -0
  110. data/db/migrate/20110527000000_add_task_id_to_reports_table.rb +11 -0
  111. data/db/migrate/20110527000001_add_api_keys_table.rb +12 -0
  112. data/db/migrate/20110606000001_add_macros_table.rb +16 -0
  113. data/db/migrate/20110622000000_add_settings_to_tasks_table.rb +12 -0
  114. data/db/migrate/20110624000001_add_listeners_table.rb +19 -0
  115. data/db/migrate/20110625000001_add_macro_to_listeners_table.rb +12 -0
  116. data/db/migrate/20110630000001_add_nexpose_consoles_table.rb +21 -0
  117. data/db/migrate/20110630000002_add_name_to_nexpose_consoles_table.rb +12 -0
  118. data/db/migrate/20110717000001_add_profiles_table.rb +15 -0
  119. data/db/migrate/20110727163801_expand_cred_ptype_column.rb +9 -0
  120. data/db/migrate/20110730000001_add_initial_indexes.rb +85 -0
  121. data/db/migrate/20110812000001_prune_indexes.rb +23 -0
  122. data/db/migrate/20110922000000_expand_notes.rb +9 -0
  123. data/db/migrate/20110928101300_add_mod_ref_table.rb +17 -0
  124. data/db/migrate/20111011110000_add_display_name_to_reports_table.rb +24 -0
  125. data/db/migrate/20111203000000_inet_columns.rb +13 -0
  126. data/db/migrate/20111204000000_more_inet_columns.rb +17 -0
  127. data/db/migrate/20111210000000_add_scope_to_hosts.rb +9 -0
  128. data/db/migrate/20120126110000_add_virtual_host_to_hosts.rb +9 -0
  129. data/db/migrate/20120411173220_rename_workspace_members.rb +9 -0
  130. data/db/migrate/20120601152442_add_counter_caches_to_hosts.rb +21 -0
  131. data/db/migrate/20120625000000_add_vuln_details.rb +34 -0
  132. data/db/migrate/20120625000001_add_host_details.rb +16 -0
  133. data/db/migrate/20120625000002_expand_details.rb +16 -0
  134. data/db/migrate/20120625000003_expand_details2.rb +24 -0
  135. data/db/migrate/20120625000004_add_vuln_attempts.rb +19 -0
  136. data/db/migrate/20120625000005_add_vuln_and_host_counter_caches.rb +14 -0
  137. data/db/migrate/20120625000006_add_module_details.rb +118 -0
  138. data/db/migrate/20120625000007_add_exploit_attempts.rb +26 -0
  139. data/db/migrate/20120625000008_add_fail_message.rb +12 -0
  140. data/db/migrate/20120718202805_add_owner_and_payload_to_web_vulns.rb +13 -0
  141. data/db/migrate/20130228214900_change_required_columns_to_null_false_in_web_vulns.rb +35 -0
  142. data/lib/mdm.rb +12 -0
  143. data/lib/mdm/host/operating_system_normalization.rb +984 -0
  144. data/lib/metasploit_data_models.rb +60 -0
  145. data/lib/metasploit_data_models/base64_serializer.rb +103 -0
  146. data/lib/metasploit_data_models/engine.rb +23 -0
  147. data/lib/metasploit_data_models/serialized_prefs.rb +23 -0
  148. data/lib/metasploit_data_models/validators/ip_format_validator.rb +13 -0
  149. data/lib/metasploit_data_models/validators/password_is_strong_validator.rb +70 -0
  150. data/lib/metasploit_data_models/version.rb +8 -0
  151. data/lib/tasks/yard.rake +26 -0
  152. data/metasploit_data_models.gemspec +31 -0
  153. data/script/rails +8 -0
  154. data/spec/app/models/mdm/module_action_spec.rb +38 -0
  155. data/spec/app/models/mdm/module_arch_spec.rb +38 -0
  156. data/spec/app/models/mdm/module_author_spec.rb +50 -0
  157. data/spec/app/models/mdm/module_detail_spec.rb +291 -0
  158. data/spec/app/models/mdm/module_mixin_spec.rb +38 -0
  159. data/spec/app/models/mdm/module_platform_spec.rb +38 -0
  160. data/spec/app/models/mdm/module_ref_spec.rb +38 -0
  161. data/spec/app/models/mdm/module_target_spec.rb +41 -0
  162. data/spec/app/models/mdm/web_vuln_spec.rb +126 -0
  163. data/spec/dummy/Rakefile +7 -0
  164. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  165. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  166. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  167. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  168. data/spec/dummy/app/mailers/.gitkeep +0 -0
  169. data/spec/dummy/app/models/.gitkeep +0 -0
  170. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  171. data/spec/dummy/config.ru +4 -0
  172. data/spec/dummy/config/application.rb +61 -0
  173. data/spec/dummy/config/boot.rb +10 -0
  174. data/spec/dummy/config/database.yml.example +22 -0
  175. data/spec/dummy/config/environment.rb +5 -0
  176. data/spec/dummy/config/environments/development.rb +37 -0
  177. data/spec/dummy/config/environments/production.rb +67 -0
  178. data/spec/dummy/config/environments/test.rb +37 -0
  179. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  180. data/spec/dummy/config/initializers/inflections.rb +15 -0
  181. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  182. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  183. data/spec/dummy/config/initializers/session_store.rb +8 -0
  184. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  185. data/spec/dummy/config/routes.rb +2 -0
  186. data/spec/dummy/db/schema.rb +638 -0
  187. data/spec/dummy/lib/assets/.gitkeep +0 -0
  188. data/spec/dummy/log/.gitkeep +0 -0
  189. data/spec/dummy/public/404.html +26 -0
  190. data/spec/dummy/public/422.html +26 -0
  191. data/spec/dummy/public/500.html +25 -0
  192. data/spec/dummy/public/favicon.ico +0 -0
  193. data/spec/dummy/script/rails +6 -0
  194. data/spec/factories/mdm/addresses.rb +7 -0
  195. data/spec/factories/mdm/hosts.rb +18 -0
  196. data/spec/factories/mdm/module_actions.rb +14 -0
  197. data/spec/factories/mdm/module_archs.rb +14 -0
  198. data/spec/factories/mdm/module_authors.rb +22 -0
  199. data/spec/factories/mdm/module_details.rb +9 -0
  200. data/spec/factories/mdm/module_mixins.rb +14 -0
  201. data/spec/factories/mdm/module_platforms.rb +14 -0
  202. data/spec/factories/mdm/module_refs.rb +14 -0
  203. data/spec/factories/mdm/module_targets.rb +19 -0
  204. data/spec/factories/mdm/services.rb +35 -0
  205. data/spec/factories/mdm/users.rb +22 -0
  206. data/spec/factories/mdm/web_sites.rb +8 -0
  207. data/spec/factories/mdm/web_vulns.rb +64 -0
  208. data/spec/factories/mdm/workspaces.rb +23 -0
  209. data/spec/lib/base64_serializer_spec.rb +174 -0
  210. data/spec/spec_helper.rb +36 -0
  211. metadata +433 -0
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ # bundler configuration
2
+ .bundle
3
+ # Mac OS X folder attributes
4
+ .DS_Store
5
+ # built gems
6
+ *.gem
7
+ # Rubymine project configuration
8
+ .idea
9
+ # logs
10
+ *.log
11
+ # Don't check in rvmrc since this is a gem
12
+ .rvmrc
13
+ # YARD database
14
+ .yardoc
15
+ # coverage report directory for simplecov/Rubymine
16
+ coverage
17
+ # generated yardocs
18
+ doc
19
+ # Installed gem versions. Not stored for the same reasons as .rvmrc
20
+ Gemfile.lock
21
+ # Packaging directory for builds
22
+ pkg/*
23
+ # Database configuration (with passwords) for specs
24
+ spec/dummy/config/database.yml
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format nested
2
+ --colour
3
+ --drb
data/.simplecov ADDED
@@ -0,0 +1,38 @@
1
+ # RM_INFO is set when using Rubymine. In Rubymine, starting SimpleCov is
2
+ # controlled by running with coverage, so don't explicitly start coverage (and
3
+ # therefore generate a report) when in Rubymine. This _will_ generate a report
4
+ # whenever `rake spec` is run.
5
+ unless ENV['RM_INFO']
6
+ SimpleCov.start
7
+ end
8
+
9
+ SimpleCov.configure do
10
+ load_adapter('rails')
11
+
12
+ # ignore this file
13
+ add_filter '.simplecov'
14
+
15
+ #
16
+ # Changed Files in Git Group
17
+ # @see http://fredwu.me/post/35625566267/simplecov-test-coverage-for-changed-files-only
18
+ #
19
+
20
+ untracked = `git ls-files --exclude-standard --others`
21
+ unstaged = `git diff --name-only`
22
+ staged = `git diff --name-only --cached`
23
+ all = untracked + unstaged + staged
24
+ changed_filenames = all.split("\n")
25
+
26
+ add_group 'Changed' do |source_file|
27
+ changed_filenames.detect { |changed_filename|
28
+ source_file.filename.end_with?(changed_filename)
29
+ }
30
+ end
31
+
32
+ #
33
+ # Specs are reported on to ensure that all examples are being run and all
34
+ # lets, befores, afters, etc are being used.
35
+ #
36
+
37
+ add_group 'Specs', 'spec'
38
+ end
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --markup markdown
2
+ --protected
3
+ {app,lib}/**/*.rb
4
+ db/migrate/*.rb
data/Gemfile ADDED
@@ -0,0 +1,27 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in metasploit_data_models.gemspec
4
+ gemspec
5
+
6
+ # used by dummy application
7
+ group :development, :test do
8
+ # supplies factories for producing model instance for specs
9
+ # Version 4.1.0 or newer is needed to support generate calls without the 'FactoryGirl.' in factory definitions syntax.
10
+ gem 'factory_girl', '>= 4.1.0'
11
+ # auto-load factories from spec/factories
12
+ gem 'factory_girl_rails'
13
+ # rails is only used for the dummy application in spec/dummy
14
+ gem 'rails'
15
+ end
16
+
17
+ group :test do
18
+ # In a full rails project, factory_girl_rails would be in both the :development, and :test group, but since we only
19
+ # want rails in :test, factory_girl_rails must also only be in :test.
20
+ # add matchers from shoulda, such as validates_presence_of, which are useful for testing validations
21
+ gem 'shoulda-matchers'
22
+ # code coverage of tests
23
+ gem 'simplecov', :require => false
24
+ # need rspec-rails >= 2.12.0 as 2.12.0 adds support for redefining named subject in nested context that uses the
25
+ # named subject from the outer context without causing a stack overflow.
26
+ gem 'rspec-rails', '>= 2.12.0'
27
+ end
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (C) 2012, Rapid7, Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of Rapid7 LLC nor the names of its contributors
15
+ may be used to endorse or promote products derived from this software
16
+ without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ #MetasploitDataModels
2
+
3
+ The database layer for Metasploit
4
+
5
+
6
+ ## Purpose
7
+ __MetasploitDataModels__ exists to do several key things:
8
+
9
+ 1. Allow code sharing between Metasploit Framework (MSF) and the commercial versions of Metasploit (Community, Express, Pro -- usually referred to collectively as "Pro")
10
+
11
+ 2. Give developers a lightweight entry point to MSF's backend for use in developing tools that gather data intended for later use with Metasploit (e.g. specialized scanners).
12
+
13
+ 3. Make it easy to keep commercial stuff private while increasing the functionality of the open-source tools we provide to the community.
14
+
15
+
16
+ ## Usage
17
+
18
+ ### Rails
19
+
20
+ In a Rails application, MetasploitDataModels acts a
21
+ [Rails Engine](http://edgeapi.rubyonrails.org/classes/Rails/Engine.html) and the models are available to application
22
+ just as if they were defined under app/models. If your Rails appliation needs to modify the models, this can be done
23
+ using ActiveSupport.on_load hooks in initializers. The block passed to on_load hook is evaluated in the context of the
24
+ model class, so defining method and including modules will work just like reopeninng the class, but
25
+ ActiveSupport.on_load ensures that the monkey patches will work after reloading in development mode. Each class has a
26
+ different on_load name, which is just the class name converted to an underscored symbol, so Mdm::ApiKey runs the
27
+ :mdm_api_key load hooks, etc.
28
+
29
+ # Gemfile
30
+ gem :metasploiit_data_models, :git => git://github.com/rapid7/metasploit_data_models.git, :tag => 'v0.3.0'
31
+
32
+ # config/initializers/metasploit_data_models.rb
33
+ ActiveSupport.on_load(:mdm_api_key) do
34
+ # Returns the String obfuscated token for display. Meant to avoid CSRF
35
+ # api-key stealing attackes.
36
+ def obfuscated_token
37
+ token[0..3] + "****************************"
38
+ end
39
+ end
40
+
41
+ ### Metasploit Framework
42
+
43
+ In Metasploit Framework, `MetasploitDataModels.require_models` is called by the `Msf::DbManager` to use the data models
44
+ only if the user wants to use the database.
45
+
46
+ ### Elsewhere
47
+
48
+ __NOTE: This isn't in RubyGems yet. Using a Gemfile entry pointing to this repo (i.e., using
49
+ [Bundler](http://gembundler.com)) is the suggested option for now.__
50
+
51
+ Usage outside of Rapid7 is still alpha, as reflected in the pre-1.0.0 version, and we're not making many promises. That
52
+ being said, usage is easy:
53
+
54
+ connection_info = YAML.load_file("path/to/rails-style/db_config_file")
55
+ ActiveRecord::Base.establish_connection(connection_info['development'])
56
+ MetasploitDataModels.require_models
57
+
58
+ Basically you need to do the following things:
59
+
60
+ 1. Establish an ActiveRecord connection. A Rails __config/database.yml__ is ideal for this.
61
+ 2. `MetasploitDataModels.require_models`
62
+
63
+
64
+ ## Developer Info
65
+
66
+ ### Console
67
+ The gem includes a console based on [Pry](https://github.com/pry/pry/)
68
+
69
+ Give it a path to a working MSF database.yml file for full
70
+ ActiveRecord-based access to your data.
71
+
72
+ __Note:__ "development" mode is hardcoded into the console currently.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ print_without = false
9
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
10
+
11
+ begin
12
+ load 'rails/tasks/engine.rake'
13
+ rescue LoadError
14
+ puts "railties not in bundle, so can't load engine tasks."
15
+ print_without = true
16
+ end
17
+
18
+ Bundler::GemHelper.install_tasks
19
+
20
+ #
21
+ # load rake files like a normal rails app
22
+ # @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
23
+ #
24
+
25
+ pathname = Pathname.new(__FILE__)
26
+ root = pathname.parent
27
+ rakefile_glob = root.join('lib', 'tasks', '**', '*.rake').to_path
28
+
29
+ Dir.glob(rakefile_glob) do |rakefile|
30
+ load rakefile
31
+ end
32
+
33
+ begin
34
+ require 'rspec/core'
35
+ rescue LoadError
36
+ puts "rspec not in bundle, so can't set up spec tasks. " \
37
+ "To run specs ensure to install the development and test groups."
38
+ print_without = true
39
+ else
40
+ require 'rspec/core/rake_task'
41
+
42
+ # Depend on app:db:test:prepare so that test database is recreated just like in a full rails app
43
+ # @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl
44
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
45
+
46
+ task :default => :spec
47
+ end
48
+
49
+ if print_without
50
+ puts "Bundle currently installed '--without #{Bundler.settings.without.join(' ')}'."
51
+ puts "To clear the without option do `bundle install --without ''` (the --without flag with an empty string) or " \
52
+ "`rm -rf .bundle` to remove the .bundle/config manually and then `bundle install`"
53
+ end
@@ -0,0 +1,20 @@
1
+ class Mdm::ApiKey < ActiveRecord::Base
2
+ #
3
+ # Validators
4
+ #
5
+
6
+ validate :supports_api
7
+ validates :token, :presence => true, :length => { :minimum => 8 }
8
+
9
+ protected
10
+
11
+ def supports_api
12
+ license = License.get
13
+
14
+ if license and not license.supports_api?
15
+ errors[:license] = " - this product does not support API access"
16
+ end
17
+ end
18
+
19
+ ActiveSupport.run_load_hooks(:mdm_api_key, self)
20
+ end
@@ -0,0 +1,9 @@
1
+ class Mdm::Client < ActiveRecord::Base
2
+ #
3
+ # Relations
4
+ #
5
+ belongs_to :campaign, :class_name => 'Mdm::Campaign'
6
+ belongs_to :host, :class_name => 'Mdm::Host'
7
+
8
+ ActiveSupport.run_load_hooks(:mdm_client, self)
9
+ end
@@ -0,0 +1,80 @@
1
+ class Mdm::Cred < ActiveRecord::Base
2
+ #
3
+ # CONSTANTS
4
+ #
5
+ KEY_ID_REGEX = /([0-9a-fA-F:]{47})/
6
+ PTYPES = {
7
+ 'read/write password' => 'password_rw',
8
+ 'read-only password' => 'password_ro',
9
+ 'SMB hash' => 'smb_hash',
10
+ 'SSH private key' => 'ssh_key',
11
+ 'SSH public key' => 'ssh_pubkey'
12
+ }
13
+
14
+ #
15
+ # Relations
16
+ #
17
+ belongs_to :service, :class_name => "Mdm::Service"
18
+
19
+ def ptype_human
20
+ humanized = PTYPES.select do |k, v|
21
+ v == ptype
22
+ end.keys[0]
23
+
24
+ humanized ? humanized : ptype
25
+ end
26
+
27
+ # Returns its key id. If this is not an ssh-type key, returns nil.
28
+ def ssh_key_id
29
+ return nil unless self.ptype =~ /^ssh_/
30
+ return nil unless self.proof =~ KEY_ID_REGEX
31
+ $1.downcase # Can't run into NilClass problems.
32
+ end
33
+
34
+ def ssh_key_matches?(other_cred)
35
+ return false unless other_cred.kind_of? self.class
36
+ return false unless self.ptype == other_cred.ptype
37
+ case self.ptype
38
+ when "ssh_key"
39
+ matches = self.ssh_private_keys
40
+ when "ssh_pubkey"
41
+ matches = self.ssh_public_keys
42
+ else
43
+ false
44
+ end
45
+ matches.include?(self) and matches.include?(other_cred)
46
+ end
47
+
48
+ # Returns all keys with matching key ids, including itself
49
+ # If this is not an ssh-type key, always returns an empty array.
50
+ def ssh_keys
51
+ (self.ssh_private_keys | self.ssh_public_keys)
52
+ end
53
+
54
+ # Returns all private keys with matching key ids, including itself
55
+ # If this is not an ssh-type key, always returns an empty array.
56
+ def ssh_private_keys
57
+ return [] unless self.ssh_key_id
58
+ matches = self.class.all(
59
+ :conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_key", "%#{self.ssh_key_id}%"]
60
+ )
61
+ matches.select {|c| c.workspace == self.workspace}
62
+ end
63
+
64
+ # Returns all public keys with matching key ids, including itself
65
+ # If this is not an ssh-type key, always returns an empty array.
66
+ def ssh_public_keys
67
+ return [] unless self.ssh_key_id
68
+ matches = self.class.all(
69
+ :conditions => ["creds.ptype = ? AND creds.proof ILIKE ?", "ssh_pubkey", "%#{self.ssh_key_id}%"]
70
+ )
71
+ matches.select {|c| c.workspace == self.workspace}
72
+ end
73
+
74
+ # Returns its workspace
75
+ def workspace
76
+ self.service.host.workspace
77
+ end
78
+
79
+ ActiveSupport.run_load_hooks(:mdm_cred, self)
80
+ end
@@ -0,0 +1,30 @@
1
+ class Mdm::Event < ActiveRecord::Base
2
+ #
3
+ # Relations
4
+ #
5
+
6
+ belongs_to :host, :class_name => 'Mdm::Host'
7
+ belongs_to :workspace, :class_name => 'Mdm::Workspace'
8
+
9
+ #
10
+ # Scopes
11
+ #
12
+
13
+ scope :flagged, where(:critical => true, :seen => false)
14
+ scope :module_run, where(:name => 'module_run')
15
+
16
+ #
17
+ # Serializations
18
+ #
19
+
20
+ serialize :info, MetasploitDataModels::Base64Serializer.new
21
+
22
+ #
23
+ # Validations
24
+ #
25
+
26
+ validates :name, :presence => true
27
+
28
+ ActiveSupport.run_load_hooks(:mdm_event, self)
29
+ end
30
+
@@ -0,0 +1,14 @@
1
+ class Mdm::ExploitAttempt < ActiveRecord::Base
2
+ #
3
+ # Relations
4
+ #
5
+ belongs_to :host, :class_name => 'Mdm::Host', :counter_cache => :exploit_attempt_count
6
+
7
+ #
8
+ # Validations
9
+ #
10
+
11
+ validates :host_id, :presence => true
12
+
13
+ ActiveSupport.run_load_hooks(:mdm_exploit_attempt, self)
14
+ end
@@ -0,0 +1,11 @@
1
+ class Mdm::ExploitedHost < ActiveRecord::Base
2
+ #
3
+ # Relations
4
+ #
5
+
6
+ belongs_to :host, :class_name => 'Mdm::Host'
7
+ belongs_to :service, :class_name => 'Mdm::Service'
8
+ belongs_to :workspace, :class_name => 'Mdm::Workspace'
9
+
10
+ ActiveSupport.run_load_hooks(:mdm_exploited_host, self)
11
+ end
@@ -0,0 +1,134 @@
1
+
2
+ class Mdm::Host < ActiveRecord::Base
3
+ include Mdm::Host::OperatingSystemNormalization
4
+
5
+ #
6
+ # Callbacks
7
+ #
8
+
9
+ before_destroy :cleanup_tags
10
+
11
+ #
12
+ # CONSTANTS
13
+ #
14
+
15
+ # Fields searched for the search scope
16
+ SEARCH_FIELDS = [
17
+ 'address::text',
18
+ 'hosts.name',
19
+ 'os_name',
20
+ 'os_flavor',
21
+ 'os_sp',
22
+ 'mac',
23
+ 'purpose',
24
+ 'comments'
25
+ ]
26
+
27
+ #
28
+ # Relations
29
+ #
30
+
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:
36
+ 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'
42
+ belongs_to :workspace, :class_name => 'Mdm::Workspace'
43
+
44
+ #
45
+ # Through host_tags
46
+ #
47
+ has_many :tags, :through => :hosts_tags, :class_name => 'Mdm::Tag'
48
+
49
+ #
50
+ # Through services
51
+ #
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'
55
+
56
+ #
57
+ # Nested Attributes
58
+ # @note Must be declared after relations being referenced.
59
+ #
60
+
61
+ accepts_nested_attributes_for :services, :reject_if => lambda { |s| s[:port].blank? }, :allow_destroy => true
62
+
63
+ #
64
+ # Validations
65
+ #
66
+
67
+ validates :address,
68
+ :exclusion => {
69
+ :in => ['127.0.0.1']
70
+ },
71
+ :ip_format => true,
72
+ :presence => true,
73
+ :uniqueness => {
74
+ :scope => :workspace_id,
75
+ :unless => :ip_address_invalid?
76
+ }
77
+ validates :workspace, :presence => true
78
+
79
+ #
80
+ # Scopes
81
+ #
82
+
83
+ scope :alive, where({'hosts.state' => 'alive'})
84
+ scope :flagged, where('notes.critical = true AND notes.seen = false').includes(:notes)
85
+ scope :search,
86
+ lambda { |*args|
87
+ # @todo replace with AREL
88
+ terms = SEARCH_FIELDS.collect { |field|
89
+ "#{field} ILIKE ?"
90
+ }
91
+ disjunction = terms.join(' OR ')
92
+ formatted_parameter = "%#{args[0]}%"
93
+ parameters = [formatted_parameter] * SEARCH_FIELDS.length
94
+ conditions = [disjunction] + parameters
95
+
96
+ {
97
+ :conditions => conditions
98
+ }
99
+ }
100
+ scope :tag_search,
101
+ lambda { |*args| where("tags.name" => args[0]).includes(:tags) }
102
+
103
+ def attribute_locked?(attr)
104
+ n = notes.find_by_ntype("host.updated.#{attr}")
105
+ n && n.data[:locked]
106
+ end
107
+
108
+ def cleanup_tags
109
+ # No need to keep tags with no hosts
110
+ tags.each do |tag|
111
+ tag.destroy if tag.hosts == [self]
112
+ end
113
+ # Clean up association table records
114
+ Mdm::HostTag.delete_all("host_id = #{self.id}")
115
+ end
116
+
117
+ # This is replicated by the IpAddressValidator class. Had to put it here as well to avoid
118
+ # SQL errors when checking address uniqueness.
119
+ def ip_address_invalid?
120
+ begin
121
+ potential_ip = IPAddr.new(address)
122
+ return true unless potential_ip.ipv4? || potential_ip.ipv6?
123
+ rescue ArgumentError
124
+ return true
125
+ end
126
+ end
127
+
128
+ def is_vm?
129
+ !!self.virtual_host
130
+ end
131
+
132
+ ActiveSupport.run_load_hooks(:mdm_host, self)
133
+ end
134
+