metasploit_data_models 0.7.0-java
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.
- data/.gitignore +24 -0
- data/.rspec +3 -0
- data/.simplecov +38 -0
- data/.travis.yml +6 -0
- data/.yardopts +4 -0
- data/Gemfile +27 -0
- data/LICENSE +27 -0
- data/README.md +72 -0
- data/Rakefile +53 -0
- data/app/models/mdm/api_key.rb +20 -0
- data/app/models/mdm/client.rb +9 -0
- data/app/models/mdm/cred.rb +93 -0
- data/app/models/mdm/event.rb +30 -0
- data/app/models/mdm/exploit_attempt.rb +14 -0
- data/app/models/mdm/exploited_host.rb +11 -0
- data/app/models/mdm/host.rb +134 -0
- data/app/models/mdm/host_detail.rb +15 -0
- data/app/models/mdm/host_tag.rb +13 -0
- data/app/models/mdm/imported_cred.rb +10 -0
- data/app/models/mdm/listener.rb +24 -0
- data/app/models/mdm/loot.rb +63 -0
- data/app/models/mdm/macro.rb +20 -0
- data/app/models/mdm/mod_ref.rb +3 -0
- data/app/models/mdm/module_action.rb +24 -0
- data/app/models/mdm/module_arch.rb +24 -0
- data/app/models/mdm/module_author.rb +25 -0
- data/app/models/mdm/module_detail.rb +59 -0
- data/app/models/mdm/module_mixin.rb +24 -0
- data/app/models/mdm/module_platform.rb +24 -0
- data/app/models/mdm/module_ref.rb +24 -0
- data/app/models/mdm/module_target.rb +26 -0
- data/app/models/mdm/nexpose_console.rb +20 -0
- data/app/models/mdm/note.rb +49 -0
- data/app/models/mdm/profile.rb +9 -0
- data/app/models/mdm/ref.rb +14 -0
- data/app/models/mdm/report.rb +50 -0
- data/app/models/mdm/report_template.rb +27 -0
- data/app/models/mdm/route.rb +9 -0
- data/app/models/mdm/service.rb +56 -0
- data/app/models/mdm/session.rb +48 -0
- data/app/models/mdm/session_event.rb +9 -0
- data/app/models/mdm/tag.rb +46 -0
- data/app/models/mdm/task.rb +41 -0
- data/app/models/mdm/user.rb +25 -0
- data/app/models/mdm/vuln.rb +60 -0
- data/app/models/mdm/vuln_attempt.rb +15 -0
- data/app/models/mdm/vuln_detail.rb +14 -0
- data/app/models/mdm/vuln_ref.rb +13 -0
- data/app/models/mdm/web_form.rb +16 -0
- data/app/models/mdm/web_page.rb +16 -0
- data/app/models/mdm/web_site.rb +47 -0
- data/app/models/mdm/web_vuln.rb +190 -0
- data/app/models/mdm/wmap_request.rb +3 -0
- data/app/models/mdm/wmap_target.rb +3 -0
- data/app/models/mdm/workspace.rb +196 -0
- data/bin/mdm_console +68 -0
- data/console_db.yml +9 -0
- data/db/migrate/000_create_tables.rb +79 -0
- data/db/migrate/001_add_wmap_tables.rb +35 -0
- data/db/migrate/002_add_workspaces.rb +36 -0
- data/db/migrate/003_move_notes.rb +20 -0
- data/db/migrate/004_add_events_table.rb +16 -0
- data/db/migrate/005_expand_info.rb +58 -0
- data/db/migrate/006_add_timestamps.rb +26 -0
- data/db/migrate/007_add_loots.rb +20 -0
- data/db/migrate/008_create_users.rb +16 -0
- data/db/migrate/009_add_loots_ctype.rb +10 -0
- data/db/migrate/010_add_alert_fields.rb +16 -0
- data/db/migrate/011_add_reports.rb +19 -0
- data/db/migrate/012_add_tasks.rb +24 -0
- data/db/migrate/013_add_tasks_result.rb +10 -0
- data/db/migrate/014_add_loots_fields.rb +12 -0
- data/db/migrate/015_rename_user.rb +16 -0
- data/db/migrate/016_add_host_purpose.rb +10 -0
- data/db/migrate/017_expand_info2.rb +58 -0
- data/db/migrate/018_add_workspace_user_info.rb +29 -0
- data/db/migrate/019_add_workspace_desc.rb +23 -0
- data/db/migrate/020_add_user_preferences.rb +11 -0
- data/db/migrate/021_standardize_info_and_data.rb +18 -0
- data/db/migrate/022_enlarge_event_info.rb +10 -0
- data/db/migrate/023_add_report_downloaded_at.rb +10 -0
- data/db/migrate/024_convert_service_info_to_text.rb +12 -0
- data/db/migrate/025_add_user_admin.rb +19 -0
- data/db/migrate/026_add_creds_table.rb +19 -0
- data/db/migrate/20100819123300_migrate_cred_data.rb +154 -0
- data/db/migrate/20100824151500_add_exploited_table.rb +16 -0
- data/db/migrate/20100908001428_add_owner_to_workspaces.rb +9 -0
- data/db/migrate/20100911122000_add_report_templates.rb +18 -0
- data/db/migrate/20100916151530_require_admin_flag.rb +15 -0
- data/db/migrate/20100916175000_add_campaigns_and_templates.rb +61 -0
- data/db/migrate/20100920012100_add_generate_exe_column.rb +8 -0
- data/db/migrate/20100926214000_add_template_prefs.rb +11 -0
- data/db/migrate/20101001000000_add_web_tables.rb +57 -0
- data/db/migrate/20101002000000_add_query.rb +10 -0
- data/db/migrate/20101007000000_add_vuln_info.rb +15 -0
- data/db/migrate/20101008111800_add_clients_to_campaigns.rb +10 -0
- data/db/migrate/20101009023300_add_campaign_attachments.rb +15 -0
- data/db/migrate/20101104135100_add_imported_creds.rb +17 -0
- data/db/migrate/20101203000000_fix_web_tables.rb +34 -0
- data/db/migrate/20101203000001_expand_host_comment.rb +12 -0
- data/db/migrate/20101206212033_add_limit_to_network_to_workspaces.rb +9 -0
- data/db/migrate/20110112154300_add_module_uuid_to_tasks.rb +9 -0
- data/db/migrate/20110204112800_add_host_tags.rb +28 -0
- data/db/migrate/20110317144932_add_session_table.rb +110 -0
- data/db/migrate/20110414180600_add_local_id_to_session_table.rb +11 -0
- data/db/migrate/20110415175705_add_routes_table.rb +18 -0
- data/db/migrate/20110422000000_convert_binary.rb +73 -0
- data/db/migrate/20110425095900_add_last_seen_to_sessions.rb +8 -0
- data/db/migrate/20110513143900_track_successful_exploits.rb +31 -0
- data/db/migrate/20110517160800_rename_and_prune_nessus_vulns.rb +26 -0
- data/db/migrate/20110527000000_add_task_id_to_reports_table.rb +11 -0
- data/db/migrate/20110527000001_add_api_keys_table.rb +12 -0
- data/db/migrate/20110606000001_add_macros_table.rb +16 -0
- data/db/migrate/20110622000000_add_settings_to_tasks_table.rb +12 -0
- data/db/migrate/20110624000001_add_listeners_table.rb +19 -0
- data/db/migrate/20110625000001_add_macro_to_listeners_table.rb +12 -0
- data/db/migrate/20110630000001_add_nexpose_consoles_table.rb +21 -0
- data/db/migrate/20110630000002_add_name_to_nexpose_consoles_table.rb +12 -0
- data/db/migrate/20110717000001_add_profiles_table.rb +15 -0
- data/db/migrate/20110727163801_expand_cred_ptype_column.rb +9 -0
- data/db/migrate/20110730000001_add_initial_indexes.rb +85 -0
- data/db/migrate/20110812000001_prune_indexes.rb +23 -0
- data/db/migrate/20110922000000_expand_notes.rb +9 -0
- data/db/migrate/20110928101300_add_mod_ref_table.rb +17 -0
- data/db/migrate/20111011110000_add_display_name_to_reports_table.rb +24 -0
- data/db/migrate/20111203000000_inet_columns.rb +13 -0
- data/db/migrate/20111204000000_more_inet_columns.rb +17 -0
- data/db/migrate/20111210000000_add_scope_to_hosts.rb +9 -0
- data/db/migrate/20120126110000_add_virtual_host_to_hosts.rb +9 -0
- data/db/migrate/20120411173220_rename_workspace_members.rb +9 -0
- data/db/migrate/20120601152442_add_counter_caches_to_hosts.rb +21 -0
- data/db/migrate/20120625000000_add_vuln_details.rb +34 -0
- data/db/migrate/20120625000001_add_host_details.rb +16 -0
- data/db/migrate/20120625000002_expand_details.rb +16 -0
- data/db/migrate/20120625000003_expand_details2.rb +24 -0
- data/db/migrate/20120625000004_add_vuln_attempts.rb +19 -0
- data/db/migrate/20120625000005_add_vuln_and_host_counter_caches.rb +14 -0
- data/db/migrate/20120625000006_add_module_details.rb +118 -0
- data/db/migrate/20120625000007_add_exploit_attempts.rb +26 -0
- data/db/migrate/20120625000008_add_fail_message.rb +12 -0
- data/db/migrate/20120718202805_add_owner_and_payload_to_web_vulns.rb +13 -0
- data/db/migrate/20130228214900_change_required_columns_to_null_false_in_web_vulns.rb +35 -0
- data/db/migrate/20130423211152_add_creds_counter_cache.rb +24 -0
- data/lib/mdm.rb +12 -0
- data/lib/mdm/host/operating_system_normalization.rb +984 -0
- data/lib/metasploit_data_models.rb +60 -0
- data/lib/metasploit_data_models/base64_serializer.rb +103 -0
- data/lib/metasploit_data_models/engine.rb +23 -0
- data/lib/metasploit_data_models/serialized_prefs.rb +23 -0
- data/lib/metasploit_data_models/validators/ip_format_validator.rb +13 -0
- data/lib/metasploit_data_models/validators/password_is_strong_validator.rb +70 -0
- data/lib/metasploit_data_models/version.rb +8 -0
- data/lib/tasks/yard.rake +26 -0
- data/metasploit_data_models.gemspec +54 -0
- data/script/rails +8 -0
- data/spec/app/models/mdm/module_action_spec.rb +38 -0
- data/spec/app/models/mdm/module_arch_spec.rb +38 -0
- data/spec/app/models/mdm/module_author_spec.rb +50 -0
- data/spec/app/models/mdm/module_detail_spec.rb +291 -0
- data/spec/app/models/mdm/module_mixin_spec.rb +38 -0
- data/spec/app/models/mdm/module_platform_spec.rb +38 -0
- data/spec/app/models/mdm/module_ref_spec.rb +38 -0
- data/spec/app/models/mdm/module_target_spec.rb +41 -0
- data/spec/app/models/mdm/web_vuln_spec.rb +126 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +61 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml.example +22 -0
- data/spec/dummy/config/database.yml.travis +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/db/schema.rb +639 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/mdm/addresses.rb +7 -0
- data/spec/factories/mdm/hosts.rb +18 -0
- data/spec/factories/mdm/module_actions.rb +14 -0
- data/spec/factories/mdm/module_archs.rb +14 -0
- data/spec/factories/mdm/module_authors.rb +22 -0
- data/spec/factories/mdm/module_details.rb +9 -0
- data/spec/factories/mdm/module_mixins.rb +14 -0
- data/spec/factories/mdm/module_platforms.rb +14 -0
- data/spec/factories/mdm/module_refs.rb +14 -0
- data/spec/factories/mdm/module_targets.rb +19 -0
- data/spec/factories/mdm/services.rb +35 -0
- data/spec/factories/mdm/users.rb +22 -0
- data/spec/factories/mdm/web_sites.rb +8 -0
- data/spec/factories/mdm/web_vulns.rb +64 -0
- data/spec/factories/mdm/workspaces.rb +23 -0
- data/spec/lib/base64_serializer_spec.rb +174 -0
- data/spec/spec_helper.rb +36 -0
- metadata +472 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class Mdm::User < ActiveRecord::Base
|
|
2
|
+
extend MetasploitDataModels::SerializedPrefs
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# Relations
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
has_many :owned_workspaces, :foreign_key => 'owner_id', :class_name => 'Mdm::Workspace'
|
|
9
|
+
has_many :tags, :class_name => 'Mdm::Tag'
|
|
10
|
+
has_and_belongs_to_many :workspaces, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::Workspace'
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# Serialziations
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
serialize :prefs, MetasploitDataModels::Base64Serializer.new
|
|
17
|
+
|
|
18
|
+
serialized_prefs_attr_accessor :nexpose_host, :nexpose_port, :nexpose_user, :nexpose_pass, :nexpose_creds_type, :nexpose_creds_user, :nexpose_creds_pass
|
|
19
|
+
serialized_prefs_attr_accessor :http_proxy_host, :http_proxy_port, :http_proxy_user, :http_proxy_pass
|
|
20
|
+
serialized_prefs_attr_accessor :time_zone, :session_key
|
|
21
|
+
serialized_prefs_attr_accessor :last_login_address # specifically NOT last_login_ip to prevent confusion with AuthLogic magic columns (which dont work for serialized fields)
|
|
22
|
+
|
|
23
|
+
ActiveSupport.run_load_hooks(:mdm_user, self)
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class Mdm::Vuln < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Callbacks
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
after_update :save_refs
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Relations
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
belongs_to :host, :class_name => 'Mdm::Host', :counter_cache => :vuln_count
|
|
13
|
+
belongs_to :service, :class_name => 'Mdm::Service', :foreign_key => :service_id
|
|
14
|
+
has_many :vuln_attempts, :dependent => :destroy, :class_name => 'Mdm::VulnAttempt'
|
|
15
|
+
has_many :vuln_details, :dependent => :destroy, :class_name => 'Mdm::VulnDetail'
|
|
16
|
+
has_many :vulns_refs, :class_name => 'Mdm::VulnRef'
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Through :vuln_refs
|
|
20
|
+
#
|
|
21
|
+
has_many :refs, :through => :vulns_refs, :class_name => 'Mdm::Ref'
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Scopes
|
|
25
|
+
#
|
|
26
|
+
|
|
27
|
+
scope :search, lambda { |*args|
|
|
28
|
+
where(
|
|
29
|
+
[
|
|
30
|
+
'(vulns.name ILIKE ? or vulns.info ILIKE ? or refs.name ILIKE ?)',
|
|
31
|
+
"%#{args[0]}%",
|
|
32
|
+
"%#{args[0]}%",
|
|
33
|
+
"%#{args[0]}%"
|
|
34
|
+
]
|
|
35
|
+
).joins(
|
|
36
|
+
'LEFT OUTER JOIN vulns_refs ON vulns_refs.vuln_id=vulns.id LEFT OUTER JOIN refs ON refs.id=vulns_refs.ref_id'
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
# Validations
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
validates :name, :presence => true
|
|
45
|
+
validates_associated :refs
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def before_destroy
|
|
50
|
+
Mdm::VulnRef.delete_all('vuln_id = ?', self.id)
|
|
51
|
+
Mdm::VulnDetail.delete_all('vuln_id = ?', self.id)
|
|
52
|
+
Mdm::VulnAttempt.delete_all('vuln_id = ?', self.id)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def save_refs
|
|
56
|
+
refs.each { |ref| ref.save(:validate => false) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
ActiveSupport.run_load_hooks(:mdm_vuln, self)
|
|
60
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Mdm::VulnAttempt < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Relations
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
belongs_to :vuln, :class_name => 'Mdm::Vuln', :counter_cache => :vuln_attempt_count
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Validations
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
validates :vuln_id, :presence => true
|
|
13
|
+
|
|
14
|
+
ActiveSupport.run_load_hooks(:mdm_vuln_attempt, self)
|
|
15
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class Mdm::VulnDetail < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Relations
|
|
4
|
+
#
|
|
5
|
+
belongs_to :vuln, :class_name => 'Mdm::Vuln', :counter_cache => :vuln_detail_count
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# Validations
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
validates :vuln_id, :presence => true
|
|
12
|
+
|
|
13
|
+
ActiveSupport.run_load_hooks(:mdm_vuln_detail, self)
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Mdm::VulnRef < ActiveRecord::Base
|
|
2
|
+
self.table_name = 'vulns_refs'
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# Relations
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
belongs_to :ref, :class_name => 'Mdm::Ref'
|
|
9
|
+
belongs_to :vuln, :class_name => 'Mdm::Vuln'
|
|
10
|
+
|
|
11
|
+
ActiveSupport.run_load_hooks(:mdm_vuln_ref, self)
|
|
12
|
+
end
|
|
13
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Mdm::WebForm < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Relations
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
belongs_to :web_site, :class_name => 'Mdm::WebSite'
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Serializations
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
serialize :params, MetasploitDataModels::Base64Serializer.new
|
|
13
|
+
|
|
14
|
+
ActiveSupport.run_load_hooks(:mdm_web_form, self)
|
|
15
|
+
end
|
|
16
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Mdm::WebPage < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Relations
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
belongs_to :web_site, :class_name => 'Mdm::WebSite'
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Serializations
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
serialize :headers, MetasploitDataModels::Base64Serializer.new
|
|
13
|
+
|
|
14
|
+
ActiveSupport.run_load_hooks(:mdm_web_page, self)
|
|
15
|
+
end
|
|
16
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class Mdm::WebSite < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Relations
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
belongs_to :service, :class_name => 'Mdm::Service', :foreign_key => 'service_id'
|
|
7
|
+
has_many :web_forms, :dependent => :destroy, :class_name => 'Mdm::WebForm'
|
|
8
|
+
has_many :web_pages, :dependent => :destroy, :class_name => 'Mdm::WebPage'
|
|
9
|
+
has_many :web_vulns, :dependent => :destroy, :class_name => 'Mdm::WebVuln'
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Serializations
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
serialize :options, ::MetasploitDataModels::Base64Serializer.new
|
|
16
|
+
|
|
17
|
+
def form_count
|
|
18
|
+
web_forms.size
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def page_count
|
|
22
|
+
web_pages.size
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def to_url(ignore_vhost=false)
|
|
26
|
+
proto = self.service.name == "https" ? "https" : "http"
|
|
27
|
+
host = ignore_vhost ? self.service.host.address : self.vhost
|
|
28
|
+
port = self.service.port
|
|
29
|
+
|
|
30
|
+
if Rex::Socket.is_ipv6?(host)
|
|
31
|
+
host = "[#{host}]"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
url = "#{proto}://#{host}"
|
|
35
|
+
if not ((proto == "http" and port == 80) or (proto == "https" and port == 443))
|
|
36
|
+
url += ":#{port}"
|
|
37
|
+
end
|
|
38
|
+
url
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def vuln_count
|
|
42
|
+
web_vulns.size
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
ActiveSupport.run_load_hooks(:mdm_web_site, self)
|
|
46
|
+
end
|
|
47
|
+
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# A Web Vulnerability found during a web scan or web audit.
|
|
2
|
+
#
|
|
3
|
+
# If you need to modify Mdm::WebVuln you can use ActiveSupport.on_load(:mdm_web_vuln) inside an initializer so that
|
|
4
|
+
# your patches are reloaded on each request in development mode for your Rails application.
|
|
5
|
+
#
|
|
6
|
+
# @example extending Mdm::WebVuln
|
|
7
|
+
# # config/initializers/mdm_web_vuln.rb
|
|
8
|
+
# ActiveSupport.on_load(:mdm_web_vuln) do
|
|
9
|
+
# def confidence_percentage
|
|
10
|
+
# "#{confidence}%"
|
|
11
|
+
# end
|
|
12
|
+
# end
|
|
13
|
+
class Mdm::WebVuln < ActiveRecord::Base
|
|
14
|
+
#
|
|
15
|
+
# CONSTANTS
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
# A percentage {#confidence} that the vulnerability is real and not a false positive.
|
|
19
|
+
CONFIDENCE_RANGE = 0 .. 100
|
|
20
|
+
|
|
21
|
+
# Default value for {#params}
|
|
22
|
+
DEFAULT_PARAMS = []
|
|
23
|
+
|
|
24
|
+
# Allowed {#method methods}.
|
|
25
|
+
METHODS = [
|
|
26
|
+
'GET',
|
|
27
|
+
# XXX I don't know why PATH is a valid method when it's not an HTTP Method/Verb
|
|
28
|
+
'PATH',
|
|
29
|
+
'POST'
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# {#risk Risk} is rated on a scale from 0 (least risky) to 5 (most risky).
|
|
33
|
+
RISK_RANGE = 0 .. 5
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Associations
|
|
37
|
+
#
|
|
38
|
+
|
|
39
|
+
belongs_to :web_site, :class_name => 'Mdm::WebSite'
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# Attributes
|
|
43
|
+
#
|
|
44
|
+
|
|
45
|
+
# @!attribute [rw] blame
|
|
46
|
+
# Who to blame for the vulnerability
|
|
47
|
+
#
|
|
48
|
+
# @return [String]
|
|
49
|
+
|
|
50
|
+
# @!attribute [rw] category
|
|
51
|
+
# Category of this vulnerability.
|
|
52
|
+
#
|
|
53
|
+
# @return [String]
|
|
54
|
+
|
|
55
|
+
# @!attribute [rw] confidence
|
|
56
|
+
# Percentage confidence scanner or auditor has that this vulnerability is not a false positive
|
|
57
|
+
#
|
|
58
|
+
# @return [Integer] 1% to 100%
|
|
59
|
+
|
|
60
|
+
# @!attribute [rw] description
|
|
61
|
+
# Description of the vulnerability
|
|
62
|
+
#
|
|
63
|
+
# @return [String, nil]
|
|
64
|
+
|
|
65
|
+
# @!attribute [rw] method
|
|
66
|
+
# HTTP Methods for request that found vulnerability. 'PATH' is also allowed even though it is not an HTTP Method.
|
|
67
|
+
#
|
|
68
|
+
# @return [String]
|
|
69
|
+
# @see METHODS
|
|
70
|
+
|
|
71
|
+
# @!attribute [rw] name
|
|
72
|
+
# Name of the vulnerability
|
|
73
|
+
#
|
|
74
|
+
# @return [String]
|
|
75
|
+
|
|
76
|
+
# @!attribute [rw] path
|
|
77
|
+
# Path portion of URL
|
|
78
|
+
#
|
|
79
|
+
# @return [String]
|
|
80
|
+
|
|
81
|
+
# @!attribute [rw] payload
|
|
82
|
+
# Web audit payload that gets executed by the remote server. Used for code injection vulnerabilities.
|
|
83
|
+
#
|
|
84
|
+
# @return [String, nil]
|
|
85
|
+
|
|
86
|
+
# @!attribute [rw] pname
|
|
87
|
+
# Name of parameter that demonstrates vulnerability
|
|
88
|
+
#
|
|
89
|
+
# @return [String]
|
|
90
|
+
|
|
91
|
+
# @!attribute [rw] proof
|
|
92
|
+
# String that proves vulnerability, such as a code snippet, etc.
|
|
93
|
+
#
|
|
94
|
+
# @return [String]
|
|
95
|
+
|
|
96
|
+
# @!attribute [rw] query
|
|
97
|
+
# The GET query.
|
|
98
|
+
#
|
|
99
|
+
# @return [String]
|
|
100
|
+
|
|
101
|
+
# @!attribute [rw] request
|
|
102
|
+
#
|
|
103
|
+
# @return [String]
|
|
104
|
+
|
|
105
|
+
# @!attribute [rw] risk
|
|
106
|
+
# {RISK_RANGE Risk} of leaving this vulnerability unpatched.
|
|
107
|
+
#
|
|
108
|
+
# @return [Integer]
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Validations
|
|
112
|
+
#
|
|
113
|
+
|
|
114
|
+
validates :category, :presence => true
|
|
115
|
+
validates :confidence,
|
|
116
|
+
:inclusion => {
|
|
117
|
+
:in => CONFIDENCE_RANGE
|
|
118
|
+
}
|
|
119
|
+
validates :method,
|
|
120
|
+
:inclusion => {
|
|
121
|
+
:in => METHODS
|
|
122
|
+
}
|
|
123
|
+
validates :name, :presence => true
|
|
124
|
+
validates :path, :presence => true
|
|
125
|
+
validates :pname, :presence => true
|
|
126
|
+
validates :proof, :presence => true
|
|
127
|
+
validates :risk,
|
|
128
|
+
:inclusion => {
|
|
129
|
+
:in => RISK_RANGE
|
|
130
|
+
}
|
|
131
|
+
validates :web_site, :presence => true
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# Serializations
|
|
135
|
+
#
|
|
136
|
+
|
|
137
|
+
# @!attribute [rw] params
|
|
138
|
+
# Parameters sent as part of request
|
|
139
|
+
#
|
|
140
|
+
# @return [Array<Array<(String, String)>>] Array of parameter key value pairs
|
|
141
|
+
serialize :params, MetasploitDataModels::Base64Serializer.new(:default => DEFAULT_PARAMS)
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Methods
|
|
145
|
+
#
|
|
146
|
+
|
|
147
|
+
# Parameters sent as part of request.
|
|
148
|
+
#
|
|
149
|
+
# @return [Array<Array<(String, String)>>]
|
|
150
|
+
def params
|
|
151
|
+
normalize_params(
|
|
152
|
+
read_attribute(:params)
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Set parameters sent as part of request.
|
|
157
|
+
#
|
|
158
|
+
# @param params [Array<Array<(String, String)>>, nil] Array of parameter key value pairs
|
|
159
|
+
# @return [void]
|
|
160
|
+
def params=(params)
|
|
161
|
+
write_attribute(
|
|
162
|
+
:params,
|
|
163
|
+
normalize_params(params)
|
|
164
|
+
)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
private
|
|
168
|
+
|
|
169
|
+
# Creates a duplicate of {DEFAULT_PARAMS} that is safe to modify.
|
|
170
|
+
#
|
|
171
|
+
# @return [Array] an empty array
|
|
172
|
+
def default_params
|
|
173
|
+
DEFAULT_PARAMS.dup
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Returns either the given params or {DEFAULT_PARAMS} if params is `nil`
|
|
177
|
+
#
|
|
178
|
+
# @param [Array<Array<(String, String)>>, nil] params
|
|
179
|
+
# @return [Array<<Array<(String, String)>>] params if not `nil`
|
|
180
|
+
# @return [nil] if params is `nil`
|
|
181
|
+
def normalize_params(params)
|
|
182
|
+
params || default_params
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# switch back to public for load hooks
|
|
186
|
+
public
|
|
187
|
+
|
|
188
|
+
ActiveSupport.run_load_hooks(:mdm_web_vuln, self)
|
|
189
|
+
end
|
|
190
|
+
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
class Mdm::Workspace < ActiveRecord::Base
|
|
2
|
+
#
|
|
3
|
+
# Callbacks
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
before_save :normalize
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# CONSTANTS
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
DEFAULT = 'default'
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Relations
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
has_many :creds, :through => :services, :class_name => 'Mdm::Cred'
|
|
19
|
+
has_many :events, :class_name => 'Mdm::Event'
|
|
20
|
+
has_many :hosts, :dependent => :destroy, :class_name => 'Mdm::Host'
|
|
21
|
+
has_many :imported_creds, :dependent => :destroy, :class_name => 'Mdm::ImportedCred'
|
|
22
|
+
has_many :listeners, :dependent => :destroy, :class_name => 'Mdm::Listener'
|
|
23
|
+
has_many :notes, :class_name => 'Mdm::Note'
|
|
24
|
+
belongs_to :owner, :class_name => 'Mdm::User', :foreign_key => 'owner_id'
|
|
25
|
+
has_many :report_templates, :dependent => :destroy, :class_name => 'Mdm::ReportTemplate'
|
|
26
|
+
has_many :reports, :dependent => :destroy, :class_name => 'Mdm::Report'
|
|
27
|
+
has_many :tasks, :dependent => :destroy, :class_name => 'Mdm::Task', :order => 'created_at DESC'
|
|
28
|
+
has_and_belongs_to_many :users, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::User'
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
# Through :hosts
|
|
32
|
+
#
|
|
33
|
+
has_many :clients, :through => :hosts, :class_name => 'Mdm::Client'
|
|
34
|
+
has_many :exploited_hosts, :through => :hosts, :class_name => 'Mdm::ExploitedHost'
|
|
35
|
+
has_many :loots, :through => :hosts, :class_name => 'Mdm::Loot'
|
|
36
|
+
has_many :vulns, :through => :hosts, :class_name => 'Mdm::Vuln'
|
|
37
|
+
has_many :services, :through => :hosts, :class_name => 'Mdm::Service', :foreign_key => 'service_id'
|
|
38
|
+
has_many :sessions, :through => :hosts, :class_name => 'Mdm::Session'
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
# Validations
|
|
42
|
+
#
|
|
43
|
+
|
|
44
|
+
validates :name, :presence => true, :uniqueness => true, :length => {:maximum => 255}
|
|
45
|
+
validates :description, :length => {:maximum => 4096}
|
|
46
|
+
validate :boundary_must_be_ip_range
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# If limit_to_network is disabled, this will always return true.
|
|
50
|
+
# Otherwise, return true only if all of the given IPs are within the project
|
|
51
|
+
# boundaries.
|
|
52
|
+
#
|
|
53
|
+
def allow_actions_on?(ips)
|
|
54
|
+
return true unless limit_to_network
|
|
55
|
+
return true unless boundary
|
|
56
|
+
return true if boundary.empty?
|
|
57
|
+
boundaries = Shellwords.split(boundary)
|
|
58
|
+
return true if boundaries.empty? # It's okay if there is no boundary range after all
|
|
59
|
+
given_range = Rex::Socket::RangeWalker.new(ips)
|
|
60
|
+
return false unless given_range # Can't do things to nonexistant IPs
|
|
61
|
+
allowed = false
|
|
62
|
+
boundaries.each do |boundary_range|
|
|
63
|
+
ok_range = Rex::Socket::RangeWalker.new(boundary)
|
|
64
|
+
allowed = true if ok_range.include_range? given_range
|
|
65
|
+
end
|
|
66
|
+
return allowed
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def boundary_must_be_ip_range
|
|
70
|
+
errors.add(:boundary, "must be a valid IP range") unless valid_ip_or_range?(boundary)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def creds
|
|
74
|
+
Mdm::Cred.find(
|
|
75
|
+
:all,
|
|
76
|
+
:include => {:service => :host},
|
|
77
|
+
:conditions => ["hosts.workspace_id = ?", self.id]
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.default
|
|
82
|
+
find_or_create_by_name(DEFAULT)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def default?
|
|
86
|
+
name == DEFAULT
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# This method iterates the creds table calling the supplied block with the
|
|
91
|
+
# cred instance of each entry.
|
|
92
|
+
#
|
|
93
|
+
def each_cred(&block)
|
|
94
|
+
creds.each do |cred|
|
|
95
|
+
block.call(cred)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def each_host_tag(&block)
|
|
100
|
+
host_tags.each do |host_tag|
|
|
101
|
+
block.call(host_tag)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def host_tags
|
|
106
|
+
Mdm::Tag.find(
|
|
107
|
+
:all,
|
|
108
|
+
:include => :hosts,
|
|
109
|
+
:conditions => ["hosts.workspace_id = ?", self.id]
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def web_forms
|
|
114
|
+
query = <<-EOQ
|
|
115
|
+
SELECT DISTINCT web_forms.*
|
|
116
|
+
FROM hosts, services, web_sites, web_forms
|
|
117
|
+
WHERE hosts.workspace_id = #{id} AND
|
|
118
|
+
services.host_id = hosts.id AND
|
|
119
|
+
web_sites.service_id = services.id AND
|
|
120
|
+
web_forms.web_site_id = web_sites.id
|
|
121
|
+
EOQ
|
|
122
|
+
Mdm::WebForm.find_by_sql(query)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def web_pages
|
|
126
|
+
query = <<-EOQ
|
|
127
|
+
SELECT DISTINCT web_pages.*
|
|
128
|
+
FROM hosts, services, web_sites, web_pages
|
|
129
|
+
WHERE hosts.workspace_id = #{id} AND
|
|
130
|
+
services.host_id = hosts.id AND
|
|
131
|
+
web_sites.service_id = services.id AND
|
|
132
|
+
web_pages.web_site_id = web_sites.id
|
|
133
|
+
EOQ
|
|
134
|
+
Mdm::WebPage.find_by_sql(query)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def web_sites
|
|
138
|
+
query = <<-EOQ
|
|
139
|
+
SELECT DISTINCT web_sites.*
|
|
140
|
+
FROM hosts, services, web_sites
|
|
141
|
+
WHERE hosts.workspace_id = #{id} AND
|
|
142
|
+
services.host_id = hosts.id AND
|
|
143
|
+
web_sites.service_id = services.id
|
|
144
|
+
EOQ
|
|
145
|
+
Mdm::WebSite.find_by_sql(query)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def web_vulns
|
|
149
|
+
query = <<-EOQ
|
|
150
|
+
SELECT DISTINCT web_vulns.*
|
|
151
|
+
FROM hosts, services, web_sites, web_vulns
|
|
152
|
+
WHERE hosts.workspace_id = #{id} AND
|
|
153
|
+
services.host_id = hosts.id AND
|
|
154
|
+
web_sites.service_id = services.id AND
|
|
155
|
+
web_vulns.web_site_id = web_sites.id
|
|
156
|
+
EOQ
|
|
157
|
+
Mdm::WebVuln.find_by_sql(query)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def unique_web_forms
|
|
161
|
+
query = <<-EOQ
|
|
162
|
+
SELECT DISTINCT web_forms.web_site_id, web_forms.path, web_forms.method, web_forms.query
|
|
163
|
+
FROM hosts, services, web_sites, web_forms
|
|
164
|
+
WHERE hosts.workspace_id = #{id} AND
|
|
165
|
+
services.host_id = hosts.id AND
|
|
166
|
+
web_sites.service_id = services.id AND
|
|
167
|
+
web_forms.web_site_id = web_sites.id
|
|
168
|
+
EOQ
|
|
169
|
+
Mdm::WebForm.find_by_sql(query)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def web_unique_forms(addrs=nil)
|
|
173
|
+
forms = unique_web_forms
|
|
174
|
+
if addrs
|
|
175
|
+
forms.reject!{|f| not addrs.include?( f.web_site.service.host.address ) }
|
|
176
|
+
end
|
|
177
|
+
forms
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
|
|
182
|
+
def normalize
|
|
183
|
+
boundary.strip! if boundary
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def valid_ip_or_range?(string)
|
|
187
|
+
begin
|
|
188
|
+
Rex::Socket::RangeWalker.new(string)
|
|
189
|
+
rescue
|
|
190
|
+
return false
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
ActiveSupport.run_load_hooks(:mdm_workspace, self)
|
|
195
|
+
end
|
|
196
|
+
|