├── spec ├── dummy │ ├── log │ │ └── .gitkeep │ ├── app │ │ ├── mailers │ │ │ └── .gitkeep │ │ ├── models │ │ │ ├── .gitkeep │ │ │ └── application_record.rb │ │ ├── assets │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ ├── stylesheets │ │ │ │ └── application.css │ │ │ └── javascripts │ │ │ │ └── application.js │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── controllers │ │ │ └── application_controller.rb │ │ └── views │ │ │ └── layouts │ │ │ └── application.html.erb │ ├── lib │ │ └── assets │ │ │ └── .gitkeep │ ├── public │ │ ├── favicon.ico │ │ ├── 500.html │ │ ├── 422.html │ │ └── 404.html │ ├── config │ │ ├── routes.rb │ │ ├── initializers │ │ │ ├── cookies_serializer.rb │ │ │ ├── session_store.rb │ │ │ ├── mime_types.rb │ │ │ ├── active_record_migrations.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── backtrace_silencers.rb │ │ │ ├── wrap_parameters.rb │ │ │ └── inflections.rb │ │ ├── storage.yml │ │ ├── environment.rb │ │ ├── boot.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── database.yml.example │ │ ├── database.yml.github_actions │ │ └── environments │ │ │ └── development.rb │ ├── bin │ │ ├── rake │ │ ├── bundle │ │ └── rails │ ├── config.ru │ ├── Rakefile │ └── script │ │ └── rails ├── app │ └── models │ │ ├── mdm │ │ ├── macro_spec.rb │ │ ├── api_key_spec.rb │ │ ├── mod_ref_spec.rb │ │ ├── profile_spec.rb │ │ ├── wmap_target_spec.rb │ │ ├── wmap_request_spec.rb │ │ ├── module │ │ │ ├── arch_spec.rb │ │ │ ├── mixin_spec.rb │ │ │ ├── action_spec.rb │ │ │ ├── platform_spec.rb │ │ │ ├── target_spec.rb │ │ │ └── author_spec.rb │ │ ├── route_spec.rb │ │ ├── vuln_ref_spec.rb │ │ ├── client_spec.rb │ │ ├── session_event_spec.rb │ │ └── web_form_spec.rb │ │ └── metasploit_data_models │ │ ├── search │ │ ├── operator │ │ │ └── ip_address_spec.rb │ │ ├── operation │ │ │ └── port │ │ │ │ └── number_spec.rb │ │ └── visitor │ │ │ └── method_spec.rb │ │ ├── ip_address │ │ └── v4 │ │ │ └── segment │ │ │ └── segmented_spec.rb │ │ └── automatic_exploitation │ │ └── match_spec.rb ├── factories │ ├── mdm │ │ ├── payloads.rb │ │ ├── clients.rb │ │ ├── vuln_refs.rb │ │ ├── web_sites.rb │ │ ├── host_details.rb │ │ ├── vuln_attempts.rb │ │ ├── vuln_details.rb │ │ ├── exploit_attempts.rb │ │ ├── refs.rb │ │ ├── exploited_hosts.rb │ │ ├── fingerprints │ │ │ ├── nessus_fingerprints.rb │ │ │ ├── retina_fingerprints.rb │ │ │ ├── session_fingerprints.rb │ │ │ ├── nexpose_fingerprints.rb │ │ │ └── nmap_fingerprints.rb │ │ ├── session_events.rb │ │ ├── host_tags.rb │ │ ├── addresses.rb │ │ ├── service_links.rb │ │ ├── task_creds.rb │ │ ├── task_hosts.rb │ │ ├── task_services.rb │ │ ├── task_sessions.rb │ │ ├── loots.rb │ │ ├── notes.rb │ │ ├── task.rb │ │ ├── module │ │ │ ├── refs.rb │ │ │ ├── archs.rb │ │ │ ├── mixins.rb │ │ │ ├── actions.rb │ │ │ ├── platforms.rb │ │ │ ├── targets.rb │ │ │ └── authors.rb │ │ ├── listeners.rb │ │ ├── tags.rb │ │ ├── sessions.rb │ │ ├── events.rb │ │ ├── creds.rb │ │ ├── nexpose_consoles.rb │ │ ├── vulns.rb │ │ ├── workspaces.rb │ │ ├── users.rb │ │ ├── web_forms.rb │ │ ├── routes.rb │ │ └── services.rb │ ├── metasploit_data_models │ │ └── automatic_exploitation │ │ │ ├── runs.rb │ │ │ ├── match_results.rb │ │ │ ├── match_sets.rb │ │ │ └── matches.rb │ └── module_runs.rb ├── lib │ ├── metasploit_data_models_spec.rb │ ├── ipaddr_spec.rb │ └── metasploit_data_models │ │ └── match │ │ └── child_spec.rb └── support │ ├── shared │ ├── contexts │ │ └── rex │ │ │ └── text.rb │ └── examples │ │ ├── coerces_inet_column_type_to_string.rb │ │ ├── mdm │ │ └── module │ │ │ └── detail │ │ │ ├── does_not_support_stance_with_mtype.rb │ │ │ └── supports_stance_with_mtype.rb │ │ └── metasploit_data_models │ │ └── search │ │ └── visitor │ │ ├── includes │ │ └── visit │ │ │ ├── with_metasploit_model_search_operation_base.rb │ │ │ └── with_children.rb │ │ └── where │ │ └── visit │ │ ├── with_equality.rb │ │ └── with_metasploit_model_search_group_base.rb │ └── matchers │ └── match_regex_exactly.rb ├── .rspec ├── UPGRADING.md ├── .yardopts ├── CHANGELOG.md ├── db └── migrate │ ├── 20161227212223_add_os_family_to_hosts.rb │ ├── 20130516204810_making_vulns_refs_a_real_ar_model.rb │ ├── 20140905031549_add_detected_arch_to_host.rb │ ├── 20190507120211_remove_payload_workspaces.rb │ ├── 20130531144949_making_host_tags_a_real_ar_model.rb │ ├── 20130717150737_remove_pname_validation.rb │ ├── 20150205192745_drop_service_uniqueness_index.rb │ ├── 20150209195939_add_vuln_id_to_note.rb │ ├── 20250716155919_add_resource_to_mdm_vuln.rb │ ├── 20160415153312_remove_not_null_from_web_vuln_p_arams.rb │ ├── 20250717170556_add_resource_to_services.rb │ ├── 20250720082201_drop_service_uniqueness_index2.rb │ ├── 20161004165612_add_fingerprinted_to_workspace.rb │ ├── 013_add_tasks_result.rb │ ├── 016_add_host_purpose.rb │ ├── 009_add_loots_ctype.rb │ ├── 20111210000000_add_scope_to_hosts.rb │ ├── 20150226151459_add_module_run_fk_to_loot.rb │ ├── 20110425095900_add_last_seen_to_sessions.rb │ ├── 20110922000000_expand_notes.rb │ ├── 020_add_user_preferences.rb │ ├── 022_enlarge_event_info.rb │ ├── 20150219215039_add_module_run_to_session.rb │ ├── 023_add_report_downloaded_at.rb │ ├── 20100908001428_add_owner_to_workspaces.rb │ ├── 20101008111800_add_clients_to_campaigns.rb │ ├── 20120126110000_add_virtual_host_to_hosts.rb │ ├── 20110527000000_add_task_id_to_reports_table.rb │ ├── 20110622000000_add_settings_to_tasks_table.rb │ ├── 20110112154300_add_module_uuid_to_tasks.rb │ ├── 20110414180600_add_local_id_to_session_table.rb │ ├── 20110625000001_add_macro_to_listeners_table.rb │ ├── 20130525015035_remove_campaign_id_from_clients.rb │ ├── 20150312155312_add_module_full_name_to_match.rb │ ├── 20120411173220_rename_workspace_members.rb │ ├── 20101203000001_expand_host_comment.rb │ ├── 20110527000001_add_api_keys_table.rb │ ├── 20110727163801_expand_cred_ptype_column.rb │ ├── 024_convert_service_info_to_text.rb │ ├── 014_add_loots_fields.rb │ ├── 20100920012100_add_generate_exe_column.rb │ ├── 20110630000002_add_name_to_nexpose_consoles_table.rb │ ├── 20101002000000_add_query.rb │ ├── 20130522001343_create_task_creds.rb │ ├── 20130522032517_create_task_hosts.rb │ ├── 20101009023300_add_campaign_attachments.rb │ ├── 20130522041110_create_task_services.rb │ ├── 20130604145732_create_task_sessions.rb │ ├── 20101206212033_add_limit_to_network_to_workspaces.rb │ ├── 20130510021637_remove_campaigns.rb │ ├── 015_rename_user.rb │ ├── 20111203000000_inet_columns.rb │ ├── 20131008213344_create_automatic_exploitation_runs.rb │ ├── 20120625000008_add_fail_message.rb │ ├── 20110606000001_add_macros_table.rb │ ├── 20110717000001_add_profiles_table.rb │ ├── 20120718202805_add_owner_and_payload_to_web_vulns.rb │ ├── 004_add_events_table.rb │ ├── 20150514182921_add_origin_to_mdm_vuln.rb │ ├── 20100926214000_add_template_prefs.rb │ ├── 20131017150735_create_automatic_exploitation_match_results.rb │ ├── 008_create_users.rb │ ├── 20110415175705_add_routes_table.rb │ ├── 20190308134512_create_async_callbacks.rb │ ├── 20131011184338_module_detail_on_automatic_exploitation_match.rb │ ├── 011_add_reports.rb │ ├── 20250718122714_create_service_links.rb │ ├── 20100916151530_require_admin_flag.rb │ ├── 20131002004641_create_automatic_exploitation_matches.rb │ ├── 20131021185657_make_match_polymorphic.rb │ ├── 20100911122000_add_report_templates.rb │ ├── 010_add_alert_fields.rb │ ├── 20101104135100_add_imported_creds.rb │ ├── 20120625000001_add_host_details.rb │ ├── 20130525212420_drop_table_imported_creds.rb │ ├── 20131002164449_create_automatic_exploitation_match_sets.rb │ ├── 20150326183742_add_missing_ae_indices.rb │ ├── 007_add_loots.rb │ ├── 021_standardize_info_and_data.rb │ ├── 20110928101300_add_mod_ref_table.rb │ ├── 20100824151500_add_exploited_table.rb │ ├── 019_add_workspace_desc.rb │ ├── 025_add_user_admin.rb │ ├── 20101007000000_add_vuln_info.rb │ ├── 20110624000001_add_listeners_table.rb │ ├── 20120625000002_expand_details.rb │ ├── 20120625000005_add_vuln_and_host_counter_caches.rb │ ├── 026_add_creds_table.rb │ ├── 20130430151353_change_required_columns_to_null_false_in_hosts.rb │ ├── 20150112203945_remove_duplicate_services.rb │ ├── 20150212214222_remove_duplicate_services2.rb │ ├── 20110630000001_add_nexpose_consoles_table.rb │ ├── 003_move_notes.rb │ ├── 012_add_tasks.rb │ ├── 20180904120211_create_payloads.rb │ ├── 20250721114306_remove_duplicate_services3.rb │ ├── 20110812000001_prune_indexes.rb │ ├── 018_add_workspace_user_info.rb │ ├── 20111011110000_add_display_name_to_reports_table.rb │ ├── 20111204000000_more_inet_columns.rb │ ├── 20150219173821_create_module_runs.rb │ ├── 20130228214900_change_required_columns_to_null_false_in_web_vulns.rb │ ├── 20110204112800_add_host_tags.rb │ ├── 20110517160800_rename_and_prune_nessus_vulns.rb │ ├── 20120601152442_add_counter_caches_to_hosts.rb │ ├── 20150421211719_rename_automatic_exploitation_index.rb │ ├── 20110513143900_track_successful_exploits.rb │ ├── 20130423211152_add_creds_counter_cache.rb │ ├── 20130412174719_change_foreign_key_in_module_refs.rb │ ├── 20130412171844_change_foreign_key_in_module_archs.rb │ ├── 20130412173640_change_foreign_key_in_module_mixins.rb │ ├── 20120625000004_add_vuln_attempts.rb │ ├── 20130412154159_change_foreign_key_in_module_actions.rb │ ├── 20130412173121_change_foreign_key_in_module_authors.rb │ ├── 20130412175040_change_foreign_key_in_module_targets.rb │ ├── 20130412174254_change_foreign_key_in_module_platforms.rb │ ├── 001_add_wmap_tables.rb │ ├── 20120625000003_expand_details2.rb │ ├── 002_add_workspaces.rb │ ├── 006_add_timestamps.rb │ ├── 20130515172727_valid_mdm_web_vuln_params.rb │ ├── 20101203000000_fix_web_tables.rb │ ├── 20120625000007_add_exploit_attempts.rb │ ├── 20130515164311_change_web_vulns_confidence_to_integer.rb │ ├── 005_expand_info.rb │ ├── 017_expand_info2.rb │ ├── 20120625000000_add_vuln_details.rb │ ├── 20101001000000_add_web_tables.rb │ └── 20150317145455_rename_module_indices.rb ├── console_db.yml ├── lib ├── metasploit_data_models │ ├── search │ │ ├── operator │ │ │ └── port.rb │ │ ├── operator.rb │ │ ├── operation.rb │ │ ├── visitor.rb │ │ └── operation │ │ │ └── port.rb │ ├── ip_address │ │ ├── v4 │ │ │ ├── segment.rb │ │ │ └── segment │ │ │ │ └── nmap.rb │ │ └── v4.rb │ ├── search.rb │ ├── version.rb │ ├── ip_address.rb │ ├── match.rb │ ├── change_required_columns_to_null_false.rb │ ├── serialized_prefs.rb │ ├── automatic_exploitation.rb │ ├── yaml.rb │ └── engine.rb ├── mdm │ └── module.rb ├── metasploit_data_models.rb └── mdm.rb ├── script └── rails ├── app └── models │ ├── metasploit_data_models │ ├── ip_address │ │ └── v4 │ │ │ ├── range.rb │ │ │ ├── segment │ │ │ └── nmap │ │ │ │ └── range.rb │ │ │ ├── nmap.rb │ │ │ └── cidr.rb │ ├── search │ │ ├── visitor │ │ │ ├── method.rb │ │ │ ├── attribute.rb │ │ │ └── includes.rb │ │ ├── operation │ │ │ ├── port │ │ │ │ └── number.rb │ │ │ └── range.rb │ │ └── operator │ │ │ └── ip_address.rb │ └── automatic_exploitation │ │ ├── run.rb │ │ └── match_set.rb │ └── mdm │ ├── vuln_ref.rb │ ├── module │ ├── arch.rb │ ├── platform.rb │ ├── mixin.rb │ ├── author.rb │ ├── target.rb │ ├── action.rb │ └── ref.rb │ ├── mod_ref.rb │ ├── route.rb │ ├── task_host.rb │ ├── task_service.rb │ ├── task_session.rb │ ├── client.rb │ ├── session_event.rb │ ├── host_tag.rb │ ├── api_key.rb │ ├── exploited_host.rb │ ├── wmap_target.rb │ ├── task_cred.rb │ ├── service_link.rb │ ├── profile.rb │ └── web_form.rb ├── cortex.yaml ├── bin └── rails ├── config └── initializers │ └── ipaddr.rb ├── .gitignore ├── .github └── workflows │ └── verify.yml ├── .simplecov └── LICENSE /spec/dummy/log/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/mailers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/lib/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /spec/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | end 3 | -------------------------------------------------------------------------------- /spec/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | No Deprecations or Incompatible Changes have been introduced at this time -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown 2 | --plugin yard-metasploit-erd 3 | --protected 4 | {app,lib}/**/*.rb 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Next Release 2 | 3 | * Enhancements 4 | * Bug Fixes 5 | * Deprecations 6 | * Incompatible Changes 7 | -------------------------------------------------------------------------------- /spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /spec/app/models/mdm/macro_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Macro, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | end -------------------------------------------------------------------------------- /spec/app/models/mdm/api_key_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::ApiKey, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | end -------------------------------------------------------------------------------- /spec/app/models/mdm/mod_ref_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::ModRef, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | end -------------------------------------------------------------------------------- /spec/app/models/mdm/profile_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Profile, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | end -------------------------------------------------------------------------------- /spec/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery 3 | end 4 | -------------------------------------------------------------------------------- /spec/dummy/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /db/migrate/20161227212223_add_os_family_to_hosts.rb: -------------------------------------------------------------------------------- 1 | class AddOsFamilyToHosts < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :hosts, :os_family, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Dummy::Application 5 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :marshal -------------------------------------------------------------------------------- /spec/dummy/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_dummy_session' 4 | -------------------------------------------------------------------------------- /spec/factories/mdm/payloads.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_payload, :aliases => [:payload], :class => Mdm::Payload do 3 | # 4 | # Associations 5 | # 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /console_db.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: postgresql 3 | database: msf3_dev 4 | host: localhost 5 | port: 5432 6 | username: msf3 7 | password: pass123 8 | pool: 5 9 | timeout: 5 10 | -------------------------------------------------------------------------------- /spec/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | include ArelHelpers::ArelTable 4 | include ArelHelpers::JoinAssociation 5 | end 6 | -------------------------------------------------------------------------------- /spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | -------------------------------------------------------------------------------- /db/migrate/20130516204810_making_vulns_refs_a_real_ar_model.rb: -------------------------------------------------------------------------------- 1 | class MakingVulnsRefsARealArModel < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :vulns_refs, :id, :primary_key 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140905031549_add_detected_arch_to_host.rb: -------------------------------------------------------------------------------- 1 | class AddDetectedArchToHost < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :hosts, :detected_arch, :string, :null => true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190507120211_remove_payload_workspaces.rb: -------------------------------------------------------------------------------- 1 | class RemovePayloadWorkspaces < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :payloads, :workspace_id, :references 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /spec/factories/mdm/clients.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_client, :class => Mdm::Client do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20130531144949_making_host_tags_a_real_ar_model.rb: -------------------------------------------------------------------------------- 1 | class MakingHostTagsARealArModel < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :hosts_tags, :id, :primary_key 4 | end 5 | 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20130717150737_remove_pname_validation.rb: -------------------------------------------------------------------------------- 1 | class RemovePnameValidation < ActiveRecord::Migration[4.2] 2 | 3 | def change 4 | change_column :web_vulns, :pname, :text, :null => true 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20150205192745_drop_service_uniqueness_index.rb: -------------------------------------------------------------------------------- 1 | class DropServiceUniquenessIndex < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_index(:services, :host_id_and_port_and_proto) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150209195939_add_vuln_id_to_note.rb: -------------------------------------------------------------------------------- 1 | class AddVulnIdToNote < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :notes, :vuln_id, :integer 4 | add_index :notes, :vuln_id 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20250716155919_add_resource_to_mdm_vuln.rb: -------------------------------------------------------------------------------- 1 | class AddResourceToMdmVuln < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :vulns, :resource, :jsonb, null: false, default: {} 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/search/operator/port.rb: -------------------------------------------------------------------------------- 1 | # Namespace for search operator for ports. 2 | module MetasploitDataModels::Search::Operator::Port 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :List 6 | end -------------------------------------------------------------------------------- /spec/factories/mdm/vuln_refs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_vuln_ref, :class => Mdm::VulnRef do 3 | association :ref, factory: :mdm_ref 4 | association :vuln, factory: :mdm_vuln 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160415153312_remove_not_null_from_web_vuln_p_arams.rb: -------------------------------------------------------------------------------- 1 | class RemoveNotNullFromWebVulnPArams < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column_null(:web_vulns, :params, true) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250717170556_add_resource_to_services.rb: -------------------------------------------------------------------------------- 1 | class AddResourceToServices < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :services, :resource, :jsonb, null: false, default: {} 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250720082201_drop_service_uniqueness_index2.rb: -------------------------------------------------------------------------------- 1 | class DropServiceUniquenessIndex2 < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_index(:services, :host_id_and_port_and_proto) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/app/models/mdm/wmap_target_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::WmapTarget, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | it_should_behave_like 'coerces inet column type to string', :address 5 | end -------------------------------------------------------------------------------- /spec/factories/mdm/web_sites.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_web_site, :class => Mdm::WebSite do 3 | # 4 | # Associations 5 | # 6 | association :service, :factory => :mdm_service 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/app/models/mdm/wmap_request_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::WmapRequest, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | it_should_behave_like 'coerces inet column type to string', :address 5 | end -------------------------------------------------------------------------------- /spec/factories/mdm/host_details.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_host_detail, :class => Mdm::HostDetail do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/vuln_attempts.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_vuln_attempt, :class => Mdm::VulnAttempt do 3 | # 4 | # Associations 5 | # 6 | association :vuln, :factory => :mdm_vuln 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/vuln_details.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_vuln_detail, :class => Mdm::VulnDetail do 3 | # 4 | # Associations 5 | # 6 | association :vuln, :factory => :mdm_vuln 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20161004165612_add_fingerprinted_to_workspace.rb: -------------------------------------------------------------------------------- 1 | class AddFingerprintedToWorkspace < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workspaces, :import_fingerprint, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/mdm/exploit_attempts.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_exploit_attempt, :class => Mdm::ExploitAttempt do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/refs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_ref, :class => Mdm::Ref do 3 | name { generate :mdm_ref_name } 4 | end 5 | 6 | sequence :mdm_ref_name do |n| 7 | "Mdm::Ref#name #{n}" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/013_add_tasks_result.rb: -------------------------------------------------------------------------------- 1 | class AddTasksResult < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :tasks, :result, :text 4 | end 5 | 6 | def self.down 7 | remove_column :tasks, :result 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /db/migrate/016_add_host_purpose.rb: -------------------------------------------------------------------------------- 1 | class AddHostPurpose < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :hosts, :purpose, :text 4 | end 5 | 6 | def self.down 7 | remove_column :hosts, :purpose 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/ip_address/v4/segment.rb: -------------------------------------------------------------------------------- 1 | # A segment (or octet) in an IPv4 address format. 2 | module MetasploitDataModels::IPAddress::V4::Segment 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :Nmap 6 | autoload :Single 7 | end -------------------------------------------------------------------------------- /lib/metasploit_data_models/search.rb: -------------------------------------------------------------------------------- 1 | # Namespace that deals with search {Mdm} models. 2 | module MetasploitDataModels::Search 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :Operation 6 | autoload :Operator 7 | autoload :Visitor 8 | end -------------------------------------------------------------------------------- /spec/dummy/config/initializers/active_record_migrations.rb: -------------------------------------------------------------------------------- 1 | # remove Dummy's db/migrate, which doesn't exists and replace it with gem's 2 | ActiveRecord::Migrator.migrations_paths = [ 3 | MetasploitDataModels.root.join('db', 'migrate').to_path 4 | ] -------------------------------------------------------------------------------- /spec/factories/mdm/exploited_hosts.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_exploited_host, :class => Mdm::ExploitedHost do 3 | 4 | association :host, :factory => :mdm_host 5 | association :service, :factory => :mdm_service 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/mdm/fingerprints/nessus_fingerprints.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_nessus_fingerprint, :parent => :mdm_note do 3 | ntype { 'host.os.nessus_fingerprint' } 4 | data { {:os=>"Microsoft Windows XP SP3"} } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/009_add_loots_ctype.rb: -------------------------------------------------------------------------------- 1 | class AddLootsCtype < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :loots, :content_type, :string 4 | end 5 | 6 | def self.down 7 | remove_column :loots, :content_type 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /db/migrate/20111210000000_add_scope_to_hosts.rb: -------------------------------------------------------------------------------- 1 | class AddScopeToHosts < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :hosts, :scope, :text 4 | end 5 | 6 | def self.down 7 | remove_column :hosts, :scope 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20150226151459_add_module_run_fk_to_loot.rb: -------------------------------------------------------------------------------- 1 | class AddModuleRunFkToLoot < ActiveRecord::Migration[4.2] 2 | def change 3 | change_table(:loots) do |t| 4 | t.integer :module_run_id 5 | t.index :module_run_id 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /db/migrate/20110425095900_add_last_seen_to_sessions.rb: -------------------------------------------------------------------------------- 1 | class AddLastSeenToSessions < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :sessions, :last_seen, :timestamp 4 | end 5 | def self.down 6 | remove_column :sessions, :last_seen 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20110922000000_expand_notes.rb: -------------------------------------------------------------------------------- 1 | class ExpandNotes < ActiveRecord::Migration[4.2] 2 | def self.up 3 | change_column :notes, :data, :text 4 | end 5 | def self.down 6 | change_column :notes, :data, :string, :limit => 65536 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/session_events.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_session_event, :aliases => [:session_event], :class => Mdm::SessionEvent do 3 | # 4 | # Associations 5 | # 6 | association :session, :factory => :mdm_session 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/search/operator.rb: -------------------------------------------------------------------------------- 1 | # Namespace for search operators for {MetasploitDataModels}. 2 | module MetasploitDataModels::Search::Operator 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :IPAddress 6 | autoload :Multitext 7 | autoload :Port 8 | end -------------------------------------------------------------------------------- /spec/factories/mdm/fingerprints/retina_fingerprints.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_retina_fingerprint, :parent => :mdm_note do 3 | ntype { 'host.os.retina_fingerprint' } 4 | data { { :os=>"Windows Server 2003 (X64), Service Pack 2"} } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/mdm/host_tags.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_host_tag, :class => Mdm::HostTag do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | association :tag, :factory => :mdm_tag 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/020_add_user_preferences.rb: -------------------------------------------------------------------------------- 1 | class AddUserPreferences < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :users, :prefs, :string, :limit => 524288 4 | end 5 | 6 | def self.down 7 | remove_column :users, :prefs 8 | end 9 | 10 | end 11 | 12 | -------------------------------------------------------------------------------- /db/migrate/022_enlarge_event_info.rb: -------------------------------------------------------------------------------- 1 | class EnlargeEventInfo < ActiveRecord::Migration[4.2] 2 | def self.up 3 | change_column :events, :info, :text 4 | end 5 | 6 | def self.down 7 | change_column :events, :info, :string, :limit => 65535 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /db/migrate/20150219215039_add_module_run_to_session.rb: -------------------------------------------------------------------------------- 1 | class AddModuleRunToSession < ActiveRecord::Migration[4.2] 2 | def change 3 | change_table :sessions do |t| 4 | t.integer :module_run_id 5 | end 6 | add_index :sessions, :module_run_id 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/fingerprints/session_fingerprints.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_session_fingerprint, :parent => :mdm_note do 3 | ntype { 'host.os.session_fingerprint' } 4 | data { { :os => "Microsoft Windows XP SP3", :arch => 'x86' } } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/023_add_report_downloaded_at.rb: -------------------------------------------------------------------------------- 1 | class AddReportDownloadedAt < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :reports, :downloaded_at, :timestamp 4 | end 5 | 6 | def self.down 7 | remove_column :reports, :downloaded_at 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/version.rb: -------------------------------------------------------------------------------- 1 | module MetasploitDataModels 2 | # VERSION is managed by GemRelease 3 | VERSION = '6.0.12' 4 | 5 | # @return [String] 6 | # 7 | # returns the VERSION 8 | # 9 | 10 | def self.version 11 | VERSION 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/mdm/addresses.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | sequence :mdm_ipv4_address do |n| 3 | max = 255 4 | 5 | "192.168.#{(n / max).to_i}.#{n % max}" 6 | end 7 | 8 | sequence :mdm_tcp_port do |n| 9 | max = 65535 10 | n % max 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20100908001428_add_owner_to_workspaces.rb: -------------------------------------------------------------------------------- 1 | class AddOwnerToWorkspaces < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :workspaces, :owner_id, :integer 4 | end 5 | 6 | def self.down 7 | remove_column :workspaces, :owner_id 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20101008111800_add_clients_to_campaigns.rb: -------------------------------------------------------------------------------- 1 | 2 | class AddClientsToCampaigns < ActiveRecord::Migration[4.2] 3 | def self.up 4 | add_column :clients, :campaign_id, :integer 5 | end 6 | 7 | def self.down 8 | remove_column :clients, :campaign_id 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20120126110000_add_virtual_host_to_hosts.rb: -------------------------------------------------------------------------------- 1 | class AddVirtualHostToHosts < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :hosts, :virtual_host, :text 4 | end 5 | 6 | def self.down 7 | remove_column :hosts, :viritual_host 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20110527000000_add_task_id_to_reports_table.rb: -------------------------------------------------------------------------------- 1 | class AddTaskIdToReportsTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :reports, :task_id, :integer 5 | end 6 | 7 | def self.down 8 | remove_column :reports, :task_id 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20110622000000_add_settings_to_tasks_table.rb: -------------------------------------------------------------------------------- 1 | class AddSettingsToTasksTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :tasks, :settings, :binary 5 | end 6 | 7 | def self.down 8 | remove_column :tasks, :settings 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20110112154300_add_module_uuid_to_tasks.rb: -------------------------------------------------------------------------------- 1 | class AddModuleUuidToTasks < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :tasks, :module_uuid, :string, :limit => 8 4 | end 5 | 6 | def self.down 7 | remove_column :tasks, :module_uuid 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20110414180600_add_local_id_to_session_table.rb: -------------------------------------------------------------------------------- 1 | class AddLocalIdToSessionTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :sessions, :local_id, :integer 5 | end 6 | 7 | def self.down 8 | remove_column :sessions, :local_id 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20110625000001_add_macro_to_listeners_table.rb: -------------------------------------------------------------------------------- 1 | class AddMacroToListenersTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :listeners, :macro, :text 5 | end 6 | 7 | def self.down 8 | remove_column :listeners, :macro 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20130525015035_remove_campaign_id_from_clients.rb: -------------------------------------------------------------------------------- 1 | class RemoveCampaignIdFromClients < ActiveRecord::Migration[4.2] 2 | def up 3 | remove_column :clients, :campaign_id 4 | end 5 | 6 | def down 7 | remove_column :clients, :campaign_id, :integer 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20150312155312_add_module_full_name_to_match.rb: -------------------------------------------------------------------------------- 1 | class AddModuleFullNameToMatch < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :automatic_exploitation_matches, :module_fullname, :text 4 | add_index :automatic_exploitation_matches, :module_fullname 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20120411173220_rename_workspace_members.rb: -------------------------------------------------------------------------------- 1 | class RenameWorkspaceMembers < ActiveRecord::Migration[4.2] 2 | def up 3 | rename_table :project_members, :workspace_members 4 | end 5 | 6 | def down 7 | rename_table :workspace_members, :project_members 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/fingerprints/nexpose_fingerprints.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_nexpose_fingerprint, :parent => :mdm_note do 3 | ntype { 'host.os.nexpose_fingerprint' } 4 | data { {:family=>"Windows", :certainty=>"0.67", :vendor=>"Microsoft", :arch=>"x86"} } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20101203000001_expand_host_comment.rb: -------------------------------------------------------------------------------- 1 | class ExpandHostComment < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | change_column :hosts, :comments, :text 5 | end 6 | 7 | def self.down 8 | change_column :hosts, :comments, :string, :limit => 4096 9 | end 10 | end 11 | 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20110527000001_add_api_keys_table.rb: -------------------------------------------------------------------------------- 1 | class AddApiKeysTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :api_keys do |t| 4 | t.text :token 5 | t.timestamps null: false 6 | end 7 | end 8 | def self.down 9 | drop_table :api_keys 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20110727163801_expand_cred_ptype_column.rb: -------------------------------------------------------------------------------- 1 | class ExpandCredPtypeColumn < ActiveRecord::Migration[4.2] 2 | def self.up 3 | change_column :creds, :ptype, :string, :limit => 256 4 | end 5 | def self.down 6 | change_column :creds, :ptype, :string, :limit => 16 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /db/migrate/024_convert_service_info_to_text.rb: -------------------------------------------------------------------------------- 1 | class ConvertServiceInfoToText < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | change_column :services, :info, :text 5 | end 6 | 7 | def self.down 8 | change_column :services, :info, :string, :limit => 65536 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | # Add your own tasks in files placed in lib/tasks ending in .rake, 3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 4 | 5 | require File.expand_path('../config/application', __FILE__) 6 | 7 | Dummy::Application.load_tasks 8 | -------------------------------------------------------------------------------- /spec/factories/mdm/fingerprints/nmap_fingerprints.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_nmap_fingerprint, :parent => :mdm_note do 3 | ntype { 'host.os.nmap_fingerprint' } 4 | data { { :os_accuracy => 100, :os_family=> 'Windows', :os_vendor=> 'Microsoft', :os_version => 'XP' } } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/014_add_loots_fields.rb: -------------------------------------------------------------------------------- 1 | class AddLootsFields < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :loots, :name, :text 4 | add_column :loots, :info, :text 5 | end 6 | 7 | def self.down 8 | remove_column :loots, :name 9 | remove_column :loots, :info 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /db/migrate/20100920012100_add_generate_exe_column.rb: -------------------------------------------------------------------------------- 1 | class AddGenerateExeColumn < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :email_templates, :generate_exe, :boolean, :null => false, :default => false 4 | end 5 | def self.down 6 | remove_column :email_templates, :generate_exe 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20110630000002_add_name_to_nexpose_consoles_table.rb: -------------------------------------------------------------------------------- 1 | class AddNameToNexposeConsolesTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :nexpose_consoles, :name, :text 5 | end 6 | 7 | def self.down 8 | remove_column :nexpose_consoles, :name 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/ip_address.rb: -------------------------------------------------------------------------------- 1 | # Namespace for models for validating various IPv4 formats beyond those supported by the Ruby standard library's 2 | # `IPAddr`. 3 | module MetasploitDataModels::IPAddress 4 | extend ActiveSupport::Autoload 5 | 6 | autoload :CIDR 7 | autoload :Range 8 | autoload :V4 9 | end -------------------------------------------------------------------------------- /lib/metasploit_data_models/ip_address/v4/segment/nmap.rb: -------------------------------------------------------------------------------- 1 | # A segment in Nmap's IPv4 address format: either a {List comma separated list} or a {Range hyphenated range}. 2 | module MetasploitDataModels::IPAddress::V4::Segment::Nmap 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :List 6 | autoload :Range 7 | end -------------------------------------------------------------------------------- /db/migrate/20101002000000_add_query.rb: -------------------------------------------------------------------------------- 1 | class AddQuery < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :web_forms, :query, :text 4 | add_column :web_vulns, :query, :text 5 | end 6 | def self.down 7 | remove_column :web_forms, :query 8 | remove_column :web_vulns, :query 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20130522001343_create_task_creds.rb: -------------------------------------------------------------------------------- 1 | class CreateTaskCreds < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :task_creds do |t| 4 | t.references :task, :null => false 5 | t.references :cred, :null => false 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20130522032517_create_task_hosts.rb: -------------------------------------------------------------------------------- 1 | class CreateTaskHosts < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :task_hosts do |t| 4 | t.references :task, :null => false 5 | t.references :host, :null => false 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/service_links.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :mdm_service_link, :class => 'Mdm::ServiceLink' do 5 | association :parent, :factory => :mdm_service 6 | association :child, :factory => :mdm_service 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/task_creds.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :mdm_task_cred, :class => 'Mdm::TaskCred' do 5 | 6 | association :task, :factory => :mdm_task 7 | association :cred, :factory => :mdm_cred 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/task_hosts.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :mdm_task_host, :class => 'Mdm::TaskHost' do 5 | 6 | association :task, :factory => :mdm_task 7 | association :host, :factory => :mdm_host 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/task_services.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :mdm_task_service, :class => 'Mdm::TaskService' do 5 | association :task, :factory => :mdm_task 6 | association :service, :factory => :mdm_service 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/mdm/task_sessions.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :mdm_task_session, :class => 'Mdm::TaskSession' do 5 | association :task, :factory => :mdm_task 6 | association :session, :factory => :mdm_session 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20101009023300_add_campaign_attachments.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | class AddCampaignAttachments < ActiveRecord::Migration[4.2] 4 | 5 | def self.up 6 | add_column :attachments, :campaign_id, :integer 7 | end 8 | 9 | def self.down 10 | remove_column :attachments, :campaign_id 11 | end 12 | 13 | end 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/ip_address/v4.rb: -------------------------------------------------------------------------------- 1 | # Namespace for IPv4 Address format models. 2 | module MetasploitDataModels::IPAddress::V4 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :CIDR 6 | autoload :Nmap 7 | autoload :Range 8 | autoload :Segment 9 | autoload :Segmented 10 | autoload :Single 11 | end -------------------------------------------------------------------------------- /db/migrate/20130522041110_create_task_services.rb: -------------------------------------------------------------------------------- 1 | class CreateTaskServices < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :task_services do |t| 4 | t.references :task, :null => false 5 | t.references :service, :null => false 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20130604145732_create_task_sessions.rb: -------------------------------------------------------------------------------- 1 | class CreateTaskSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :task_sessions do |t| 4 | t.references :task, :null => false 5 | t.references :session, :null => false 6 | t.timestamps null: false 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/mdm/module.rb: -------------------------------------------------------------------------------- 1 | # Namespace for all models dealing with module caching. 2 | module Mdm::Module 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :Action 6 | autoload :Arch 7 | autoload :Author 8 | autoload :Detail 9 | autoload :Mixin 10 | autoload :Platform 11 | autoload :Ref 12 | autoload :Target 13 | end -------------------------------------------------------------------------------- /spec/dummy/script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/match.rb: -------------------------------------------------------------------------------- 1 | # Namespace for {MetasploitDataModels::Match::Parent#match_child dispatching} to 2 | # {MetasploitDataModels::Match::Child#match children based on if their Regexp matches}. 3 | module MetasploitDataModels::Match 4 | extend ActiveSupport::Autoload 5 | 6 | autoload :Child 7 | autoload :Parent 8 | end 9 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/search/operation.rb: -------------------------------------------------------------------------------- 1 | # Search operations ({MetasploitDataModels::Search::Operator operator}:operand) on {Mdm} and {MetasploitDataModels} 2 | # models. 3 | module MetasploitDataModels::Search::Operation 4 | extend ActiveSupport::Autoload 5 | 6 | autoload :IPAddress 7 | autoload :Port 8 | autoload :Range 9 | end -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | <%= stylesheet_link_tag "application", :media => "all" %> 6 | <%= javascript_include_tag "application" %> 7 | <%= csrf_meta_tags %> 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /db/migrate/20101206212033_add_limit_to_network_to_workspaces.rb: -------------------------------------------------------------------------------- 1 | class AddLimitToNetworkToWorkspaces < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :workspaces, :limit_to_network, :boolean, :null => false, :default => false 4 | end 5 | 6 | def self.down 7 | remove_column :workspaces, :limit_to_network 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/mdm/loots.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_loot, :aliases => [:loot], :class => Mdm::Loot do 3 | # 4 | # Associations 5 | # 6 | association :service, :factory => :mdm_service 7 | association :workspace, :factory => :mdm_workspace 8 | association :host, :factory => :mdm_host 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20130510021637_remove_campaigns.rb: -------------------------------------------------------------------------------- 1 | class RemoveCampaigns < ActiveRecord::Migration[4.2] 2 | def up 3 | drop_table :attachments 4 | drop_table :attachments_email_templates 5 | drop_table :email_addresses 6 | drop_table :email_templates 7 | drop_table :web_templates 8 | drop_table :campaigns 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /spec/factories/mdm/notes.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_note, :aliases => [:note], :class => Mdm::Note do 3 | # 4 | # Associations 5 | # 6 | association :workspace, :factory => :mdm_workspace 7 | association :host, :factory => :mdm_host 8 | association :service, :factory => :mdm_service 9 | 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | ENGINE_ROOT = File.expand_path('../..', __FILE__) 5 | ENGINE_PATH = File.expand_path('../../lib/metasploit_data_models/engine', __FILE__) 6 | 7 | require 'rails/all' 8 | require 'rails/engine/commands' -------------------------------------------------------------------------------- /spec/factories/mdm/task.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_task, :aliases => [:task], :class => 'Mdm::Task' do 3 | # 4 | # Associations 5 | # 6 | association :workspace, :factory => :mdm_workspace 7 | 8 | # 9 | # Attributes 10 | # 11 | created_at { Time.now } 12 | updated_at { Time.now } 13 | 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/015_rename_user.rb: -------------------------------------------------------------------------------- 1 | class RenameUser < ActiveRecord::Migration[4.2] 2 | def self.up 3 | remove_column :events, :user 4 | change_table :events do |t| 5 | t.string :username 6 | end 7 | end 8 | 9 | def self.down 10 | remove_column :events, :username 11 | change_table :events do |t| 12 | t.string :user 13 | end 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /db/migrate/20111203000000_inet_columns.rb: -------------------------------------------------------------------------------- 1 | class InetColumns < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | change_column :hosts, :address, 'INET using address::INET' 5 | remove_column :hosts, :address6 6 | end 7 | 8 | def self.down 9 | change_column :hosts, :address, :text 10 | add_column :hosts, :address6, :text 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131008213344_create_automatic_exploitation_runs.rb: -------------------------------------------------------------------------------- 1 | class CreateAutomaticExploitationRuns < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :automatic_exploitation_runs do |t| 4 | t.integer :workspace_id 5 | t.integer :user_id 6 | t.integer :match_set_id 7 | 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/factories/metasploit_data_models/automatic_exploitation/runs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :automatic_exploitation_run, :class => MetasploitDataModels::AutomaticExploitation::Run do 3 | association :workspace, factory: :mdm_workspace 4 | association :user, factory: :mdm_user 5 | association :match_set, factory: :automatic_exploitation_match_set 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20120625000008_add_fail_message.rb: -------------------------------------------------------------------------------- 1 | class AddFailMessage < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :vuln_attempts, :fail_detail, :text 5 | add_column :exploit_attempts, :fail_detail, :text 6 | end 7 | 8 | def self.down 9 | remove_column :vuln_attempts, :fail_detail 10 | remove_column :exploit_attempts, :fail_detail 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/search/visitor.rb: -------------------------------------------------------------------------------- 1 | # Namespace for all visitors of `Metasploit::Model::Search::Query` that help search {Mdm} models. 2 | module MetasploitDataModels::Search::Visitor 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :Attribute 6 | autoload :Includes 7 | autoload :Joins 8 | autoload :Method 9 | autoload :Relation 10 | autoload :Where 11 | end -------------------------------------------------------------------------------- /spec/lib/metasploit_data_models_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels do 2 | context 'CONSTANTS' do 3 | context 'VERSION' do 4 | subject(:version) { 5 | described_class::VERSION 6 | } 7 | 8 | it 'is Metasploit::ERD::Version.full' do 9 | expect(version).to eq(MetasploitDataModels::VERSION) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20110606000001_add_macros_table.rb: -------------------------------------------------------------------------------- 1 | class AddMacrosTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :macros do |t| 4 | t.timestamps null: false 5 | t.text :owner 6 | t.text :name 7 | t.text :description 8 | t.binary :actions 9 | t.binary :prefs 10 | end 11 | end 12 | def self.down 13 | drop_table :macros 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /db/migrate/20110717000001_add_profiles_table.rb: -------------------------------------------------------------------------------- 1 | class AddProfilesTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :profiles do |t| 4 | t.timestamps null: false 5 | t.boolean :active, :default => true 6 | t.text :name 7 | t.text :owner 8 | t.binary :settings 9 | end 10 | end 11 | def self.down 12 | drop_table :profiles 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/refs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_ref, :class => Mdm::Module::Ref do 3 | name { generate :mdm_module_ref_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | end 10 | 11 | sequence :mdm_module_ref_name do |n| 12 | "Mdm::Module::Ref#name #{n}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20120718202805_add_owner_and_payload_to_web_vulns.rb: -------------------------------------------------------------------------------- 1 | class AddOwnerAndPayloadToWebVulns < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :web_vulns, :owner, :string 5 | add_column :web_vulns, :payload, :text 6 | end 7 | 8 | def self.down 9 | remove_column :web_vulns, :owner 10 | remove_column :web_vulns, :payload 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/archs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_arch, :class => Mdm::Module::Arch do 3 | name { generate :mdm_module_arch_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | end 10 | 11 | sequence :mdm_module_arch_name do |n| 12 | "Mdm::Module::Arch#name #{n}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/factories/metasploit_data_models/automatic_exploitation/match_results.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :automatic_exploitation_match_result, :class => 'MetasploitDataModels::AutomaticExploitation::MatchResult' do 3 | association :match, factory: :automatic_exploitation_match 4 | association :run, factory: :automatic_exploitation_run 5 | state { "succeeded" } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/004_add_events_table.rb: -------------------------------------------------------------------------------- 1 | class AddEventsTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :events do |t| 4 | t.integer :workspace_id 5 | t.integer :host_id 6 | t.timestamp :created_at 7 | t.string :user 8 | t.string :name 9 | t.string :info 10 | end 11 | end 12 | def self.down 13 | drop_table :events 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /db/migrate/20150514182921_add_origin_to_mdm_vuln.rb: -------------------------------------------------------------------------------- 1 | class AddOriginToMdmVuln < ActiveRecord::Migration[4.2] 2 | def up 3 | add_column :vulns, :origin_id, :integer 4 | add_column :vulns, :origin_type, :string 5 | 6 | add_index :vulns, :origin_id 7 | end 8 | 9 | def down 10 | remove_column :vulns, :origin_id 11 | remove_column :vulns, :origin_type 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/mdm/listeners.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_listener, :aliases => [:listener], :class => Mdm::Listener do 3 | # 4 | # Associations 5 | # 6 | association :workspace, :factory => :mdm_workspace 7 | association :task, :factory => :mdm_task 8 | 9 | address { generate :mdm_ipv4_address } 10 | port { generate :mdm_tcp_port } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/factories/metasploit_data_models/automatic_exploitation/match_sets.rb: -------------------------------------------------------------------------------- 1 | # Read about factories at https://github.com/thoughtbot/factory_bot 2 | 3 | FactoryBot.define do 4 | factory :automatic_exploitation_match_set, :class => MetasploitDataModels::AutomaticExploitation::MatchSet do 5 | association :workspace, factory: :mdm_workspace 6 | association :user, factory: :mdm_user 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/metasploit_data_models/automatic_exploitation/matches.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :automatic_exploitation_match, :class => MetasploitDataModels::AutomaticExploitation::Match do 3 | association :module_detail, factory: :mdm_module_detail 4 | association :match_set, factory: :automatic_exploitation_match_set 5 | association :matchable, factory: :mdm_vuln 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20100926214000_add_template_prefs.rb: -------------------------------------------------------------------------------- 1 | class AddTemplatePrefs < ActiveRecord::Migration[4.2] 2 | def self.up 3 | remove_column :email_templates, :generate_exe 4 | add_column :email_templates, :prefs, :text 5 | add_column :web_templates, :prefs, :text 6 | end 7 | def self.down 8 | remove_column :email_templates, :prefs 9 | remove_column :web_templates, :prefs 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20131017150735_create_automatic_exploitation_match_results.rb: -------------------------------------------------------------------------------- 1 | class CreateAutomaticExploitationMatchResults < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :automatic_exploitation_match_results do |t| 4 | t.integer :match_id 5 | t.integer :run_id 6 | t.string :state, null: false 7 | 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/mixins.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_mixin, :class => Mdm::Module::Mixin do 3 | name { generate :mdm_module_mixin_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | end 10 | 11 | sequence :mdm_module_mixin_name do |n| 12 | "Mdm::Module::Mixin#name #{n}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/008_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :users do |t| 4 | t.string :username 5 | t.string :crypted_password 6 | t.string :password_salt 7 | t.string :persistence_token 8 | 9 | t.timestamps null: false 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :users 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/actions.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_action, :class => Mdm::Module::Action do 3 | name { generate :mdm_module_action_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | end 10 | 11 | sequence :mdm_module_action_name do |n| 12 | "Mdm::Module::Action#name #{n}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/factories/mdm/tags.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_tag, :class => Mdm::Tag do 3 | association :user, factory: :mdm_user 4 | desc { generate :mdm_tag_desc } 5 | name { generate :mdm_tag_name } 6 | end 7 | 8 | sequence :mdm_tag_desc do |n| 9 | "Mdm::Tag#description #{n}" 10 | end 11 | 12 | sequence :mdm_tag_name do |n| 13 | "mdm_tag_name#{n}" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/platforms.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_platform, :class => Mdm::Module::Platform do 3 | name { generate :mdm_module_platform_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | end 10 | 11 | sequence :mdm_module_platform_name do |n| 12 | "Mdm::Module::Platform#name #{n}" 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/factories/mdm/sessions.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_session, :aliases => [:session], :class => Mdm::Session do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | association :originating_module_run, :factory => :metasploit_data_models_module_run 8 | 9 | # 10 | # Attributes 11 | # 12 | opened_at { DateTime.now } 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20110415175705_add_routes_table.rb: -------------------------------------------------------------------------------- 1 | class AddRoutesTable < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :routes do |t| 5 | t.integer :session_id 6 | t.string :subnet 7 | t.string :netmask 8 | end 9 | 10 | remove_column :sessions, :routes 11 | end 12 | 13 | def self.down 14 | drop_table :routes 15 | 16 | add_column :sessions, :routes, :string 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/search/operation/port.rb: -------------------------------------------------------------------------------- 1 | # Search operation on IP port formats: either 2 | # {MetasploitDataModels::Search::Operation::Port::Number an individual port number} or 3 | # {MetasploitDataModels::Search::Operation::Port::Range a hyphenated range of port numbers}. 4 | module MetasploitDataModels::Search::Operation::Port 5 | extend ActiveSupport::Autoload 6 | 7 | autoload :Number 8 | autoload :Range 9 | end -------------------------------------------------------------------------------- /app/models/metasploit_data_models/ip_address/v4/range.rb: -------------------------------------------------------------------------------- 1 | # A range of complete IPv4 addresses, separated by a `-`. 2 | class MetasploitDataModels::IPAddress::V4::Range < Metasploit::Model::Base 3 | extend MetasploitDataModels::Match::Child 4 | 5 | include MetasploitDataModels::IPAddress::Range 6 | 7 | # 8 | # Range Extremes 9 | # 10 | 11 | extremes class_name: 'MetasploitDataModels::IPAddress::V4::Single' 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20190308134512_create_async_callbacks.rb: -------------------------------------------------------------------------------- 1 | class CreateAsyncCallbacks < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :async_callbacks do |t| 4 | t.string :uuid, :null => false 5 | t.integer :timestamp, :null => false 6 | t.string :listener_uri 7 | t.string :target_host 8 | t.string :target_port 9 | 10 | t.timestamps null: false 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/mdm/events.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_event, :aliases => [:event], :class => Mdm::Event do 3 | name { FactoryBot.generate :mdm_event_name } 4 | 5 | trait :workspace do 6 | association :workspace, :factory => :mdm_workspace 7 | end 8 | 9 | factory :mdm_workspace_event, :traits => [:workspace] 10 | end 11 | 12 | sequence :mdm_event_name do |n| 13 | "Event #{n}" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20131011184338_module_detail_on_automatic_exploitation_match.rb: -------------------------------------------------------------------------------- 1 | class ModuleDetailOnAutomaticExploitationMatch < ActiveRecord::Migration[4.2] 2 | def up 3 | rename_column :automatic_exploitation_matches, :ref_id, :module_detail_id 4 | add_column :automatic_exploitation_matches, :match_set_id, :integer 5 | end 6 | 7 | def down 8 | rename_column :automatic_exploitation_matches, :module_detail_id, :ref_id 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /cortex.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | info: 3 | title: Metasploit Data Models 4 | description: MSF database code, gemified 5 | x-cortex-git: 6 | github: 7 | alias: r7org 8 | repository: rapid7/metasploit_data_models 9 | x-cortex-tag: metasploit-data-models 10 | x-cortex-type: service 11 | x-cortex-domain-parents: 12 | - tag: metasploit 13 | x-cortex-groups: 14 | - exposure:external-ship 15 | openapi: 3.0.1 16 | servers: 17 | - url: "/" 18 | -------------------------------------------------------------------------------- /db/migrate/011_add_reports.rb: -------------------------------------------------------------------------------- 1 | class AddReports < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :reports do |t| 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.string :created_by 7 | t.string :rtype 8 | t.string :path, :limit => 1024 9 | t.text :options 10 | t.timestamps null: false 11 | end 12 | end 13 | 14 | def self.down 15 | drop_table :reports 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /db/migrate/20250718122714_create_service_links.rb: -------------------------------------------------------------------------------- 1 | class CreateServiceLinks < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :service_links do |t| 4 | t.references :parent, null: false, foreign_key: { to_table: :services } 5 | t.references :child, null: false, foreign_key: { to_table: :services } 6 | t.timestamps 7 | end 8 | add_index :service_links, [:parent_id, :child_id], unique: true 9 | end 10 | end 11 | 12 | -------------------------------------------------------------------------------- /spec/factories/mdm/creds.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_cred, :aliases => [:cred], :class => Mdm::Cred do 3 | # 4 | # Associations 5 | # 6 | association :service, :factory => :mdm_service 7 | 8 | active { true } 9 | pass{ generate :mdm_cred_pass } 10 | ptype { 'password' } 11 | user{ generate :mdm_user_username } 12 | end 13 | 14 | sequence :mdm_cred_pass do |n| 15 | "mahp455w3rd!-#{n}" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20100916151530_require_admin_flag.rb: -------------------------------------------------------------------------------- 1 | class RequireAdminFlag < ActiveRecord::Migration[4.2] 2 | 3 | # Make the admin flag required. 4 | def self.up 5 | # update any existing records 6 | Mdm::User.where(:admin => true).update_all(:admin => nil) 7 | 8 | change_column :users, :admin, :boolean, :null => false, :default => true 9 | end 10 | 11 | def self.down 12 | change_column :users, :admin, :boolean, :default => true 13 | end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20131002004641_create_automatic_exploitation_matches.rb: -------------------------------------------------------------------------------- 1 | class CreateAutomaticExploitationMatches < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :automatic_exploitation_matches do |t| 4 | t.integer :ref_id 5 | t.string :state 6 | t.integer :nexpose_data_vulnerability_definition_id 7 | 8 | t.timestamps null: false 9 | end 10 | 11 | add_index :automatic_exploitation_matches, :ref_id 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131021185657_make_match_polymorphic.rb: -------------------------------------------------------------------------------- 1 | class MakeMatchPolymorphic < ActiveRecord::Migration[4.2] 2 | def up 3 | add_column :automatic_exploitation_matches, :matchable_type, :string 4 | add_column :automatic_exploitation_matches, :matchable_id, :integer 5 | end 6 | 7 | def down 8 | remove_column :automatic_exploitation_matches, :matchable_type 9 | remove_column :automatic_exploitation_matches, :matchable_id 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20100911122000_add_report_templates.rb: -------------------------------------------------------------------------------- 1 | class AddReportTemplates < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :report_templates do |t| 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.string :created_by 7 | t.string :path, :limit => 1024 8 | t.text :name 9 | t.timestamps null: false 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :reports 15 | end 16 | 17 | end 18 | 19 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /db/migrate/010_add_alert_fields.rb: -------------------------------------------------------------------------------- 1 | class AddAlertFields < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :notes, :critical, :boolean 4 | add_column :notes, :seen, :boolean 5 | add_column :events, :critical, :boolean 6 | add_column :events, :seen, :boolean 7 | end 8 | 9 | def self.down 10 | remove_column :notes, :critical 11 | remove_column :notes, :seen 12 | remove_column :events, :critical 13 | remove_column :events, :seen 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /db/migrate/20101104135100_add_imported_creds.rb: -------------------------------------------------------------------------------- 1 | class AddImportedCreds < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :imported_creds do |t| 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.string :user, :limit => 512 7 | t.string :pass, :limit => 512 8 | t.string :ptype, :limit => 16, :default => "password" 9 | end 10 | end 11 | 12 | def self.down 13 | drop_table :imported_creds 14 | end 15 | 16 | end 17 | 18 | -------------------------------------------------------------------------------- /db/migrate/20120625000001_add_host_details.rb: -------------------------------------------------------------------------------- 1 | class AddHostDetails < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :host_details do |t| 5 | t.integer :host_id # Host table reference 6 | 7 | # Nexpose-specific fields 8 | t.integer :nx_console_id # NexposeConsole table reference 9 | t.integer :nx_device_id # Reference from the Nexpose side 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :host_details 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20130525212420_drop_table_imported_creds.rb: -------------------------------------------------------------------------------- 1 | class DropTableImportedCreds < ActiveRecord::Migration[4.2] 2 | def up 3 | drop_table :imported_creds 4 | end 5 | 6 | def down 7 | create_table :imported_creds do |t| 8 | t.integer :workspace_id, :null => false, :default => 1 9 | t.string :user, :limit => 512 10 | t.string :pass, :limit => 512 11 | t.string :ptype, :limit => 16, :default => "password" 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20131002164449_create_automatic_exploitation_match_sets.rb: -------------------------------------------------------------------------------- 1 | class CreateAutomaticExploitationMatchSets < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :automatic_exploitation_match_sets do |t| 4 | t.integer :workspace_id 5 | t.integer :user_id 6 | 7 | t.timestamps null: false 8 | end 9 | add_index :automatic_exploitation_match_sets, :user_id 10 | add_index :automatic_exploitation_match_sets, :workspace_id 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20150326183742_add_missing_ae_indices.rb: -------------------------------------------------------------------------------- 1 | class AddMissingAeIndices < ActiveRecord::Migration[4.2] 2 | def up 3 | add_index :automatic_exploitation_match_results, :match_id 4 | add_index :automatic_exploitation_match_results, :run_id 5 | 6 | add_index :automatic_exploitation_runs, :match_set_id 7 | add_index :automatic_exploitation_runs, :user_id 8 | add_index :automatic_exploitation_runs, :workspace_id 9 | end 10 | 11 | def down 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/007_add_loots.rb: -------------------------------------------------------------------------------- 1 | class AddLoots < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :loots do |t| 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.integer :host_id 7 | t.integer :service_id 8 | t.string :ltype, :limit => 512 9 | t.string :path, :limit => 1024 10 | t.text :data 11 | t.timestamps null: false 12 | end 13 | end 14 | 15 | def self.down 16 | drop_table :loots 17 | end 18 | 19 | end 20 | 21 | -------------------------------------------------------------------------------- /db/migrate/021_standardize_info_and_data.rb: -------------------------------------------------------------------------------- 1 | class StandardizeInfoAndData < ActiveRecord::Migration[4.2] 2 | def self.up 3 | # Remove the host requirement. We'll add the column back in below. 4 | remove_column :vulns, :data 5 | change_table :vulns do |t| 6 | t.string :info, :limit => 65536 7 | end 8 | end 9 | 10 | def self.down 11 | remove_column :vulns, :info 12 | change_table :notes do |t| 13 | t.string :data, :limit => 65536 14 | 15 | end 16 | end 17 | end 18 | 19 | -------------------------------------------------------------------------------- /db/migrate/20110928101300_add_mod_ref_table.rb: -------------------------------------------------------------------------------- 1 | # Probably temporary, a spot to stash module names and their associated refs 2 | # Don't count on it being populated at any given moment. 3 | class AddModRefTable < ActiveRecord::Migration[4.2] 4 | 5 | def self.up 6 | create_table :mod_refs do |t| 7 | t.string :module, :limit => 1024 8 | t.string :mtype, :limit => 128 9 | t.text :ref 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :mod_refs 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/ip_address/v4/segment/nmap/range.rb: -------------------------------------------------------------------------------- 1 | # A range of segment number composed of a {#begin} and {#end} segment number, separated by a `-`. 2 | class MetasploitDataModels::IPAddress::V4::Segment::Nmap::Range < Metasploit::Model::Base 3 | extend MetasploitDataModels::Match::Child 4 | 5 | include MetasploitDataModels::IPAddress::Range 6 | 7 | # 8 | # Range Extremes 9 | # 10 | 11 | extremes class_name: 'MetasploitDataModels::IPAddress::V4::Segment::Single' 12 | end -------------------------------------------------------------------------------- /db/migrate/20100824151500_add_exploited_table.rb: -------------------------------------------------------------------------------- 1 | class AddExploitedTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :exploited_hosts do |t| 4 | t.integer :host_id, :null => false 5 | t.integer :service_id 6 | t.string :session_uuid, :limit => 8 7 | t.string :name, :limit => 2048 8 | t.string :payload, :limit => 2048 9 | t.timestamps null: false 10 | end 11 | end 12 | def self.down 13 | drop_table :exploited_hosts 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /spec/factories/mdm/nexpose_consoles.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_nexpose_console, :aliases => [:nexpose_console], :class => Mdm::NexposeConsole do 3 | name { generate :mdm_nexpose_console_name } 4 | port { generate :mdm_tcp_port } 5 | address { generate :mdm_ipv4_address } 6 | username {'ConsoleUser'} 7 | password { 's0meH4rdP4ssW0rd' } 8 | end 9 | 10 | sequence :mdm_nexpose_console_name do |n| 11 | "Nexpose Console Name #{n}" 12 | end 13 | 14 | 15 | end 16 | -------------------------------------------------------------------------------- /spec/app/models/metasploit_data_models/search/operator/ip_address_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::Search::Operator::IPAddress, type: :model do 2 | subject(:operator) { 3 | described_class.new 4 | } 5 | 6 | context '#operate_on' do 7 | subject(:operate_on) { 8 | operator.operate_on(formatted_value) 9 | } 10 | 11 | let(:formatted_value) { 12 | nil 13 | } 14 | 15 | it { is_expected.to be_a MetasploitDataModels::Search::Operation::IPAddress } 16 | end 17 | end -------------------------------------------------------------------------------- /db/migrate/019_add_workspace_desc.rb: -------------------------------------------------------------------------------- 1 | class AddWorkspaceDesc < ActiveRecord::Migration[4.2] 2 | def self.up 3 | change_table :workspaces do |t| 4 | t.string :description, :limit => 4096 5 | end 6 | 7 | change_table :hosts do |t| 8 | t.string :comments, :limit => 4096 9 | end 10 | end 11 | 12 | def self.down 13 | change_table :workspaces do |t| 14 | t.remove :description 15 | end 16 | 17 | change_table :hosts do |t| 18 | t.remove :comments 19 | end 20 | end 21 | 22 | end 23 | 24 | -------------------------------------------------------------------------------- /db/migrate/025_add_user_admin.rb: -------------------------------------------------------------------------------- 1 | class AddUserAdmin < ActiveRecord::Migration[4.2] 2 | 3 | # Add user admin flag and project member list. 4 | def self.up 5 | add_column :users, :admin, :boolean, :default => true 6 | 7 | create_table :project_members, :id => false do |t| 8 | t.integer :workspace_id, :null => false 9 | t.integer :user_id, :null => false 10 | end 11 | end 12 | 13 | def self.down 14 | remove_column :users, :admin 15 | 16 | drop_table :project_members 17 | end 18 | end 19 | 20 | -------------------------------------------------------------------------------- /db/migrate/20101007000000_add_vuln_info.rb: -------------------------------------------------------------------------------- 1 | class AddVulnInfo < ActiveRecord::Migration[4.2] 2 | def self.up 3 | add_column :web_vulns, :category, :text 4 | add_column :web_vulns, :confidence, :text 5 | add_column :web_vulns, :description, :text 6 | add_column :web_vulns, :blame, :text 7 | end 8 | def self.down 9 | remove_column :web_forms, :category 10 | remove_column :web_vulns, :confidence 11 | remove_column :web_vulns, :description 12 | remove_column :web_vulns, :blame 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /db/migrate/20110624000001_add_listeners_table.rb: -------------------------------------------------------------------------------- 1 | class AddListenersTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :listeners do |t| 4 | t.timestamps null: false 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.integer :task_id 7 | t.boolean :enabled, :default => true 8 | t.text :owner 9 | t.text :payload 10 | t.text :address 11 | t.integer :port 12 | t.binary :options 13 | end 14 | end 15 | def self.down 16 | drop_table :listeners 17 | end 18 | end 19 | 20 | -------------------------------------------------------------------------------- /spec/support/shared/contexts/rex/text.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_context 'Rex::Text' do 2 | before(:example) do 3 | rex_text = Module.new do 4 | def self.ascii_safe_hex(str, whitespace=false) 5 | if whitespace 6 | str.gsub(/([\x00-\x20\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] } 7 | else 8 | str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]} 9 | end 10 | end 11 | end 12 | 13 | stub_const('Rex::Text', rex_text) 14 | end 15 | end -------------------------------------------------------------------------------- /spec/factories/mdm/module/targets.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_target, :class => Mdm::Module::Target do 3 | index { generate :mdm_module_target_index } 4 | name { generate :mdm_module_target_name } 5 | 6 | # 7 | # Associations 8 | # 9 | association :detail, :factory => :mdm_module_detail 10 | end 11 | 12 | sequence :mdm_module_target_index do |n| 13 | n 14 | end 15 | 16 | sequence :mdm_module_target_name do |n| 17 | "Mdm::Module::Target#name #{n}" 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20120625000002_expand_details.rb: -------------------------------------------------------------------------------- 1 | class ExpandDetails < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :vuln_details, :nx_vuln_status, :text 5 | add_column :vuln_details, :nx_proof_key, :text 6 | add_column :vuln_details, :src, :string 7 | add_column :host_details, :src, :string 8 | end 9 | 10 | def self.down 11 | remove_column :vuln_details, :nx_vuln_status 12 | remove_column :vuln_details, :nx_proof_key 13 | remove_column :vuln_details, :src 14 | remove_column :host_details, :src 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/factories/mdm/vulns.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_vuln, :class => Mdm::Vuln do 3 | name { generate :mdm_vuln_name } 4 | 5 | trait :host do 6 | association :host, :factory => :mdm_host 7 | end 8 | 9 | trait :service do 10 | association :service, :factory => :mdm_service 11 | end 12 | 13 | factory :mdm_host_vuln, :traits => [:host] 14 | factory :mdm_service_vuln, :traits => [:service] 15 | end 16 | 17 | sequence :mdm_vuln_name do |n| 18 | "Mdm::Vuln#name #{n}" 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/support/shared/examples/coerces_inet_column_type_to_string.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'coerces inet column type to string' do |column| 2 | raise ArgumentError, 'must pass the column name' unless column 3 | 4 | context 'with an inet column' do 5 | let(:address) { '10.0.0.1' } 6 | 7 | before(:example) do 8 | subject.update_attribute column, address 9 | end 10 | 11 | it 'should cast the column as a string when fetching from the database' do 12 | expect(subject.send(column)).to eq(address) 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /db/migrate/20120625000005_add_vuln_and_host_counter_caches.rb: -------------------------------------------------------------------------------- 1 | class AddVulnAndHostCounterCaches < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :hosts, :host_detail_count, :integer, :default => 0 5 | add_column :vulns, :vuln_detail_count, :integer, :default => 0 6 | add_column :vulns, :vuln_attempt_count, :integer, :default => 0 7 | end 8 | 9 | def self.down 10 | remove_column :hosts, :host_detail_count 11 | remove_column :vulns, :vuln_detail_count 12 | remove_column :vulns, :vuln_attempt_count 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/026_add_creds_table.rb: -------------------------------------------------------------------------------- 1 | class AddCredsTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :creds do |t| 4 | t.integer :service_id, :null => false 5 | t.timestamps null: false 6 | t.string :user, :limit => 2048 7 | t.string :pass, :limit => 4096 8 | t.boolean :active, :default => true 9 | t.string :proof, :limit => 4096 10 | t.string :ptype, :limit => 16 11 | t.integer :source_id 12 | t.string :source_type 13 | end 14 | end 15 | def self.down 16 | drop_table :creds 17 | end 18 | end 19 | 20 | -------------------------------------------------------------------------------- /db/migrate/20130430151353_change_required_columns_to_null_false_in_hosts.rb: -------------------------------------------------------------------------------- 1 | # Changes all the {COLUMNS} in the hosts table that are required for {Mdm::Host}, but were previously `:null => true`. 2 | class ChangeRequiredColumnsToNullFalseInHosts < MetasploitDataModels::ChangeRequiredColumnsToNullFalse 3 | # Columns that were previously `:null => true`, but are actually required to be non-null, so should be 4 | # `:null => false` 5 | COLUMNS = [ 6 | :address, 7 | :workspace_id 8 | ] 9 | # Table in which {COLUMNS} are. 10 | TABLE_NAME = :hosts 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20150112203945_remove_duplicate_services.rb: -------------------------------------------------------------------------------- 1 | class RemoveDuplicateServices < ActiveRecord::Migration[4.2] 2 | def change 3 | select_mgr = Mdm::Service.arel_table.project( 4 | Mdm::Service[:host_id], 5 | Mdm::Service[:proto], 6 | Mdm::Service[:port].count 7 | ).group( 8 | 'host_id', 9 | 'port', 10 | 'proto' 11 | ).having(Mdm::Service[:port].count.gt(1)) 12 | 13 | Mdm::Service.find_by_sql(select_mgr).each(&:destroy) 14 | 15 | add_index :services, [:host_id, :port, :proto], unique: true 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20150212214222_remove_duplicate_services2.rb: -------------------------------------------------------------------------------- 1 | class RemoveDuplicateServices2 < ActiveRecord::Migration[4.2] 2 | def change 3 | select_mgr = Mdm::Service.arel_table.project( 4 | Mdm::Service[:host_id], 5 | Mdm::Service[:proto], 6 | Mdm::Service[:port].count 7 | ).group( 8 | 'host_id', 9 | 'port', 10 | 'proto' 11 | ).having(Mdm::Service[:port].count.gt(1)) 12 | 13 | Mdm::Service.find_by_sql(select_mgr).each(&:destroy) 14 | 15 | add_index :services, [:host_id, :port, :proto], unique: true 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20110630000001_add_nexpose_consoles_table.rb: -------------------------------------------------------------------------------- 1 | class AddNexposeConsolesTable < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :nexpose_consoles do |t| 4 | t.timestamps null: false 5 | t.boolean :enabled, :default => true 6 | t.text :owner 7 | t.text :address 8 | t.integer :port, :default => 3780 9 | t.text :username 10 | t.text :password 11 | t.text :status 12 | t.text :version 13 | t.text :cert 14 | t.binary :cached_sites 15 | end 16 | end 17 | def self.down 18 | drop_table :nexpose_consoles 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /app/models/mdm/vuln_ref.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Vuln} and {Mdm::Ref}. 2 | class Mdm::VulnRef < ApplicationRecord 3 | self.table_name = 'vulns_refs' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # {Mdm::Ref Reference} to {#vuln}. 10 | belongs_to :ref, 11 | class_name: 'Mdm::Ref', 12 | inverse_of: :vulns_refs 13 | 14 | # {Mdm::Vuln Vulnerability} imported or discovered by metasploit. 15 | belongs_to :vuln, 16 | class_name: 'Mdm::Vuln', 17 | inverse_of: :vulns_refs 18 | 19 | Metasploit::Concern.run(self) 20 | end 21 | 22 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/ip_address/v4/nmap.rb: -------------------------------------------------------------------------------- 1 | # Nmap's octet range format composed of segments of comma separated list of segment numbers and segment number ranges. 2 | # 3 | # @example Nmap octect range format 4 | # # equivalent to ['1.5.6.7', '3.5.6.7', '4.5.6.7'] 5 | # '1,3-4.5.6.7' 6 | # 7 | # @see http://nmap.org/book/man-target-specification.html 8 | class MetasploitDataModels::IPAddress::V4::Nmap < MetasploitDataModels::IPAddress::V4::Segmented 9 | # 10 | # Segments 11 | # 12 | 13 | segment class_name: 'MetasploitDataModels::IPAddress::V4::Segment::Nmap::List' 14 | end -------------------------------------------------------------------------------- /db/migrate/003_move_notes.rb: -------------------------------------------------------------------------------- 1 | class MoveNotes < ActiveRecord::Migration[4.2] 2 | def self.up 3 | # Remove the host requirement. We'll add the column back in below. 4 | remove_column :notes, :host_id 5 | change_table :notes do |t| 6 | t.integer :workspace_id, :null => false, :default => 1 7 | t.integer :service_id 8 | t.integer :host_id 9 | end 10 | end 11 | 12 | def self.down 13 | remove_column :notes, :workspace_id 14 | remove_column :notes, :service_id 15 | change_table :notes do |t| 16 | t.integer :host_id, :null => false 17 | end 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /db/migrate/012_add_tasks.rb: -------------------------------------------------------------------------------- 1 | class AddTasks < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :tasks do |t| 5 | t.integer :workspace_id, :null => false, :default => 1 6 | t.string :created_by 7 | t.string :module 8 | t.datetime :completed_at 9 | t.string :path, :limit => 1024 10 | t.string :info 11 | t.string :description 12 | t.integer :progress 13 | t.text :options 14 | t.text :error 15 | t.timestamps null: false 16 | end 17 | end 18 | 19 | def self.down 20 | drop_table :tasks 21 | end 22 | 23 | end 24 | 25 | -------------------------------------------------------------------------------- /db/migrate/20180904120211_create_payloads.rb: -------------------------------------------------------------------------------- 1 | class CreatePayloads < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :payloads do |t| 4 | t.string :name 5 | t.string :uuid 6 | t.integer :uuid_mask 7 | t.integer :timestamp 8 | t.string :arch 9 | t.string :platform 10 | t.string :urls 11 | t.string :description 12 | t.references :workspace 13 | t.string :raw_payload 14 | t.string :raw_payload_hash 15 | t.string :build_status 16 | t.string :build_opts 17 | 18 | t.timestamps null: false 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails gems 3 | # installed from the root of your application. 4 | 5 | ENGINE_ROOT = File.expand_path('..', __dir__) 6 | ENGINE_PATH = File.expand_path('../lib/metasploit_data_models/engine', __dir__) 7 | APP_PATH = File.expand_path('../test/dummy/config/application', __dir__) 8 | 9 | # Set up gems listed in the Gemfile. 10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 11 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 12 | 13 | require 'rails/all' 14 | require 'rails/engine/commands' 15 | -------------------------------------------------------------------------------- /spec/factories/mdm/module/authors.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_module_author, :class => Mdm::Module::Author do 3 | name { generate :mdm_module_author_name } 4 | 5 | # 6 | # Associations 7 | # 8 | association :detail, :factory => :mdm_module_detail 9 | 10 | factory :full_mdm_module_author do 11 | email { generate :mdm_module_author_name } 12 | end 13 | end 14 | 15 | sequence :mdm_module_author_name do |n| 16 | "Mdm::Module::Author#name #{n}" 17 | end 18 | 19 | sequence :mdm_module_author_email do |n| 20 | "Mdm::Module::Author#email #{n}" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/factories/mdm/workspaces.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_workspace, :class => Mdm::Workspace do 3 | # 4 | # Associations 5 | # 6 | association :owner, :factory => :mdm_user 7 | 8 | # 9 | # Attributes 10 | # 11 | boundary { generate :mdm_ipv4_address } 12 | description { generate :mdm_workspace_description } 13 | name { generate :mdm_workspace_name } 14 | end 15 | 16 | sequence :mdm_workspace_description do |n| 17 | "Mdm::Workspace description #{n}" 18 | end 19 | 20 | sequence :mdm_workspace_name do |n| 21 | "Mdm::Workspace Name #{n}" 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /db/migrate/20250721114306_remove_duplicate_services3.rb: -------------------------------------------------------------------------------- 1 | class RemoveDuplicateServices3 < ActiveRecord::Migration[7.0] 2 | def change 3 | select_mgr = Mdm::Service.arel_table.project( 4 | Mdm::Service[:host_id], 5 | Mdm::Service[:proto], 6 | Mdm::Service[:port].count 7 | ).group( 8 | 'host_id', 9 | 'port', 10 | 'proto' 11 | ).having(Mdm::Service[:port].count.gt(1)) 12 | 13 | Mdm::Service.find_by_sql(select_mgr).each(&:destroy) 14 | 15 | add_index :services, [:host_id, :port, :proto, :name, :resource], unique: true, name: 'index_services_on_5_columns' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/visitor/method.rb: -------------------------------------------------------------------------------- 1 | # Extracts which AREL method to use as a translation for `Metasploit::Model::Search::Group::Base` subclasses. 2 | class MetasploitDataModels::Search::Visitor::Method 3 | include Metasploit::Model::Visitation::Visit 4 | 5 | visit 'Metasploit::Model::Search::Group::Intersection', 6 | 'Metasploit::Model::Search::Operation::Group::Intersection' do 7 | :and 8 | end 9 | 10 | visit 'Metasploit::Model::Search::Group::Union', 11 | 'Metasploit::Model::Search::Operation::Group::Union' do 12 | :or 13 | end 14 | 15 | Metasploit::Concern.run(self) 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20110812000001_prune_indexes.rb: -------------------------------------------------------------------------------- 1 | class PruneIndexes < ActiveRecord::Migration[4.2] 2 | def self.up 3 | 4 | if indexes(:hosts).map{|x| x.columns }.flatten.include?("comments") 5 | remove_index :hosts, :comments 6 | end 7 | 8 | if indexes(:services).map{|x| x.columns }.flatten.include?("info") 9 | remove_index :services, :info 10 | end 11 | 12 | if indexes(:vulns).map{|x| x.columns }.flatten.include?("info") 13 | remove_index :vulns, :info 14 | end 15 | end 16 | 17 | def self.down 18 | add_index :hosts, :comments 19 | add_index :services, :info 20 | add_index :vulns, :info 21 | end 22 | end 23 | 24 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require_tree . 13 | */ 14 | -------------------------------------------------------------------------------- /config/initializers/ipaddr.rb: -------------------------------------------------------------------------------- 1 | module IPAddrExtensions 2 | extend ActiveSupport::Concern 3 | 4 | def coerce(other) 5 | begin 6 | case other 7 | when IPAddr 8 | other 9 | when String 10 | self.class.new(other) 11 | else 12 | self.class.new(other, @family) 13 | end 14 | rescue ArgumentError => e 15 | OpenStruct.new(family: false, to_i: false) 16 | end 17 | end 18 | 19 | def include?(other) 20 | begin 21 | super(other) 22 | rescue IPAddr::InvalidAddressError 23 | false 24 | end 25 | end 26 | 27 | end 28 | 29 | IPAddr.send(:prepend, IPAddrExtensions) 30 | -------------------------------------------------------------------------------- /app/models/mdm/module/arch.rb: -------------------------------------------------------------------------------- 1 | # A supported architecture for a given {Mdm::Module::Detail Metasploit Module} 2 | class Mdm::Module::Arch < ApplicationRecord 3 | self.table_name = 'module_archs' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 10 | 11 | # 12 | # Attributes 13 | # 14 | 15 | # @!attribute name 16 | # The architecture abbreviation, such as `'x86'` 17 | # 18 | # @return [String] 19 | 20 | # 21 | # Validations 22 | # 23 | 24 | validates :detail, :presence => true 25 | validates :name, :presence => true 26 | 27 | Metasploit::Concern.run(self) 28 | end 29 | -------------------------------------------------------------------------------- /db/migrate/018_add_workspace_user_info.rb: -------------------------------------------------------------------------------- 1 | class AddWorkspaceUserInfo < ActiveRecord::Migration[4.2] 2 | def self.up 3 | change_table :workspaces do |t| 4 | t.string :boundary, :limit => 4096 5 | end 6 | 7 | change_table :users do |t| 8 | t.string :fullname 9 | t.string :email 10 | t.string :phone 11 | t.string :company 12 | end 13 | end 14 | 15 | def self.down 16 | change_table :workspaces do |t| 17 | t.remove :boundary 18 | end 19 | 20 | change_table :users do |t| 21 | t.remove :fullname 22 | t.remove :email 23 | t.remove :phone 24 | t.remove :company 25 | end 26 | end 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /spec/factories/mdm/users.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_user, :class => Mdm::User do 3 | admin { true } 4 | company { "Interplanetary Teleportation, LTD" } 5 | email { "rwillingham@itl.com" } 6 | fullname { generate :mdm_user_fullname } 7 | phone { "5123334444" } 8 | username { generate :mdm_user_username } 9 | end 10 | 11 | factory :non_admin_mdm_user, :parent => :mdm_user do 12 | admin { false } 13 | end 14 | 15 | sequence :mdm_user_fullname do |n| 16 | "Mdm User Fullname the #{n.ordinalize}" 17 | end 18 | 19 | sequence :mdm_user_username do |n| 20 | "mdm_user_username#{n}" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/support/shared/examples/mdm/module/detail/does_not_support_stance_with_mtype.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'Mdm::Module::Detail does not support stance with mtype' do |mtype| 2 | context "with #{mtype.inspect}" do 3 | # define as a let so that lets from outer context can access option to set detail. 4 | let(:mtype) do 5 | mtype 6 | end 7 | 8 | it 'should return false for supports_stance?' do 9 | expect(detail.supports_stance?).to eq(false) 10 | end 11 | 12 | context 'with nil stance' do 13 | let(:stance) do 14 | nil 15 | end 16 | 17 | it { is_expected.to be_valid } 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /db/migrate/20111011110000_add_display_name_to_reports_table.rb: -------------------------------------------------------------------------------- 1 | class AddDisplayNameToReportsTable < ActiveRecord::Migration[4.2] 2 | 3 | class Report < ApplicationRecord 4 | end 5 | 6 | def self.up 7 | 8 | add_column :reports, :name, :string, :limit => 63 9 | 10 | # Migrate to have a default name. 11 | 12 | Report.all.each do |report| 13 | rtype = report.rtype.to_s =~ /^([A-Z0-9]+)\x2d/i ? $1 : "AUDIT" 14 | default_name = rtype[0,57].downcase.capitalize + "-" + report.id.to_s[0,5] 15 | report.name = default_name 16 | report.save 17 | end 18 | end 19 | 20 | def self.down 21 | remove_column :reports, :name 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/ip_address/v4/cidr.rb: -------------------------------------------------------------------------------- 1 | # An IPv4 CIDR (Classless InterDomain Routing) block composed of a 2 | # {MetasploitDataModels::IPAddress::V4::Single IPv4} {MetasploitDataModels::IPAddress::CIDR#address address} and 3 | # {MetasploitDataModels::IPAddress::CIDR#prefix_length prefix_length} written in the form `'a.b.c.d/prefix_length'`. 4 | # 5 | # @see https://en.wikipedia.org/wiki/Cidr#IPv6_CIDR_blocks 6 | class MetasploitDataModels::IPAddress::V4::CIDR < Metasploit::Model::Base 7 | include MetasploitDataModels::IPAddress::CIDR 8 | 9 | # 10 | # CIDR 11 | # 12 | 13 | cidr address_class: MetasploitDataModels::IPAddress::V4::Single 14 | end 15 | -------------------------------------------------------------------------------- /app/models/mdm/mod_ref.rb: -------------------------------------------------------------------------------- 1 | # Joins a {Mdm::Module::Detail} and {Mdm::Ref} indirectly through the {Mdm::Module::Detail#refname} matching {#module}, 2 | # {Mdm::Module::Detail#mtype} matching {#mtype}, and {Mdm::Ref#name} matching {#ref}. 3 | class Mdm::ModRef < ApplicationRecord 4 | # 5 | # Attributes 6 | # 7 | 8 | # @!attribute module 9 | # An {Mdm::Module::Detail#refname}. 10 | # 11 | # @return [String] 12 | 13 | # @!attribute mtype 14 | # An {Mdm::Module::Detail#mtype}. 15 | # 16 | # @return [String] 17 | 18 | # @!attribute ref 19 | # An {Mdm::Ref#name}. 20 | # 21 | # @return [String] 22 | 23 | Metasploit::Concern.run(self) 24 | end 25 | -------------------------------------------------------------------------------- /db/migrate/20111204000000_more_inet_columns.rb: -------------------------------------------------------------------------------- 1 | class MoreInetColumns < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | change_column :wmap_requests, :address, 'INET using address::INET' 5 | remove_column :wmap_requests, :address6 6 | change_column :wmap_targets, :address, 'INET using address::INET' 7 | remove_column :wmap_targets, :address6 8 | end 9 | 10 | def self.down 11 | change_column :wmap_requests, :address, :string, :limit => 16 12 | add_column :wmap_requests, :address6, :string, :limit => 255 13 | change_column :wmap_targets, :address, :string, :limit => 16 14 | add_column :wmap_targets, :address6, :string, :limit => 255 15 | end 16 | 17 | end 18 | -------------------------------------------------------------------------------- /app/models/mdm/route.rb: -------------------------------------------------------------------------------- 1 | # Network route that goes through a {#session} to allow accessing IPs on the remote end of the session. 2 | class Mdm::Route < ApplicationRecord 3 | 4 | # 5 | # Associations 6 | # 7 | 8 | # The session over which this route traverses. 9 | belongs_to :session, 10 | class_name: 'Mdm::Session', 11 | inverse_of: :routes 12 | 13 | # 14 | # Attributes 15 | # 16 | 17 | # @!attribute netmask 18 | # The netmask for this route. 19 | # 20 | # @return [String] 21 | 22 | # @!attribute subnet 23 | # The subnet for this route. 24 | # 25 | # @return [String] 26 | 27 | Metasploit::Concern.run(self) 28 | end 29 | -------------------------------------------------------------------------------- /db/migrate/20150219173821_create_module_runs.rb: -------------------------------------------------------------------------------- 1 | class CreateModuleRuns < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :module_runs do |t| 4 | t.datetime :attempted_at 5 | t.text :fail_detail 6 | t.string :fail_reason 7 | t.text :module_fullname 8 | t.integer :port 9 | t.string :proto 10 | t.integer :session_id 11 | t.string :status 12 | t.integer :trackable_id 13 | t.string :trackable_type 14 | t.integer :user_id 15 | t.string :username 16 | 17 | t.timestamps null: false 18 | end 19 | 20 | add_index :module_runs, :session_id 21 | add_index :module_runs, :user_id 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/models/mdm/module/platform.rb: -------------------------------------------------------------------------------- 1 | # {#name Platform} on which the {#detail Metasploit Module} can run. 2 | class Mdm::Module::Platform < ApplicationRecord 3 | self.table_name = 'module_platforms' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # The Metasploit Module that can run on the {#name named} platform. 10 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 11 | 12 | # 13 | # Attributes 14 | # 15 | 16 | # @!attribute name 17 | # The name of the platform. 18 | # 19 | # @return [String] 20 | 21 | # 22 | # Validations 23 | # 24 | 25 | validates :detail, :presence => true 26 | validates :name, :presence => true 27 | 28 | Metasploit::Concern.run(self) 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20130228214900_change_required_columns_to_null_false_in_web_vulns.rb: -------------------------------------------------------------------------------- 1 | # Changes all the {COLUMNS} in the web_vulns table that are required for {Mdm::WebVuln}, but were previously 2 | # :null => true 3 | class ChangeRequiredColumnsToNullFalseInWebVulns < MetasploitDataModels::ChangeRequiredColumnsToNullFalse 4 | # Columns that were previously :null => true, but are actually required to be non-null, so should be 5 | # :null => false 6 | COLUMNS = [ 7 | :category, 8 | :confidence, 9 | :method, 10 | :name, 11 | :params, 12 | :path, 13 | :pname, 14 | :proof, 15 | :risk 16 | ] 17 | # Table in which {COLUMNS} are. 18 | TABLE_NAME = :web_vulns 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20110204112800_add_host_tags.rb: -------------------------------------------------------------------------------- 1 | class AddHostTags < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | 5 | create_table :tags do |t| 6 | t.integer :user_id 7 | t.string :name, :limit => 1024 8 | t.text :desc 9 | t.boolean :report_summary, :null => false, :default => false 10 | t.boolean :report_detail, :null => false, :default => false 11 | t.boolean :critical, :null => false, :default => false 12 | t.timestamps null: false 13 | end 14 | 15 | create_table :hosts_tags, :id => false do |t| 16 | t.integer :host_id 17 | t.integer :tag_id 18 | end 19 | 20 | end 21 | 22 | def self.down 23 | drop_table :hosts_tags 24 | drop_table :tags 25 | end 26 | 27 | end 28 | 29 | -------------------------------------------------------------------------------- /db/migrate/20110517160800_rename_and_prune_nessus_vulns.rb: -------------------------------------------------------------------------------- 1 | class RenameAndPruneNessusVulns < ActiveRecord::Migration[4.2] 2 | 3 | class Vuln < ApplicationRecord 4 | end 5 | 6 | # No table changes, just vuln renaming to drop the NSS id 7 | # from those vulns that have it and a descriptive name. 8 | def self.up 9 | Vuln.all.each do |v| 10 | if v.name =~ /^NSS-0?\s*$/ 11 | v.delete 12 | next 13 | end 14 | next unless(v.name =~ /^NSS-[0-9]+\s(.+)/) 15 | new_name = $1 16 | next if(new_name.nil? || new_name.strip.empty?) 17 | v.name = new_name 18 | v.save! 19 | end 20 | end 21 | 22 | def self.down 23 | say "Cannot un-rename and un-prune NSS vulns for migration 20110517160800." 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /spec/app/models/metasploit_data_models/ip_address/v4/segment/segmented_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::IPAddress::V4::Segmented, type: :model do 2 | context 'CONSTANTS' do 3 | context 'SEGMENT_COUNT' do 4 | subject(:segment_count) { 5 | described_class::SEGMENT_COUNT 6 | } 7 | 8 | it { is_expected.to eq(4) } 9 | end 10 | 11 | context 'SEPARATOR' do 12 | subject(:separator) { 13 | described_class::SEPARATOR 14 | } 15 | 16 | it { is_expected.to eq('.') } 17 | end 18 | end 19 | 20 | context 'segment_count' do 21 | subject(:segment_count) { 22 | described_class.segment_count 23 | } 24 | 25 | it { is_expected.to eq(4) } 26 | end 27 | end -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 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 new rvm version and gemset files 12 | .ruby-gemset 13 | .ruby-version 14 | # Don't check in rvmrc since this is a gem 15 | .rvmrc 16 | # YARD database 17 | .yardoc 18 | # coverage report directory for simplecov/Rubymine 19 | coverage 20 | # generated yardocs 21 | doc 22 | # Installed gem versions. Not stored for the same reasons as .rvmrc 23 | Gemfile.lock 24 | # Packaging directory for builds 25 | pkg/* 26 | # Database configuration (with passwords) for specs 27 | spec/dummy/config/database.yml 28 | # Secrets 29 | spec/dummy/tmp/* 30 | -------------------------------------------------------------------------------- /spec/dummy/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // the compiled file. 9 | // 10 | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD 11 | // GO AFTER THE REQUIRES BELOW. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require_tree . 16 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/visitor/attribute.rb: -------------------------------------------------------------------------------- 1 | # Extracts the `Arel::Attribute` objects from `Metasploit::Model::Search::Operator::Base` subclasses. 2 | class MetasploitDataModels::Search::Visitor::Attribute 3 | include Metasploit::Model::Visitation::Visit 4 | 5 | visit 'Metasploit::Model::Search::Operator::Association' do |operator| 6 | visit operator.source_operator 7 | end 8 | 9 | visit 'Metasploit::Model::Search::Operator::Attribute', 10 | 'MetasploitDataModels::Search::Operator::IPAddress', 11 | 'MetasploitDataModels::Search::Operator::Port::List' do |operator| 12 | table = operator.klass.arel_table 13 | table[operator.attribute] 14 | end 15 | 16 | Metasploit::Concern.run(self) 17 | end 18 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /spec/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /app/models/mdm/module/mixin.rb: -------------------------------------------------------------------------------- 1 | # @deprecated Never populated by metasploit-framework. 2 | # 3 | # Module mixed into a {#detail Metasploit Module}. 4 | class Mdm::Module::Mixin < ApplicationRecord 5 | self.table_name = 'module_mixins' 6 | 7 | # 8 | # Associations 9 | # 10 | 11 | # Metasploit Module the {#name named} `Module` was mixed in. 12 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 13 | 14 | # 15 | # Attributes 16 | # 17 | 18 | # @!attribute name 19 | # The `Module#name` of the mixed in `Module`. 20 | # 21 | # @return [String] 22 | 23 | # 24 | # Validation 25 | # 26 | 27 | validates :detail, :presence => true 28 | validates :name, :presence => true 29 | 30 | Metasploit::Concern.run(self) 31 | end 32 | -------------------------------------------------------------------------------- /db/migrate/20120601152442_add_counter_caches_to_hosts.rb: -------------------------------------------------------------------------------- 1 | class AddCounterCachesToHosts < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :hosts, :note_count, :integer, :default => 0 5 | add_column :hosts, :vuln_count, :integer, :default => 0 6 | add_column :hosts, :service_count, :integer, :default => 0 7 | 8 | Mdm::Host.reset_column_information 9 | Mdm::Host.all.each do |h| 10 | Mdm::Host.reset_counters h.id, :notes 11 | Mdm::Host.reset_counters h.id, :vulns 12 | Mdm::Host.reset_counters h.id, :services 13 | end 14 | end 15 | 16 | def self.down 17 | remove_column :hosts, :note_count 18 | remove_column :hosts, :vuln_count 19 | remove_column :hosts, :service_count 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/dummy/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

We're sorry, but something went wrong.

23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/operation/port/number.rb: -------------------------------------------------------------------------------- 1 | # Search operation on an attribute that holds a port number and is being searched with a single Integer port number. 2 | class MetasploitDataModels::Search::Operation::Port::Number < Metasploit::Model::Search::Operation::Integer 3 | # 4 | # CONSTANTS 5 | # 6 | 7 | # The number of bits in a port number 8 | BITS = 16 9 | # The maximum port number 10 | MAXIMUM = (1 << BITS) - 1 11 | # The minimum port number 12 | MINIMUM = 0 13 | 14 | # The range of valid port numbers from {MINIMUM} to {MAXIMUM}, inclusive. 15 | RANGE = (MINIMUM..MAXIMUM) 16 | 17 | # 18 | # Validations 19 | # 20 | 21 | validates :value, 22 | inclusion: { 23 | in: RANGE 24 | } 25 | end -------------------------------------------------------------------------------- /app/models/mdm/module/author.rb: -------------------------------------------------------------------------------- 1 | # The {#email} and {#name} of an author of a {#detail Metasploit Module}. 2 | class Mdm::Module::Author < ApplicationRecord 3 | self.table_name = 'module_authors' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # The authored Metasploit Module. 10 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 11 | 12 | # 13 | # Attributes 14 | # 15 | 16 | # @!attribute email 17 | # The email address of the author. 18 | # 19 | # @return [String] 20 | 21 | # @!attribute name 22 | # The name of the author. 23 | # 24 | # @return [String] 25 | 26 | # 27 | # Validations 28 | # 29 | 30 | validates :detail, :presence => true 31 | validates :name, :presence => true 32 | 33 | Metasploit::Concern.run(self) 34 | end 35 | -------------------------------------------------------------------------------- /db/migrate/20150421211719_rename_automatic_exploitation_index.rb: -------------------------------------------------------------------------------- 1 | class RenameAutomaticExploitationIndex < ActiveRecord::Migration[4.2] 2 | def up 3 | if index_name_exists? :automatic_exploitation_matches, :index_automatic_exploitation_matches_on_ref_id 4 | rename_index :automatic_exploitation_matches, 5 | :index_automatic_exploitation_matches_on_ref_id, 6 | :index_automatic_exploitation_matches_on_module_detail_id 7 | end 8 | end 9 | def down 10 | if index_name_exists? :automatic_exploitation_matches, :index_automatic_exploitation_matches_on_module_detail_id 11 | rename_index :automatic_exploitation_matches, 12 | :index_automatic_exploitation_matches_on_module_detail_id, 13 | :index_automatic_exploitation_matches_on_ref_id 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/dummy/config/database.yml.example: -------------------------------------------------------------------------------- 1 | # Please only use postgresql bound to a TCP port. 2 | development: &pgsql 3 | adapter: postgresql 4 | database: metasploit_data_models_development 5 | username: metasploit_data_models_development 6 | password: __________________________________ 7 | host: localhost 8 | port: 5432 9 | pool: 5 10 | timeout: 5 11 | 12 | # Warning: The database defined as "test" will be erased and 13 | # re-generated from your development database when you run "rake". 14 | # Do not set this db to the same as development or production. 15 | # 16 | # Note also, sqlite3 is totally unsupported by Metasploit now. 17 | test: 18 | <<: *pgsql 19 | database: metasploit_data_models_test 20 | username: metasploit_data_models_test 21 | password: ___________________________ 22 | 23 | -------------------------------------------------------------------------------- /spec/support/matchers/match_regex_exactly.rb: -------------------------------------------------------------------------------- 1 | # Checks that the string matches the 2 | RSpec::Matchers.define :match_string_exactly do |string| 3 | failure_message do |regexp| 4 | match = regexp.match(string) 5 | 6 | failure_message = "expected #{regexp} to match #{string}" 7 | 8 | if match 9 | failure_message << ', but' 10 | 11 | unless match.pre_match.empty? 12 | failure_message << " pre-match is #{match.pre_match}" 13 | end 14 | 15 | unless match.post_match.empty? 16 | failure_message << " post-match is #{match.post_match}" 17 | end 18 | end 19 | 20 | failure_message 21 | end 22 | 23 | match do |regexp| 24 | match = regexp.match(string) 25 | 26 | match && match.pre_match.empty? && match.post_match.empty? 27 | end 28 | end -------------------------------------------------------------------------------- /spec/dummy/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The change you wanted was rejected.

23 |

Maybe you tried to change something you didn't have access to.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /spec/factories/mdm/web_forms.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_web_form, :aliases => [:web_form], :class => Mdm::WebForm do 3 | # 4 | # Associations 5 | # 6 | association :web_site, :factory => :mdm_web_site 7 | 8 | trait :exported do 9 | add_attribute(:method) { generate :mdm_web_form_method } 10 | params { generate :mdm_web_form_params } 11 | path { generate :mdm_web_form_path } 12 | end 13 | end 14 | 15 | methods = ['GET', 'POST'] 16 | 17 | sequence :mdm_web_form_method do |n| 18 | methods[n % methods.length] 19 | end 20 | 21 | sequence :mdm_web_form_params do |n| 22 | [ 23 | [ 24 | "name#{n}", 25 | "value#{n}" 26 | ] 27 | ] 28 | end 29 | 30 | sequence :mdm_web_form_path do |n| 31 | "path/to/web/form/#{n}" 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /db/migrate/20110513143900_track_successful_exploits.rb: -------------------------------------------------------------------------------- 1 | class TrackSuccessfulExploits < ActiveRecord::Migration[4.2] 2 | 3 | 4 | class ExploitedHost < ApplicationRecord 5 | end 6 | 7 | class Vuln < ApplicationRecord 8 | end 9 | 10 | def self.up 11 | add_column :vulns, :exploited_at, :timestamp 12 | 13 | # Migrate existing exploited_hosts entries 14 | 15 | ExploitedHost.all.select {|x| x.name}.each do |exploited_host| 16 | next unless(exploited_host.name =~ /^(exploit|auxiliary)\//) 17 | vulns = Vuln.where(name: exploited_host.name, host_id: exploited_host.host_id) 18 | next if vulns.empty? 19 | vulns.each do |vuln| 20 | vuln.exploited_at = exploited_host.updated_at 21 | vuln.save 22 | end 23 | end 24 | 25 | end 26 | 27 | def self.down 28 | remove_column :vulns, :exploited_at 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /db/migrate/20130423211152_add_creds_counter_cache.rb: -------------------------------------------------------------------------------- 1 | class AddCredsCounterCache < ActiveRecord::Migration[4.2] 2 | def up 3 | add_column :hosts, :cred_count, :integer, :default => 0 4 | Mdm::Host.reset_column_information 5 | # Set initial counts 6 | cred_service_ids = Set.new 7 | Mdm::Cred.all.each {|c| cred_service_ids << c.service_id} 8 | cred_service_ids.each do |service_id| 9 | #Mdm::Host.reset_counters(Mdm::Service.find(service_id).host.id, :creds) 10 | begin 11 | host = Mdm::Service.find(service_id).host 12 | rescue 13 | next 14 | end 15 | next if host.nil? # This can happen with orphan creds/services 16 | host.cred_count = host.creds.count 17 | host.save 18 | end 19 | end 20 | 21 | def down 22 | remove_column :hosts, :cred_count 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/dummy/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The page you were looking for doesn't exist.

23 |

You may have mistyped the address or the page may have moved.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /db/migrate/20130412174719_change_foreign_key_in_module_refs.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_refs.module_detail_id` to `module_refs.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleRefs < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_refs 11 | 12 | # Renames `module_refs.detail_id` to `module_refs.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_refs.module_detail_id` to `module_refs.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20130412171844_change_foreign_key_in_module_archs.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_archs.module_detail_id` to `module_archs.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleArchs < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_archs 11 | 12 | # Renames `module_archs.detail_id` to `module_archs.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_archs.module_detail_id` to `module_archs.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20130412173640_change_foreign_key_in_module_mixins.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_mixins.module_detail_id` to `module_mixins.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleMixins < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_mixins 11 | 12 | # Renames `module_mixins.detail_id` to `module_mixins.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_mixins.module_detail_id` to `module_mixins.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20120625000004_add_vuln_attempts.rb: -------------------------------------------------------------------------------- 1 | class AddVulnAttempts < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :vuln_attempts do |t| 5 | t.integer :vuln_id # Vuln table reference 6 | t.timestamp :attempted_at # Timestamp of when the session was opened or the module exited 7 | t.boolean :exploited # Whether or not the attempt succeeded 8 | t.string :fail_reason # Short string corresponding to a Msf::Exploit::Failure constant 9 | t.string :username # The user that tested this vulnerability 10 | t.text :module # The specific module name that was used 11 | t.integer :session_id # Database identifier of any opened session 12 | t.integer :loot_id # Database identifier of any 'proof' loot (for non-session exploits) 13 | end 14 | end 15 | 16 | def self.down 17 | drop_table :vuln_attempts 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20130412154159_change_foreign_key_in_module_actions.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_actions.module_detail_id` to `module_actions.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleActions < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_actions 11 | 12 | # Renames `module_actions.detail_id` to `module_actions.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_actions.module_detail_id` to `module_actions.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20130412173121_change_foreign_key_in_module_authors.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_authors.module_detail_id` to `module_authors.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleAuthors < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_authors 11 | 12 | # Renames `module_authors.detail_id` to `module_authors.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_authors.module_detail_id` to `module_authors.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20130412175040_change_foreign_key_in_module_targets.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_targets.module_detail_id` to `module_targets.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModuleTargets < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_targets 11 | 12 | # Renames `module_targets.detail_id` to `module_targets.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_targets.module_detail_id` to `module_targets.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /db/migrate/20130412174254_change_foreign_key_in_module_platforms.rb: -------------------------------------------------------------------------------- 1 | # Changes `module_platforms.module_detail_id` to `module_platforms.detail_id` so that foreign key matches the conventional 2 | # name when `Mdm::ModuleDetail` became {Mdm::Module::Detail}. 3 | class ChangeForeignKeyInModulePlatforms < ActiveRecord::Migration[4.2] 4 | # 5 | # CONSTANTS 6 | # 7 | 8 | NEW_COLUMN_NAME= :detail_id 9 | OLD_COLUMN_NAME = :module_detail_id 10 | TABLE_NAME = :module_platforms 11 | 12 | # Renames `module_platforms.detail_id` to `module_platforms.module_detail_id`. 13 | # 14 | # @return [void] 15 | def down 16 | rename_column TABLE_NAME, NEW_COLUMN_NAME, OLD_COLUMN_NAME 17 | end 18 | 19 | # Rename `module_platforms.module_detail_id` to `module_platforms.detail_id` 20 | # 21 | # @return [void] 22 | def up 23 | rename_column TABLE_NAME, OLD_COLUMN_NAME, NEW_COLUMN_NAME 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/lib/ipaddr_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe IPAddr do 2 | subject(:ip_address) { IPAddr.new('10.0.0.1') } 3 | 4 | describe '#==' do 5 | it { is_expected.to be == '10.0.0.1'} 6 | it { is_expected.to be == IPAddr.new('10.0.0.1')} 7 | it { is_expected.not_to be == 'foo'} 8 | 9 | it 'does not raise an error when compared to a non ip address' do 10 | expect { 11 | ip_address == 'foo' 12 | }.to_not raise_error 13 | end 14 | end 15 | 16 | describe '#include?' do 17 | subject(:ip_range) { IPAddr.new('10.0.0.1/24') } 18 | it { is_expected.to include '10.0.0.1'} 19 | it { is_expected.to include ip_address} 20 | it { is_expected.not_to include 'foo'} 21 | 22 | it 'does not raise an error when checking for a non ip address' do 23 | expect { 24 | ip_range.include? 'foo' 25 | }.to_not raise_error 26 | end 27 | end 28 | 29 | end -------------------------------------------------------------------------------- /spec/dummy/config/database.yml.github_actions: -------------------------------------------------------------------------------- 1 | # @note This file is only for use in Github Actions. If you need to make a `spec/dummy/config/database.yml` for running 2 | # rake, rake spec, or rspec locally, please customize `spec/dummy/config/database.yml.example`. 3 | # 4 | # @example Customizing config/database.yml.example 5 | # cp spec/dummy/config/database.yml.example spec/dummy/config/database.yml 6 | # # update password fields for each environment's user 7 | 8 | development: &pgsql 9 | adapter: postgresql 10 | database: metasploit_data_models_development 11 | host: localhost 12 | username: postgres 13 | password: postgres 14 | pool: 25 15 | timeout: 5 16 | 17 | # Warning: The database defined as "test" will be erased and re-generated from your development database when you run 18 | # `rake`. Do not set this db to the same as development or production. 19 | test: 20 | <<: *pgsql 21 | database: metasploit_data_models_test -------------------------------------------------------------------------------- /db/migrate/001_add_wmap_tables.rb: -------------------------------------------------------------------------------- 1 | class AddWmapTables < ActiveRecord::Migration[4.2] 2 | def self.up 3 | create_table :wmap_targets do |t| 4 | t.string :host # vhost 5 | t.string :address, :limit => 16 # unique 6 | t.string :address6 7 | t.integer :port 8 | t.integer :ssl 9 | t.integer :selected 10 | end 11 | 12 | create_table :wmap_requests do |t| 13 | t.string :host # vhost 14 | t.string :address, :limit => 16 # unique 15 | t.string :address6 16 | t.integer :port 17 | t.integer :ssl 18 | t.string :meth, :limit => 32 19 | t.text :path 20 | t.text :headers 21 | t.text :query 22 | t.text :body 23 | t.string :respcode, :limit => 16 24 | t.text :resphead 25 | t.text :response 26 | t.timestamp :created 27 | end 28 | end 29 | 30 | def self.down 31 | drop_table :wmap_targets 32 | drop_table :wmap_requests 33 | end 34 | end 35 | 36 | -------------------------------------------------------------------------------- /db/migrate/20120625000003_expand_details2.rb: -------------------------------------------------------------------------------- 1 | class ExpandDetails2 < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | add_column :host_details, :nx_site_name, :string 5 | add_column :host_details, :nx_site_importance, :string 6 | add_column :host_details, :nx_scan_template, :string 7 | add_column :host_details, :nx_risk_score, :float 8 | 9 | add_column :vuln_details, :nx_scan_id, :integer 10 | add_column :vuln_details, :nx_vulnerable_since, :timestamp 11 | add_column :vuln_details, :nx_pci_compliance_status, :string 12 | end 13 | 14 | def self.down 15 | remove_column :host_details, :nx_site_name 16 | remove_column :host_details, :nx_site_importance 17 | remove_column :host_details, :nx_scan_template 18 | remove_column :host_details, :nx_risk_score 19 | 20 | remove_column :vuln_details, :nx_scan_id 21 | remove_column :vuln_details, :nx_vulnerable_since 22 | remove_column :vuln_details, :nx_pci_compliance_status 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/factories/mdm/routes.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_route, :aliases => [:route], :class => Mdm::Route do 3 | # 4 | # Associations 5 | # 6 | association :session, :factory => :mdm_session 7 | 8 | netmask { generate :mdm_route_netmask } 9 | subnet { generate :mdm_route_subnet } 10 | end 11 | 12 | sequence :mdm_route_netmask do |n| 13 | bits = 32 14 | bitmask = n % bits 15 | 16 | [ (~((2 ** (bits - bitmask)) - 1)) & 0xffffffff ].pack('N').unpack('CCCC').join('.') 17 | 18 | bits = 32 19 | shift = n % bits 20 | mask_range = 2 ** bits 21 | full_mask = mask_range - 1 22 | 23 | integer_netmask = (full_mask << shift) 24 | formatted_netmask = [integer_netmask].pack('N').unpack('CCCC').join('.') 25 | 26 | formatted_netmask 27 | end 28 | 29 | sequence :mdm_route_subnet do |n| 30 | class_c_network = n % 255 31 | 32 | "192.168.#{class_c_network}.0" 33 | end 34 | 35 | 36 | end 37 | -------------------------------------------------------------------------------- /spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_metasploit_model_search_operation_base.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'MetasploitDataModels::Search::Visitor::Includes#visit with Metasploit::Model::Search::Operation::Base' do 2 | let(:operator) do 3 | double('Operation Operator') 4 | end 5 | 6 | let(:node) do 7 | node_class.new( 8 | :operator => operator 9 | ) 10 | end 11 | 12 | it 'should visit operator' do 13 | expect(visitor).to receive(:visit).with(node).and_call_original 14 | expect(visitor).to receive(:visit).with(operator).and_return([]) 15 | 16 | visit 17 | end 18 | 19 | it 'should return operator visit' do 20 | operator_visit = ["Visited Operator"] 21 | expect(visitor).to receive(:visit).with(node).and_call_original 22 | allow(visitor).to receive(:visit).with(operator).and_return(operator_visit) 23 | 24 | expect(visit).to eq(operator_visit) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/support/shared/examples/mdm/module/detail/supports_stance_with_mtype.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'Mdm::Module::Detail supports stance with mtype' do |mtype| 2 | context "with #{mtype.inspect}" do 3 | # define as a let so that lets from outer context can access option to set detail. 4 | let(:mtype) do 5 | mtype 6 | end 7 | 8 | it 'should return true for supports_stance?' do 9 | expect(detail.supports_stance?).to eq(true) 10 | end 11 | 12 | context 'with nil stance' do 13 | let(:stance) do 14 | nil 15 | end 16 | 17 | it { is_expected.to be_invalid } 18 | end 19 | 20 | context "with 'aggresive' stance" do 21 | let(:stance) do 22 | 'aggressive' 23 | end 24 | 25 | it { is_expected.to be_valid } 26 | end 27 | 28 | context "with 'passive' stance" do 29 | let(:stance) do 30 | 'passive' 31 | end 32 | 33 | it { is_expected.to be_valid } 34 | end 35 | end 36 | end -------------------------------------------------------------------------------- /lib/metasploit_data_models/change_required_columns_to_null_false.rb: -------------------------------------------------------------------------------- 1 | # Changes all the COLUMNS in the table with TABLE_NAME that are required from the table's mode, but were previously 2 | # `:null => true`, to `:null => false`. 3 | # 4 | # @abstract Subclass and define COLUMNS as Array and TABLE_NAME as Symbol. 5 | class MetasploitDataModels::ChangeRequiredColumnsToNullFalse < ActiveRecord::Migration[4.2] 6 | # Marks all the COLUMNS as `:null => true` 7 | def down 8 | # Use self.class:: so constants are resolved in subclasses instead of this class. 9 | self.class::COLUMNS.each do |column| 10 | change_column_null(self.class::TABLE_NAME, column, true) 11 | end 12 | end 13 | 14 | # Marks all the COLUMNS as `:null => false` 15 | def up 16 | # Use self.class:: so constants are resolved in subclasses instead of this class. 17 | self.class::COLUMNS.each do |column| 18 | change_column_null(self.class::TABLE_NAME, column, false) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/app/models/metasploit_data_models/search/operation/port/number_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::Search::Operation::Port::Number, type: :model do 2 | context 'CONSTANTS' do 3 | context 'BITS' do 4 | subject(:bits) { 5 | described_class::BITS 6 | } 7 | 8 | it { is_expected.to eq(16) } 9 | end 10 | 11 | context 'MAXIMUM' do 12 | subject(:maxium) { 13 | described_class::MAXIMUM 14 | } 15 | 16 | it { is_expected.to eq(65535) } 17 | end 18 | 19 | context 'MINIMUM' do 20 | subject(:minimum) { 21 | described_class::MINIMUM 22 | } 23 | 24 | it { is_expected.to eq(0) } 25 | end 26 | 27 | context 'RANGE' do 28 | subject(:range) { 29 | described_class::RANGE 30 | } 31 | 32 | it { is_expected.to eq((0..65535)) } 33 | end 34 | end 35 | 36 | context 'validations' do 37 | it { is_expected.to validate_inclusion_of(:value).in_range(described_class::RANGE) } 38 | end 39 | end -------------------------------------------------------------------------------- /app/models/mdm/task_host.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Host} and {Mdm::Task} that signifies that the {#task} found the {#host}. 2 | class Mdm::TaskHost < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # The {Mdm::Host} found by {#task}. 8 | belongs_to :host, 9 | class_name: 'Mdm::Host', 10 | inverse_of: :task_hosts 11 | 12 | # An {Mdm::Task} that found {#host}. 13 | belongs_to :task, 14 | class_name: 'Mdm::Task', 15 | inverse_of: :task_hosts 16 | 17 | # 18 | # Attributes 19 | # 20 | 21 | # @!attribute created_at 22 | # When this task host was created. 23 | # 24 | # @return [DateTime] 25 | 26 | # @!attribute updated_at 27 | # The last time this task host was updated. 28 | # 29 | # @return [DateTime] 30 | 31 | # 32 | # Validations 33 | # 34 | 35 | validates :host_id, 36 | :uniqueness => { 37 | :scope => :task_id 38 | } 39 | 40 | Metasploit::Concern.run(self) 41 | end 42 | -------------------------------------------------------------------------------- /db/migrate/002_add_workspaces.rb: -------------------------------------------------------------------------------- 1 | class AddWorkspaces < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :workspaces do |t| 5 | t.string :name 6 | t.timestamps null: false 7 | end 8 | 9 | change_table :hosts do |t| 10 | t.integer :workspace_id, :required => true 11 | end 12 | 13 | remove_index :hosts, :column => :address 14 | 15 | # 16 | # This was broken after 018_add_workspace_user_info was introduced 17 | # because of the new boundary column. For some reason, the 18 | # find_or_create_by_name that .default eventually calls here tries to 19 | # create a record with the boundary field that doesn't exist yet. 20 | # See #1724 21 | # 22 | #w = Msf::DBManager::Workspace.default 23 | #Msf::DBManager::Host.update_all ["workspace_id = ?", w.id] 24 | end 25 | 26 | def self.down 27 | drop_table :workspaces 28 | 29 | change_table :hosts do |t| 30 | t.remove :workspace_id 31 | end 32 | 33 | add_index :hosts, :address, :unique => true 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/arch_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Arch, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:name).of_type(:text) } 13 | end 14 | 15 | context 'indices' do 16 | it { is_expected.to have_db_index(:detail_id) } 17 | end 18 | end 19 | 20 | context 'factories' do 21 | context 'mdm_module_arch' do 22 | subject(:mdm_module_arch) do 23 | FactoryBot.build(:mdm_module_arch) 24 | end 25 | 26 | it { is_expected.to be_valid } 27 | end 28 | end 29 | 30 | context 'validations' do 31 | it { is_expected.to validate_presence_of(:detail) } 32 | it { is_expected.to validate_presence_of(:name) } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /db/migrate/006_add_timestamps.rb: -------------------------------------------------------------------------------- 1 | 2 | # Adds 'created_at' and 'updated_at' columns to every primary table. 3 | # 4 | class AddTimestamps < ActiveRecord::Migration[4.2] 5 | 6 | @@TABLES_NEEDING_RENAME = [:clients, :hosts, :notes, :refs, :services, :vulns, :wmap_requests] 7 | @@TABLES_NEEDING_CREATED_AT = [:wmap_targets] 8 | @@TABLES_NEEDING_UPDATED_AT = [:clients, :events, :hosts, :notes, :refs, :services, :vulns, :wmap_requests, :wmap_targets] 9 | 10 | def self.up 11 | @@TABLES_NEEDING_RENAME.each { |t| rename_column t, :created, :created_at } 12 | 13 | @@TABLES_NEEDING_CREATED_AT.each { |t| add_column t, :created_at, :datetime } 14 | 15 | @@TABLES_NEEDING_UPDATED_AT.each { |t| add_column t, :updated_at, :datetime } 16 | end 17 | 18 | def self.down 19 | @@TABLES_NEEDING_RENAME.each { |t| rename_column t, :created_at, :created } 20 | 21 | @@TABLES_NEEDING_CREATED_AT.each { |t| remove_column t, :created_at } 22 | 23 | @@TABLES_NEEDING_UPDATED_AT.each { |t| remove_column t, :updated_at } 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /db/migrate/20130515172727_valid_mdm_web_vuln_params.rb: -------------------------------------------------------------------------------- 1 | class ValidMdmWebVulnParams < ActiveRecord::Migration[4.2] 2 | # Don't put back the bad format because there's not way to figure our which of the [] were '' before {#up} and 3 | # which were `[]` before {#up}. 4 | # 5 | # @return [void] 6 | def down 7 | end 8 | 9 | # Changes any Mdm::WebVuln#params with value `''` to value `[]`. 10 | # 11 | # @return [void] 12 | def up 13 | # Can't search serialized columns, so have to load all the Mdm::WebVulns in memory 14 | Mdm::WebVuln.find_each do |web_vuln| 15 | if web_vuln.invalid? 16 | # cast nil, '' and {} to correct []. 17 | if web_vuln.params.blank? 18 | web_vuln.params = [] 19 | end 20 | 21 | # If its still invalid have to destroy the Mdm::WebVuln or a different export error could occur. 22 | if web_vuln.invalid? 23 | web_vuln.destroy 24 | else 25 | web_vuln.save! 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/mixin_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Mixin, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:name).of_type(:text) } 13 | end 14 | 15 | context 'indices' do 16 | it { is_expected.to have_db_index(:detail_id) } 17 | end 18 | end 19 | 20 | context 'factories' do 21 | context 'mdm_module_mixin' do 22 | subject(:mdm_module_mixin) do 23 | FactoryBot.build :mdm_module_mixin 24 | end 25 | 26 | it { is_expected.to be_valid } 27 | end 28 | end 29 | 30 | context 'validations' do 31 | it { is_expected.to validate_presence_of(:detail) } 32 | it { is_expected.to validate_presence_of(:name) } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/action_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Action, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:name).of_type(:text) } 13 | end 14 | 15 | context 'indices' do 16 | it { is_expected.to have_db_index(:detail_id) } 17 | end 18 | end 19 | 20 | context 'factories' do 21 | context 'mdm_module_action' do 22 | subject(:mdm_module_action) do 23 | FactoryBot.build(:mdm_module_action) 24 | end 25 | 26 | it { is_expected.to be_valid } 27 | end 28 | end 29 | 30 | context 'validations' do 31 | it { is_expected.to validate_presence_of(:detail) } 32 | it { is_expected.to validate_presence_of(:name) } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/serialized_prefs.rb: -------------------------------------------------------------------------------- 1 | # Allows attributes to be extracted and written to key of serialized `Hash` `prefs`. 2 | module MetasploitDataModels::SerializedPrefs 3 | # Setup each arg in `args` as the name of an attribute embedded in the `prefs` `Hash`. Defines `#` and 4 | # `#=(value)` methods like standard `attr_accessor`. 5 | # 6 | # @param args [Array] The names of the attributes to store in the `prefs` `Hash`. 7 | # @return [void] 8 | def serialized_prefs_attr_accessor(*args) 9 | args.each do |method_name| 10 | 11 | method_declarations = <<-RUBY 12 | def #{method_name} 13 | return if not self.prefs 14 | self.prefs[:#{method_name}] 15 | end 16 | 17 | def #{method_name}=(value) 18 | temp = self.prefs || {} 19 | temp[:#{method_name}] = value 20 | self.prefs = temp 21 | end 22 | RUBY 23 | 24 | class_eval method_declarations, __FILE__, __LINE__ 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/platform_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Platform, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:name).of_type(:text) } 13 | end 14 | 15 | context 'indices' do 16 | it { is_expected.to have_db_index(:detail_id) } 17 | end 18 | end 19 | 20 | context 'factories' do 21 | context 'mdm_module_platform' do 22 | subject(:mdm_module_platform) do 23 | FactoryBot.build :mdm_module_platform 24 | end 25 | 26 | it { is_expected.to be_valid } 27 | end 28 | end 29 | 30 | context 'validations' do 31 | it { is_expected.to validate_presence_of :detail } 32 | it { is_expected.to validate_presence_of :name } 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/models/mdm/task_service.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Service} and {Mdm::Task} that signifies that the {#task} found the {#service}. 2 | class Mdm::TaskService < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # The {Mdm::Service} found by {#task}. 8 | belongs_to :service, 9 | class_name: 'Mdm::Service', 10 | inverse_of: :task_services 11 | 12 | # An {Mdm::Task} that found {#service}. 13 | belongs_to :task, 14 | class_name: 'Mdm::Task', 15 | inverse_of: :task_services 16 | 17 | # 18 | # Attributes 19 | # 20 | 21 | # @!attribute created_at 22 | # When this task service was created. 23 | # 24 | # @return [DateTime] 25 | 26 | # @!attribute updated_at 27 | # The last time this task service was updated. 28 | # 29 | # @return [DateTime] 30 | 31 | # 32 | # Validations 33 | # 34 | 35 | validates :service_id, 36 | :uniqueness => { 37 | :scope => :task_id 38 | } 39 | 40 | Metasploit::Concern.run(self) 41 | end 42 | -------------------------------------------------------------------------------- /app/models/mdm/task_session.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Session} and {Mdm::Task} that signifies that the {#task} spawned the {#session}. 2 | class Mdm::TaskSession < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # The {Mdm::Session} found by {#task}. 8 | belongs_to :session, 9 | class_name: 'Mdm::Session', 10 | inverse_of: :task_sessions 11 | 12 | # An {Mdm::Task} that found {#session} 13 | belongs_to :task, 14 | class_name: 'Mdm::Task', 15 | inverse_of: :task_sessions 16 | 17 | # 18 | # Attributes 19 | # 20 | 21 | # @!attribute created_at 22 | # When this task session was created. 23 | # 24 | # @return [DateTime] 25 | 26 | # @!attribute updated_at 27 | # The last time this task session was updated. 28 | # 29 | # @return [DateTime] 30 | 31 | # 32 | # Validations 33 | # 34 | 35 | validates :session_id, 36 | :uniqueness => { 37 | :scope => :task_id 38 | } 39 | 40 | Metasploit::Concern.run(self) 41 | end 42 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/automatic_exploitation.rb: -------------------------------------------------------------------------------- 1 | # Namespace for automatic exploitation. Automatic exploitation 2 | # {MetasploitDataModels::AutomaticExploitation::Match matches} 3 | # {MetasploitDataModels::AutomaticExploitation::Match#matchable services or vulnerbatility} with the 4 | # {MetasploitDataModels::AutomaticExploitation::Match#module_detail Metasploit Module} that can exploit the service or 5 | # vulnerability. These matches are grouped into a {MetasploitDataModels::AutomaticExploitation::MatchSet a set} that 6 | # can be {MetasploitDataModels::AutomaticExploitation::Run run} multiple times. 7 | module MetasploitDataModels::AutomaticExploitation 8 | extend ActiveSupport::Autoload 9 | 10 | autoload :Match 11 | autoload :MatchResult 12 | autoload :MatchSet 13 | autoload :Run 14 | 15 | # 16 | # Module Methods 17 | # 18 | 19 | # The prefix of the `ApplicationRecord#table_name` of subclasses in this namespace. 20 | # 21 | # @return [String] 22 | def self.table_name_prefix 23 | 'automatic_exploitation_' 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: Verify 2 | 3 | # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions 4 | permissions: 5 | actions: none 6 | checks: none 7 | contents: none 8 | deployments: none 9 | id-token: none 10 | issues: none 11 | discussions: none 12 | packages: none 13 | pages: none 14 | pull-requests: none 15 | repository-projects: none 16 | security-events: none 17 | statuses: none 18 | 19 | on: 20 | push: 21 | branches: 22 | - '*' 23 | pull_request: 24 | branches: 25 | - '*' 26 | 27 | jobs: 28 | build: 29 | uses: rapid7/metasploit-framework/.github/workflows/shared_gem_verify_rails.yml@master 30 | with: 31 | dependencies: '["libpcap-dev", "graphviz"]' 32 | test_commands: | 33 | cp spec/dummy/config/database.yml.github_actions spec/dummy/config/database.yml 34 | bundle exec rake --version 35 | bundle exec rake db:create db:migrate 36 | bundle exec rake spec 37 | bundle exec rake spec 38 | bundle exec rake yard 39 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/automatic_exploitation/run.rb: -------------------------------------------------------------------------------- 1 | # Runs a {#match_set set of matches} to produce {#match_results results}. 2 | class MetasploitDataModels::AutomaticExploitation::Run < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # Results of each match in {#match_set}. 8 | has_many :match_results, 9 | class_name:'MetasploitDataModels::AutomaticExploitation::MatchResult', 10 | inverse_of: :run, 11 | dependent: :destroy 12 | 13 | # Set of matches to run 14 | belongs_to :match_set, 15 | class_name: 'MetasploitDataModels::AutomaticExploitation::MatchSet', 16 | inverse_of: :runs 17 | 18 | # User that initiated this run. 19 | belongs_to :user, 20 | class_name: "Mdm::User", 21 | inverse_of: :automatic_exploitation_runs 22 | 23 | # Workspace in which this run was performed. 24 | belongs_to :workspace, 25 | class_name: "Mdm::Workspace", 26 | inverse_of: :automatic_exploitation_runs 27 | 28 | Metasploit::Concern.run(self) 29 | end 30 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/operator/ip_address.rb: -------------------------------------------------------------------------------- 1 | # Operator for `inet` columns in a PostgreSQL database, which operates on formatted values using 2 | # {MetasploitDataModels::Search::Operation::IPAddress}. 3 | class MetasploitDataModels::Search::Operator::IPAddress < Metasploit::Model::Search::Operator::Single 4 | # 5 | # Attributes 6 | # 7 | 8 | # @!attribute [r] attribute 9 | # The attribute on `Metasploit::Model::Search::Operator::Base#klass` that is searchable. 10 | # 11 | # @return [Symbol] the attribute name 12 | attr_accessor :attribute 13 | 14 | # 15 | # Validations 16 | # 17 | 18 | validates :attribute, 19 | presence: true 20 | 21 | # 22 | # Instance Methods 23 | # 24 | 25 | alias_method :name, :attribute 26 | 27 | # The class used for `Metasploit::Model::Search::Operator::Single#operate_on`. 28 | # 29 | # @return [String] `'MetasploitDataModels::Search::Operation::IPAddress'` 30 | def operation_class_name 31 | @operation_class_name ||= 'MetasploitDataModels::Search::Operation::IPAddress' 32 | end 33 | end -------------------------------------------------------------------------------- /spec/app/models/mdm/route_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Route, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | context 'associations' do 5 | it { is_expected.to belong_to(:session).class_name('Mdm::Session') } 6 | end 7 | 8 | context 'factory' do 9 | it 'should be valid' do 10 | route = FactoryBot.build(:mdm_route) 11 | expect(route).to be_valid 12 | end 13 | end 14 | 15 | context '#destroy' do 16 | it 'should successfully destroy the object' do 17 | route = FactoryBot.create(:mdm_route) 18 | expect { 19 | route.destroy 20 | }.to_not raise_error 21 | expect { 22 | route.reload 23 | }.to raise_error(ActiveRecord::RecordNotFound) 24 | end 25 | end 26 | 27 | context 'database' do 28 | context 'columns' do 29 | it { is_expected.to have_db_column(:session_id).of_type(:integer) } 30 | it { is_expected.to have_db_column(:subnet).of_type(:string) } 31 | it { is_expected.to have_db_column(:netmask).of_type(:string) } 32 | end 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_equality.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'MetasploitDataModels::Search::Visitor::Where#visit with equality operation' do 2 | let(:node) do 3 | node_class.new( 4 | :operator => operator, 5 | :value => value 6 | ) 7 | end 8 | 9 | let(:operator) do 10 | Metasploit::Model::Search::Operator::Attribute.new( 11 | # any class that responds to arel_table 12 | :klass => Mdm::Host 13 | ) 14 | end 15 | 16 | let(:value) do 17 | "value" 18 | end 19 | 20 | it 'should visit operation.operator with attribute_visitor' do 21 | expect(visitor.attribute_visitor).to receive(:visit).with(operator).and_call_original 22 | 23 | visit 24 | end 25 | 26 | it 'should call eq on Arel::Attributes::Attribute from attribute_visitor' do 27 | attribute = double('Visited Operator') 28 | allow(visitor.attribute_visitor).to receive(:visit).with(operator).and_return(attribute) 29 | 30 | expect(attribute).to receive(:eq).with(value) 31 | 32 | visit 33 | end 34 | end -------------------------------------------------------------------------------- /app/models/mdm/module/target.rb: -------------------------------------------------------------------------------- 1 | # A potential target for a {Mdm::Module::Detail exploit Metasploit Module}. Targets can change options including 2 | # offsets for ROP chains to tune an exploit to work with different system libraries and versions. 3 | class Mdm::Module::Target < ApplicationRecord 4 | self.table_name = 'module_targets' 5 | 6 | # 7 | # Associations 8 | # 9 | 10 | # Exploit Metasploit Module with the {#name named} target at the given {#index}. 11 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 12 | 13 | # 14 | # Attributes 15 | # 16 | 17 | # @!attribute index 18 | # The index of this target in the {#detail exploit Metasploit Module}'s list of targets. The index is used for 19 | # target selection. 20 | # 21 | # @return [Integer] 22 | 23 | # @!attribute name 24 | # The name of this target. 25 | # 26 | # @return [String] 27 | 28 | # 29 | # Validators 30 | # 31 | 32 | validates :detail, :presence => true 33 | validates :index, :presence => true 34 | validates :name, :presence => true 35 | 36 | Metasploit::Concern.run(self) 37 | end 38 | -------------------------------------------------------------------------------- /app/models/mdm/client.rb: -------------------------------------------------------------------------------- 1 | # Client used for `report_client` in metasploit-framework Metasploit Modules. 2 | class Mdm::Client < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # {Mdm::Host} from which this client connected. 8 | belongs_to :host, 9 | class_name: 'Mdm::Host', 10 | inverse_of: :clients 11 | 12 | # 13 | # Attributes 14 | # 15 | 16 | # @!attribute created_at 17 | # When this client was created. 18 | # 19 | # @return [DateTime] 20 | 21 | # @!attribute updated_at 22 | # When this client was last updated. 23 | # 24 | # @return [DateTime] 25 | 26 | # 27 | # @!group User Agent 28 | # 29 | 30 | # @!attribute ua_name 31 | # Parsed name from {#ua_string user agent string} 32 | # 33 | # @return [String] 34 | 35 | # @!attribute ua_string 36 | # Raw user agent string from client browser 37 | # 38 | # @return [String] 39 | 40 | # @!attribute ua_ver 41 | # Version of user agent. 42 | # 43 | # @return [String] 44 | 45 | # 46 | # @!endgroup 47 | # 48 | 49 | Metasploit::Concern.run(self) 50 | end 51 | -------------------------------------------------------------------------------- /app/models/mdm/session_event.rb: -------------------------------------------------------------------------------- 1 | # Events that occurred when using a {#session}. 2 | class Mdm::SessionEvent < ApplicationRecord 3 | 4 | # 5 | # Associations 6 | # 7 | 8 | # The session in which the event occurred. 9 | belongs_to :session, 10 | class_name: 'Mdm::Session', 11 | inverse_of: :events 12 | 13 | # @!attribute command 14 | # The command that was run through the session that triggered this event. 15 | # 16 | # @return [String] 17 | 18 | # @!attribute created_at 19 | # When this event occurred. 20 | # 21 | # @return [DateTime] 22 | 23 | # @!attribute etype 24 | # The type of the event. 25 | # 26 | # @return [String] 27 | 28 | # @!attribute local_path 29 | # The current local directory when {#command} was run. 30 | # 31 | # @return [String] 32 | 33 | # @!attribute output 34 | # The {#output} of running {#command}. 35 | # 36 | # @return [String] 37 | 38 | # @!attribute remote_path 39 | # The current remote directory when {#command} was run. 40 | # 41 | # @return [String] 42 | 43 | Metasploit::Concern.run(self) 44 | end 45 | -------------------------------------------------------------------------------- /app/models/mdm/module/action.rb: -------------------------------------------------------------------------------- 1 | # Actions that auxiliary or post Metasploit Modules can perform. Actions are used to select subcommand-like behavior 2 | # implemented by the same Metasploit Nodule. The semantics of a given action are specific to a given 3 | # {Mdm::Module::Detail Metasploit Module}: if two {Mdm::Module::Detail Metasploit Modules} have 4 | # {Mdm::Module::Action actions} with the same {Mdm::Module::Action#name name}, no similarity should be assumed between 5 | # those two {Mdm::Module::Action actions} or {Mdm::Module::Detail Metasploit Modules}. 6 | class Mdm::Module::Action < ApplicationRecord 7 | self.table_name = 'module_actions' 8 | 9 | # 10 | # Associations 11 | # 12 | 13 | # The Metasploit Module with this action. 14 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 15 | 16 | # 17 | # Attributes 18 | # 19 | 20 | # @!attribute [rw] name 21 | # The name of this action. 22 | # 23 | # @return [String] 24 | 25 | # 26 | # Validations 27 | # 28 | 29 | validates :detail, :presence => true 30 | validates :name, :presence => true 31 | 32 | Metasploit::Concern.run(self) 33 | end 34 | -------------------------------------------------------------------------------- /lib/metasploit_data_models/yaml.rb: -------------------------------------------------------------------------------- 1 | # Namespace for YAML configuration 2 | class MetasploitDataModels::YAML 3 | # 4 | # CONSTANTS 5 | # 6 | 7 | # List of supported classes when deserializing YAML classes 8 | # See: https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 9 | # 10 | PERMITTED_CLASSES = [ 11 | Range, 12 | Set, 13 | Symbol, 14 | Time, 15 | 'WEBrick::Cookie'.to_sym, 16 | 'ActionController::Parameters'.to_sym, 17 | 'ActiveModel::Attribute::FromDatabase'.to_sym, 18 | 'ActiveModel::Attribute::FromUser'.to_sym, 19 | 'ActiveModel::Attribute::WithCastValue'.to_sym, 20 | 'ActiveModel::Type::Boolean'.to_sym, 21 | 'ActiveModel::Type::Integer'.to_sym, 22 | 'ActiveModel::Type::String'.to_sym, 23 | 'ActiveRecord::Coders::JSON'.to_sym, 24 | 'ActiveSupport::TimeWithZone'.to_sym, 25 | 'ActiveSupport::TimeZone'.to_sym, 26 | 'ActiveRecord::Type::Serialized'.to_sym, 27 | 'ActiveRecord::Type::Text'.to_sym, 28 | 'ActiveSupport::HashWithIndifferentAccess'.to_sym, 29 | 'Mdm::Workspace'.to_sym 30 | ].freeze 31 | end 32 | -------------------------------------------------------------------------------- /spec/dummy/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | # Raises error for missing translations 26 | # config.action_view.raise_on_missing_translations = true 27 | end 28 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/target_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Target, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:index).of_type(:integer) } 13 | it { is_expected.to have_db_column(:name).of_type(:text) } 14 | end 15 | 16 | context 'indices' do 17 | it { is_expected.to have_db_index(:detail_id) } 18 | end 19 | end 20 | 21 | context 'factories' do 22 | context 'mdm_module_target' do 23 | subject(:mdm_module_target) do 24 | FactoryBot.build :mdm_module_target 25 | end 26 | 27 | it { is_expected.to be_valid } 28 | end 29 | end 30 | 31 | context 'validations' do 32 | it { is_expected.to validate_presence_of(:detail) } 33 | it { is_expected.to validate_presence_of(:index) } 34 | it { is_expected.to validate_presence_of(:name) } 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/factories/module_runs.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | sequence(:session_id) 3 | 4 | factory :metasploit_data_models_module_run, class: MetasploitDataModels::ModuleRun do 5 | 6 | association :user, factory: :mdm_user 7 | association :module_detail, factory: :mdm_module_detail 8 | association :trackable, factory: :mdm_host 9 | 10 | trait :failed do 11 | status { MetasploitDataModels::ModuleRun::FAIL } 12 | end 13 | 14 | trait :exploited do 15 | status { MetasploitDataModels::ModuleRun::SUCCEED } 16 | end 17 | 18 | trait :error do 19 | status { MetasploitDataModels::ModuleRun::ERROR } 20 | end 21 | 22 | attempted_at { Time.now } 23 | port { generate :port } 24 | proto { "tcp" } 25 | fail_detail { generate :module_run_fail_detail } 26 | status { MetasploitDataModels::ModuleRun::SUCCEED } 27 | username { "joefoo" } 28 | end 29 | 30 | sequence :module_run_module_fullname do |n| 31 | "exploit/windows/happy-stack-smasher-#{n}" 32 | end 33 | 34 | sequence :module_run_fail_detail do |n| 35 | "MetasploitDataModels::ModuleRun#fail_detail #{n}" 36 | end 37 | 38 | 39 | end 40 | 41 | -------------------------------------------------------------------------------- /spec/support/shared/examples/metasploit_data_models/search/visitor/includes/visit/with_children.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'MetasploitDataModels::Search::Visitor::Includes#visit with #children' do 2 | let(:children) do 3 | 2.times.collect { |n| 4 | double("Child #{n}") 5 | } 6 | end 7 | 8 | let(:node) do 9 | node_class.new( 10 | :children => children 11 | ) 12 | end 13 | 14 | it 'should visit each child' do 15 | # needed for call to visit subject 16 | expect(visitor).to receive(:visit).with(node).and_call_original 17 | 18 | children.each do |child| 19 | expect(visitor).to receive(:visit).with(child).and_return([]) 20 | end 21 | 22 | visit 23 | end 24 | 25 | it 'should return Array of all child visits' do 26 | child_visits = [] 27 | 28 | expect(visitor).to receive(:visit).with(node).and_call_original 29 | 30 | children.each_with_index do |child, i| 31 | child_visit = ["Visited Child #{i}"] 32 | allow(visitor).to receive(:visit).with(child).and_return(child_visit) 33 | child_visits.concat(child_visit) 34 | end 35 | 36 | expect(visit).to eq(child_visits) 37 | end 38 | end -------------------------------------------------------------------------------- /db/migrate/20101203000000_fix_web_tables.rb: -------------------------------------------------------------------------------- 1 | class FixWebTables < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | change_column :web_pages, :path, :text 5 | change_column :web_pages, :query, :text 6 | change_column :web_pages, :cookie, :text 7 | change_column :web_pages, :auth, :text 8 | change_column :web_pages, :ctype, :text 9 | change_column :web_pages, :location, :text 10 | change_column :web_pages, :path, :text 11 | change_column :web_vulns, :path, :text 12 | change_column :web_vulns, :pname, :text 13 | 14 | add_column :web_pages, :request, :text 15 | add_column :web_vulns, :request, :text 16 | end 17 | 18 | def self.down 19 | change_column :web_pages, :path, :text 20 | change_column :web_pages, :query, :text 21 | change_column :web_pages, :cookie, :text 22 | change_column :web_pages, :auth, :text 23 | change_column :web_pages, :ctype, :text 24 | change_column :web_pages, :location, :text 25 | change_column :web_pages, :path, :text 26 | change_column :web_vulns, :path, :text 27 | change_column :web_vulns, :pname, :text 28 | 29 | remove_column :web_pages, :request 30 | remove_column :web_vulns, :request 31 | end 32 | end 33 | 34 | 35 | -------------------------------------------------------------------------------- /.simplecov: -------------------------------------------------------------------------------- 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_profile('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 -------------------------------------------------------------------------------- /app/models/mdm/module/ref.rb: -------------------------------------------------------------------------------- 1 | # External references to the vulnerability exploited by this module. 2 | class Mdm::Module::Ref < ApplicationRecord 3 | self.table_name = 'module_refs' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # @!attribute [rw] detail 10 | # The root of the module metadata tree. 11 | # 12 | # @return [Mdm::Module::Detail] 13 | belongs_to :detail, :class_name => 'Mdm::Module::Detail' 14 | 15 | # @!attribute [r] refs 16 | # References with the same name attached to {Mdm::Vuln Mdm::Vulns}. 17 | # 18 | # @return [Array] 19 | has_many :refs, 20 | :class_name => 'Mdm::Ref', 21 | :foreign_key => :name, 22 | :primary_key => :name 23 | 24 | # 25 | # Attributes 26 | # 27 | 28 | # @!attribute [rw] name 29 | # Designation for external reference. May include a prefix for the authority, such as 'CVE-', in which case the 30 | # rest of the name is the designation assigned by that authority. 31 | # 32 | # @return [String] 33 | 34 | # 35 | # Validations 36 | # 37 | 38 | validates :detail, :presence => true 39 | validates :name, :presence => true 40 | 41 | Metasploit::Concern.run(self) 42 | end 43 | -------------------------------------------------------------------------------- /app/models/mdm/host_tag.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Host} and {Mdm::Tag}. 2 | class Mdm::HostTag < ApplicationRecord 3 | self.table_name = "hosts_tags" 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # Host with {#tag}. 10 | # 11 | # @todo MSP-2723 12 | belongs_to :host, 13 | class_name: 'Mdm::Host', 14 | inverse_of: :hosts_tags 15 | 16 | # Tag on {#host}. 17 | # 18 | # @todo MSP-2723 19 | belongs_to :tag, 20 | class_name: 'Mdm::Tag', 21 | inverse_of: :hosts_tags 22 | 23 | # 24 | # Callbacks 25 | # 26 | 27 | # @see http://stackoverflow.com/a/11694704 28 | after_destroy :destroy_orphan_tag 29 | 30 | # 31 | # Instance Methods 32 | # 33 | 34 | private 35 | 36 | # Destroys {#tag} if it is orphaned 37 | # 38 | # @see http://stackoverflow.com/a/11694704 39 | # @return [void] 40 | def destroy_orphan_tag 41 | # ensure fresh load of tag record 42 | # in theory this will always return one result safe navigation is just "extra" 43 | Mdm::Tag.where(id: tag.id).first&.destroy_if_orphaned 44 | end 45 | 46 | # switch back to public for load hooks 47 | public 48 | 49 | Metasploit::Concern.run(self) 50 | end 51 | 52 | -------------------------------------------------------------------------------- /app/models/mdm/api_key.rb: -------------------------------------------------------------------------------- 1 | # API key to access the RPC. 2 | class Mdm::ApiKey < ApplicationRecord 3 | 4 | # 5 | # Attributes 6 | # 7 | 8 | # @!attribute [rw] created_at 9 | # When this API Key was created. 10 | # 11 | # @return [DateTime] 12 | 13 | # @!attribute [rw] token 14 | # The API Key to authenicate to the RPC. 15 | # 16 | # @return [String] 17 | 18 | # @!attribute [rw] updated_at 19 | # The last time this API Key was updated. 20 | # 21 | # @return [DateTime] 22 | 23 | # 24 | # 25 | # Validations 26 | # 27 | # 28 | 29 | # 30 | # Method Validations 31 | # 32 | 33 | validate :supports_api 34 | 35 | # 36 | # Attribute Validations 37 | # 38 | 39 | validates :token, :presence => true, :length => { :minimum => 8 } 40 | 41 | # 42 | # Instance Methods 43 | # 44 | 45 | protected 46 | 47 | 48 | # Validates whether License supports API. 49 | # 50 | # @return [void] 51 | # @todo MSP-2724 52 | def supports_api 53 | license = License.get 54 | 55 | if license and not license.supports_api? 56 | errors.add :license, " - this product does not support API access" 57 | end 58 | end 59 | 60 | Metasploit::Concern.run(self) 61 | end 62 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/automatic_exploitation/match_set.rb: -------------------------------------------------------------------------------- 1 | # A set of {#matches automatic exploitation matches}. 2 | class MetasploitDataModels::AutomaticExploitation::MatchSet < ApplicationRecord 3 | # 4 | # Associations 5 | # 6 | 7 | # Runs of this set of {#matches}. 8 | has_many :runs, 9 | class_name: "MetasploitDataModels::AutomaticExploitation::Run", 10 | inverse_of: :match_set 11 | 12 | # Matches in this set. 13 | has_many :matches, 14 | class_name: "MetasploitDataModels::AutomaticExploitation::Match", 15 | inverse_of: :match_set, 16 | dependent: :destroy 17 | 18 | # User that created this match set. 19 | belongs_to :user, 20 | inverse_of: :automatic_exploitation_match_sets, 21 | class_name: "Mdm::User" 22 | 23 | # Workspace in which this match set exists. 24 | belongs_to :workspace, 25 | inverse_of: :automatic_exploitation_match_sets, 26 | class_name: "Mdm::Workspace" 27 | 28 | # 29 | # Validations 30 | # 31 | 32 | validates :user, 33 | presence: true 34 | 35 | validates :workspace, 36 | presence: true 37 | 38 | 39 | Metasploit::Concern.run(self) 40 | end 41 | -------------------------------------------------------------------------------- /spec/factories/mdm/services.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :mdm_service, :class => Mdm::Service do 3 | # 4 | # Associations 5 | # 6 | association :host, :factory => :mdm_host 7 | 8 | # 9 | # Attributes 10 | # 11 | name { generate :mdm_service_name } 12 | port { generate :port } 13 | proto { generate :mdm_service_proto } 14 | state { 'open' } 15 | resource { generate :mdm_service_resource } 16 | 17 | factory :web_service do 18 | proto { 'tcp' } 19 | name { FactoryBot.generate(:web_service_name) } 20 | end 21 | end 22 | 23 | sequence(:mdm_service_name) { |n| 24 | "mdm_service_name#{n}" 25 | } 26 | 27 | sequence(:mdm_service_resource) { |n| 28 | { "mdm_service_resource#{n}".to_sym => "mdm_service_resource_value#{n}" } 29 | } 30 | 31 | sequence :mdm_service_proto, Mdm::Service::PROTOS.cycle 32 | 33 | port_bits = 16 34 | port_limit = 1 << port_bits 35 | 36 | sequence :port do |n| 37 | n % port_limit 38 | end 39 | 40 | web_service_names = ['http', 'https'] 41 | web_service_name_count = web_service_names.length 42 | 43 | sequence :web_service_name do |n| 44 | web_service_names[n % web_service_name_count] 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /app/models/mdm/exploited_host.rb: -------------------------------------------------------------------------------- 1 | # @deprecated use {Mdm::ExploitAttempt} instead. 2 | # 3 | # When a {#host} or {#service} on a {#host} is exploited. 4 | class Mdm::ExploitedHost < ApplicationRecord 5 | # 6 | # Associations 7 | # 8 | 9 | # The host that was exploited. 10 | belongs_to :host, 11 | class_name: 'Mdm::Host', 12 | inverse_of: :exploited_hosts 13 | 14 | # The service on {#host} that was exploited. 15 | belongs_to :service, 16 | class_name: 'Mdm::Service', 17 | inverse_of: :exploited_hosts 18 | 19 | # 20 | # Attributes 21 | # 22 | 23 | # @!attribute name 24 | # Name of exploit. 25 | # 26 | # @return [String] 27 | 28 | # @!attribute payload 29 | # {Mdm::Module::Class#full_name Full name of the payload module} used to exploit the {#host} or {#service} on 30 | # {#host}. 31 | # 32 | # @return [String] 33 | 34 | # @!attribute session_uuid 35 | # UUID of local session. 36 | # 37 | # @return [String] 38 | # @deprecated Sessions no longer have UUIDs. They have {Mdm::Session#local_id} that reflects the in-memory 39 | # Msf::Session ID and an in-database {Mdm::Session#id}. 40 | 41 | Metasploit::Concern.run(self) 42 | end 43 | -------------------------------------------------------------------------------- /app/models/mdm/wmap_target.rb: -------------------------------------------------------------------------------- 1 | # WMAP target. WMAP is a plugin to metasploit-framework. 2 | class Mdm::WmapTarget < ApplicationRecord 3 | # 4 | # Attributes 5 | # 6 | 7 | # @!attribute address 8 | # IP address of {#host}. 9 | # 10 | # @return [String] 11 | 12 | # @!attribute created_at 13 | # When this target was created. 14 | # 15 | # @return [DateTime] 16 | 17 | # @!attribute host 18 | # Name of this target. 19 | # 20 | # @return [String] 21 | 22 | # @!attribute port 23 | # Port on this target to send {Mdm::WmapRequest requests}. 24 | # 25 | # @return [Integer] 26 | 27 | # @!attribute selected 28 | # Whether this target should be sent requests. 29 | # 30 | # @return [Integer] 31 | 32 | # @!attribute ssl 33 | # Version of SSL to use when sending requests to this target. 34 | # 35 | # @return [Integer] 36 | 37 | # @!attribute updated_at 38 | # The last time this target was updated. 39 | # 40 | # @return [DateTime] 41 | 42 | # 43 | # Instance Methods 44 | # 45 | 46 | # @note Necessary to avoid coercion to an `IPAddr` object. 47 | # 48 | # The IP address for this target. 49 | # 50 | # @return [String] 51 | def address 52 | self[:address].to_s 53 | end 54 | 55 | Metasploit::Concern.run(self) 56 | end 57 | -------------------------------------------------------------------------------- /app/models/mdm/task_cred.rb: -------------------------------------------------------------------------------- 1 | # @deprecated {Mdm::Task} has and belongs to many `Metasploit::Credential::Cores` in `Mdm::Task#credential_cores` and 2 | # has and belongs to many `Metasploit::Credential::Logins` in `Mdm::Task#credential_logins` when the 3 | # `Metasploit::Credential::Engine` is installed. 4 | # 5 | # Join model between {Mdm::Cred} and {Mdm::Task} that signifies that the {#task} found the {#cred}. 6 | class Mdm::TaskCred < ApplicationRecord 7 | # 8 | # Associations 9 | # 10 | 11 | # The {Mdm::Cred} found by {#task}. 12 | belongs_to :cred, 13 | class_name: 'Mdm::Cred', 14 | inverse_of: :task_creds 15 | 16 | # An {Mdm::Task} that found {#cred}. 17 | belongs_to :task, 18 | class_name: 'Mdm::Task', 19 | inverse_of: :task_creds 20 | 21 | # 22 | # Attributes 23 | # 24 | 25 | # @!attribute [rw] created_at 26 | # When this task cred was created. 27 | # 28 | # @return [DateTime] 29 | 30 | # @!attribute [rw] updated_at 31 | # The last time this task cred was updated. 32 | # 33 | # @return [DateTime] 34 | 35 | # 36 | # Validations 37 | # 38 | 39 | validates :cred_id, 40 | :uniqueness => { 41 | :scope => :task_id 42 | } 43 | 44 | Metasploit::Concern.run(self) 45 | end 46 | -------------------------------------------------------------------------------- /app/models/mdm/service_link.rb: -------------------------------------------------------------------------------- 1 | # Join model between {Mdm::Service} and {Mdm::Service} for many-to-many self-referencing relationship 2 | class Mdm::ServiceLink < ApplicationRecord 3 | self.table_name = 'service_links' 4 | 5 | # 6 | # Associations 7 | # 8 | 9 | # Parent service 10 | belongs_to :parent, 11 | class_name: 'Mdm::Service', 12 | inverse_of: :child_links 13 | 14 | # Child service 15 | belongs_to :child, 16 | class_name: 'Mdm::Service', 17 | inverse_of: :parent_links 18 | 19 | # Destroy orphaned child when destroying a service link 20 | after_destroy :destroy_orphan_child 21 | 22 | # 23 | # Attributes 24 | # 25 | 26 | # @!attribute created_at 27 | # When this task service was created. 28 | # 29 | # @return [DateTime] 30 | 31 | # @!attribute updated_at 32 | # The last time this task service was updated. 33 | # 34 | # @return [DateTime] 35 | 36 | # 37 | # Validations 38 | # 39 | 40 | validates :parent_id, 41 | :uniqueness => { 42 | :scope => :child_id 43 | } 44 | 45 | def destroy_orphan_child 46 | Mdm::Service.where(id: child.id).first&.destroy_if_orphaned 47 | end 48 | private :destroy_orphan_child 49 | 50 | Metasploit::Concern.run(self) 51 | end 52 | 53 | -------------------------------------------------------------------------------- /app/models/mdm/profile.rb: -------------------------------------------------------------------------------- 1 | # User settings. 2 | class Mdm::Profile < ApplicationRecord 3 | # 4 | # Attributes 5 | # 6 | 7 | # @!attribute active 8 | # Whether this is the currently active profile. 9 | # 10 | # @return [true] if this is the active profile. 11 | # @return [false] if this profile is inactive and another profile is active. 12 | 13 | # @!attribute created_at 14 | # When this profile was created. 15 | # 16 | # @return [DateTime] 17 | 18 | # @!attribute name 19 | # Name of this profile to distinguish it from other profiles. 20 | # 21 | # @return [String] 22 | 23 | # @!attribute owner 24 | # Owner of this profile. 25 | # 26 | # @return [''] System-wide profile for all users. 27 | # @return [String] Name of user that uses this profile. 28 | 29 | # @!attribute updated_at 30 | # The last time this profile was updated. 31 | # 32 | # @return [DateTime] 33 | 34 | # 35 | # Serializations 36 | # 37 | 38 | # Global settings. 39 | # 40 | # @return [Hash] 41 | if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 42 | serialize :settings, coder: MetasploitDataModels::Base64Serializer.new 43 | else 44 | serialize :settings, MetasploitDataModels::Base64Serializer.new 45 | end 46 | 47 | Metasploit::Concern.run(self) 48 | end 49 | 50 | -------------------------------------------------------------------------------- /db/migrate/20120625000007_add_exploit_attempts.rb: -------------------------------------------------------------------------------- 1 | class AddExploitAttempts < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :exploit_attempts do |t| 5 | t.integer :host_id # Host table reference (primary) 6 | t.integer :service_id # Service table reference (optional) 7 | t.integer :vuln_id # Vuln table reference (optional) 8 | t.timestamp :attempted_at # Timestamp of when the session was opened or the module exited 9 | t.boolean :exploited # Whether or not the attempt succeeded 10 | t.string :fail_reason # Short string corresponding to a Msf::Exploit::Failure constant 11 | t.string :username # The user that tested this vulnerability 12 | t.text :module # The specific module name that was used 13 | t.integer :session_id # Database identifier of any opened session 14 | t.integer :loot_id # Database identifier of any 'proof' loot (for non-session exploits) 15 | t.integer :port # Port -> Services are created/destroyed frequently and failed 16 | t.string :proto # Protocol | attempts may be against closed ports. 17 | end 18 | 19 | add_column :hosts, :exploit_attempt_count, :integer, :default => 0 20 | end 21 | 22 | def self.down 23 | drop_table :exploit_attempts 24 | remove_column :hosts, :exploit_attempt_count 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20130515164311_change_web_vulns_confidence_to_integer.rb: -------------------------------------------------------------------------------- 1 | # Changes web_vulns.confidence from text to integer as it is populated with integers. 2 | class ChangeWebVulnsConfidenceToInteger < ActiveRecord::Migration[4.2] 3 | # 4 | # CONSTANTS 5 | # 6 | 7 | # Columns in {TABLE} whose type needs to be change. 8 | COLUMN = :confidence 9 | # The correct type for {COLUMN}. 10 | NEW_TYPE = :integer 11 | # The incorrect type for {COLUMN}. 12 | OLD_TYPE = :text 13 | # The table in which {COLUMN} is defined. 14 | TABLE = :web_vulns 15 | 16 | # 17 | # Methods 18 | # 19 | 20 | # Changes web_vulns.confidence back to text 21 | # 22 | # @return [void] 23 | def down 24 | alter_type(:to => OLD_TYPE) 25 | end 26 | 27 | # Changes web_vulns.confidence to integer 28 | # 29 | # @return [void] 30 | def up 31 | alter_type(:to => NEW_TYPE) 32 | end 33 | 34 | private 35 | 36 | # Alters {COLUMN} type in {TABLE} from old to new type 37 | # 38 | # @param options [Hash{Symbol => #to_s}] 39 | # @option options [#to_s] :from The old type name. 40 | # @option options [#to_s] :to The new type name. 41 | def alter_type(options={}) 42 | options.assert_valid_keys(:to) 43 | 44 | new = options.fetch(:to) 45 | 46 | execute "ALTER TABLE #{TABLE} ALTER COLUMN #{COLUMN} TYPE #{new} USING confidence::#{new}" 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /db/migrate/005_expand_info.rb: -------------------------------------------------------------------------------- 1 | class ExpandInfo < ActiveRecord::Migration[4.2] 2 | def self.up 3 | remove_column :events, :info 4 | change_table :events do |t| 5 | t.string :info, :limit => 4096 6 | end 7 | 8 | remove_column :notes, :data 9 | change_table :notes do |t| 10 | t.string :data, :limit => 4096 11 | end 12 | 13 | remove_column :vulns, :data 14 | change_table :vulns do |t| 15 | t.string :data, :limit => 4096 16 | end 17 | 18 | remove_column :hosts, :info 19 | change_table :hosts do |t| 20 | t.string :info, :limit => 4096 21 | end 22 | 23 | remove_column :services, :info 24 | change_table :services do |t| 25 | t.string :info, :limit => 4096 26 | end 27 | end 28 | 29 | def self.down 30 | 31 | remove_column :events, :info 32 | change_table :events do |t| 33 | t.string :info 34 | end 35 | 36 | remove_column :notes, :data 37 | change_table :notes do |t| 38 | t.string :data, :limit => 1024 39 | end 40 | 41 | remove_column :hosts, :info 42 | change_table :hosts do |t| 43 | t.string :info, :limit => 1024 44 | end 45 | 46 | remove_column :vulns, :data 47 | change_table :hosts do |t| 48 | t.string :data, :limit => 1024 49 | end 50 | 51 | remove_column :services, :info 52 | change_table :services do |t| 53 | t.string :info, :limit => 1024 54 | end 55 | 56 | end 57 | end 58 | 59 | -------------------------------------------------------------------------------- /spec/app/models/mdm/vuln_ref_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::VulnRef, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | context 'factories' do 5 | context 'mdm_vuln_ref' do 6 | subject(:mdm_vuln_ref) do 7 | FactoryBot.build(:mdm_vuln_ref) 8 | end 9 | 10 | it { is_expected.to be_valid } 11 | end 12 | end 13 | 14 | context 'database' do 15 | context 'columns' do 16 | it { is_expected.to have_db_column(:id).of_type(:integer) } 17 | it { is_expected.to have_db_column(:ref_id).of_type(:integer) } 18 | it { is_expected.to have_db_column(:vuln_id).of_type(:integer) } 19 | end 20 | end 21 | 22 | context 'associations' do 23 | it { is_expected.to belong_to(:vuln).class_name('Mdm::Vuln') } 24 | it { is_expected.to belong_to(:ref).class_name('Mdm::Ref') } 25 | end 26 | 27 | context 'factory' do 28 | it 'should be valid' do 29 | vuln_ref = FactoryBot.build(:mdm_vuln_ref) 30 | expect(vuln_ref).to be_valid 31 | end 32 | end 33 | 34 | context '#destroy' do 35 | it 'should successfully destroy the object' do 36 | vuln_ref = FactoryBot.create(:mdm_vuln_ref) 37 | expect { 38 | vuln_ref.destroy 39 | }.to_not raise_error 40 | expect { 41 | vuln_ref.reload 42 | }.to raise_error(ActiveRecord::RecordNotFound) 43 | end 44 | end 45 | 46 | end 47 | -------------------------------------------------------------------------------- /db/migrate/017_expand_info2.rb: -------------------------------------------------------------------------------- 1 | class ExpandInfo2 < ActiveRecord::Migration[4.2] 2 | def self.up 3 | remove_column :events, :info 4 | change_table :events do |t| 5 | t.string :info, :limit => 65536 6 | end 7 | 8 | remove_column :notes, :data 9 | change_table :notes do |t| 10 | t.string :data, :limit => 65536 11 | end 12 | 13 | remove_column :vulns, :data 14 | change_table :vulns do |t| 15 | t.string :data, :limit => 65536 16 | end 17 | 18 | remove_column :hosts, :info 19 | change_table :hosts do |t| 20 | t.string :info, :limit => 65536 21 | end 22 | 23 | remove_column :services, :info 24 | change_table :services do |t| 25 | t.string :info, :limit => 65536 26 | end 27 | end 28 | 29 | def self.down 30 | 31 | remove_column :events, :info 32 | change_table :events do |t| 33 | t.string :info 34 | end 35 | 36 | remove_column :notes, :data 37 | change_table :notes do |t| 38 | t.string :data, :limit => 4096 39 | end 40 | 41 | remove_column :hosts, :info 42 | change_table :hosts do |t| 43 | t.string :info, :limit => 4096 44 | end 45 | 46 | remove_column :vulns, :data 47 | change_table :vulns do |t| 48 | t.string :data, :limit => 4096 49 | end 50 | 51 | remove_column :services, :info 52 | change_table :services do |t| 53 | t.string :info, :limit => 4096 54 | end 55 | 56 | end 57 | end 58 | 59 | -------------------------------------------------------------------------------- /lib/metasploit_data_models.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Core 3 | # 4 | require 'shellwords' 5 | # So that Mdm::WebPage#cookie can support serializing a WEBrick::Cookie 6 | require 'webrick' 7 | 8 | # 9 | # Gems 10 | # 11 | # gems must load explicitly any gem declared in gemspec 12 | # @see https://github.com/bundler/bundler/issues/2018#issuecomment-6819359 13 | # 14 | # 15 | require 'active_record' 16 | require 'active_support' 17 | require 'active_support/all' 18 | require 'metasploit/concern' 19 | require 'metasploit/model' 20 | require 'arel-helpers' 21 | 22 | # 23 | # Project 24 | # 25 | 26 | require 'metasploit_data_models/version' 27 | 28 | autoload :Mdm, 'mdm' 29 | 30 | # Core database models for metasploit-framework. 31 | module MetasploitDataModels 32 | extend ActiveSupport::Autoload 33 | 34 | autoload :AutomaticExploitation 35 | autoload :Base64Serializer 36 | autoload :ChangeRequiredColumnsToNullFalse 37 | autoload :IPAddress 38 | autoload :Match 39 | autoload :ModuleRun 40 | autoload :Search 41 | autoload :SerializedPrefs 42 | autoload :YAML 43 | 44 | # The root directory of `metasploit_data_models` gem in both development and gem installs. 45 | # 46 | # @return [Pathname] 47 | def self.root 48 | unless instance_variable_defined? :@root 49 | lib_pathname = Pathname.new(__FILE__).dirname 50 | 51 | @root = lib_pathname.parent 52 | end 53 | 54 | @root 55 | end 56 | end 57 | 58 | -------------------------------------------------------------------------------- /spec/app/models/metasploit_data_models/search/visitor/method_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::Search::Visitor::Method, type: :model do 2 | subject(:visitor) do 3 | described_class.new 4 | end 5 | 6 | it_should_behave_like 'Metasploit::Concern.run' 7 | 8 | context '#visit' do 9 | subject(:visit) do 10 | visitor.visit(node) 11 | end 12 | 13 | let(:node) do 14 | node_class.new 15 | end 16 | 17 | context 'with Metasploit::Model::Search::Group::Intersection' do 18 | let(:node_class) do 19 | Metasploit::Model::Search::Group::Intersection 20 | end 21 | 22 | it { is_expected.to eq(:and) } 23 | end 24 | 25 | context 'with Metasploit::Model::Search::Operation::Group::Intersection' do 26 | let(:node_class) do 27 | Metasploit::Model::Search::Operation::Group::Intersection 28 | end 29 | 30 | it { is_expected.to eq(:and) } 31 | end 32 | 33 | context 'with Metasploit::Model::Search::Group::Union' do 34 | let(:node_class) do 35 | Metasploit::Model::Search::Group::Union 36 | end 37 | 38 | it { is_expected.to eq(:or) } 39 | end 40 | 41 | context 'with Metasploit::Model::Search::Operation::Group::Union' do 42 | let(:node_class) do 43 | Metasploit::Model::Search::Operation::Group::Union 44 | end 45 | 46 | it { is_expected.to eq(:or) } 47 | end 48 | end 49 | end -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/operation/range.rb: -------------------------------------------------------------------------------- 1 | # Search operation on a `Range`. 2 | class MetasploitDataModels::Search::Operation::Range < Metasploit::Model::Search::Operation::Base 3 | # 4 | # CONSTANTS 5 | # 6 | 7 | # Separates beginning from end of the range. 8 | SEPARATOR = '-' 9 | 10 | # 11 | # Validation 12 | # 13 | 14 | validate :ordered 15 | validate :range 16 | 17 | # 18 | # Instance Methods 19 | # 20 | 21 | # Sets `#value` to a `Range` composed by separating `formatted_value` by `-`. 22 | # 23 | # @param formatted_value [#to_s] 24 | # @return [Range] 25 | def value=(formatted_value) 26 | range_arguments = formatted_value.to_s.split(SEPARATOR, 2) 27 | 28 | begin 29 | @value = Range.new(*range_arguments) 30 | rescue ArgumentError 31 | @value = formatted_value 32 | end 33 | 34 | @value 35 | end 36 | 37 | private 38 | 39 | # Validates that `#value` is a `Range` with `Range#begin` less than or equal to `Range#begin` 40 | # 41 | # @return [void] 42 | def ordered 43 | if value.is_a?(Range) && value.begin > value.end 44 | errors.add(:value, :order, begin: value.begin.inspect, end: value.end.inspect) 45 | end 46 | end 47 | 48 | # Validates that `#value` is a `Range` 49 | # 50 | # @return [void] 51 | def range 52 | unless value.is_a? Range 53 | errors.add(:value, :range) 54 | end 55 | end 56 | end -------------------------------------------------------------------------------- /lib/metasploit_data_models/engine.rb: -------------------------------------------------------------------------------- 1 | require 'rails' 2 | 3 | # `Rails::Engine` that exposes MetasploitDataModel's `ApplicationRecord` subclasses and automatically loads its 4 | # `FactoryBot` factories, sequences, and traits. 5 | class MetasploitDataModels::Engine < Rails::Engine 6 | # @see http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl 7 | config.generators do |g| 8 | g.fixture_replacement :factory_bot, :dir => 'spec/factories' 9 | g.helper false 10 | g.test_framework :rspec, :fixture => false 11 | end 12 | 13 | # Remove ActiveSupport::Dependencies loading paths to save time during constant resolution and to ensure that 14 | # metasploit_data_models is properly declaring all autoloads and not falling back on ActiveSupport::Dependencies 15 | config.paths.values.each do |path| 16 | path.skip_autoload! 17 | path.skip_autoload_once! 18 | path.skip_eager_load! 19 | path.skip_load_path! 20 | end 21 | 22 | initializer 'metasploit_data_models.prepend_factory_path', :after => 'factory_bot.set_factory_paths' do 23 | if defined? FactoryBot 24 | relative_definition_file_path = config.generators.options[:factory_bot][:dir] 25 | definition_file_path = root.join(relative_definition_file_path) 26 | 27 | # unshift so that Pro can modify mdm factories 28 | FactoryBot.definition_file_paths.unshift definition_file_path 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/app/models/mdm/client_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Client, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:host).class_name('Mdm::Host') } 7 | end 8 | 9 | context '#destroy' do 10 | it 'should successfully destroy the object' do 11 | client = FactoryBot.create(:mdm_client, :ua_string => 'user-agent') 12 | expect { 13 | client.destroy 14 | }.to_not raise_error 15 | expect { 16 | client.reload 17 | }.to raise_error(ActiveRecord::RecordNotFound) 18 | end 19 | end 20 | 21 | context 'factory' do 22 | it 'should be valid' do 23 | client = FactoryBot.build(:mdm_client) 24 | expect(client).to be_valid 25 | end 26 | end 27 | 28 | context 'database' do 29 | context 'columns' do 30 | it { is_expected.to have_db_column(:host_id).of_type(:integer)} 31 | it { is_expected.to have_db_column(:ua_string).of_type(:string).with_options(:null => false) } 32 | it { is_expected.to have_db_column(:ua_name).of_type(:string) } 33 | it { is_expected.to have_db_column(:ua_ver).of_type(:string) } 34 | end 35 | 36 | context 'timestamps' do 37 | it { is_expected.to have_db_column(:created_at).of_type(:datetime) } 38 | it { is_expected.to have_db_column(:updated_at).of_type(:datetime) } 39 | end 40 | 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /app/models/mdm/web_form.rb: -------------------------------------------------------------------------------- 1 | # A filled-in form on a {#web_site}. 2 | class Mdm::WebForm < ApplicationRecord 3 | 4 | # 5 | # Associations 6 | # 7 | 8 | # {Mdm::WebSite Web site} on which this form is. 9 | belongs_to :web_site, 10 | class_name: 'Mdm::WebSite', 11 | inverse_of: :web_forms 12 | 13 | # 14 | # Attributes 15 | # 16 | 17 | # @!attribute created_at 18 | # When this web form was created. 19 | # 20 | # @return [DateTime] 21 | 22 | # @!attribute method 23 | # HTTP method (or verb) used to submitted this form, such as GET or POST. 24 | # 25 | # @return [String] 26 | 27 | # @!attribute path 28 | # Path portion of URL to which this form was submitted. 29 | # 30 | # @return [String] 31 | 32 | # @!attribute query 33 | # URL query that submitted for this form. 34 | # 35 | # @return [String] 36 | 37 | # @!attribute updated_at 38 | # The last time this web form was updated. 39 | # 40 | # @return [DateTime] 41 | 42 | # 43 | # Serializations 44 | # 45 | 46 | # Parameters submitted in this form. 47 | # 48 | # @return [Array>] 49 | if ActiveRecord::VERSION::MAJOR >= 7 && ActiveRecord::VERSION::MINOR >= 1 50 | serialize :params, coder: MetasploitDataModels::Base64Serializer.new 51 | else 52 | serialize :params, MetasploitDataModels::Base64Serializer.new 53 | end 54 | 55 | Metasploit::Concern.run(self) 56 | end 57 | 58 | -------------------------------------------------------------------------------- /db/migrate/20120625000000_add_vuln_details.rb: -------------------------------------------------------------------------------- 1 | class AddVulnDetails < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :vuln_details do |t| 5 | t.integer :vuln_id # Vuln table reference 6 | t.float :cvss_score # 0.0 to 10.0 7 | t.string :cvss_vector # Ex: (AV:N/AC:L/Au:N/C:C/I:C/A:C)(AV:N/AC:L/Au:N/C:C/I:C/A:C) 8 | 9 | t.string :title # Short identifier 10 | t.text :description # Plain text or HTML (trusted) 11 | t.text :solution # Plain text or HTML (trusted) 12 | t.binary :proof # Should be UTF-8, but may not be, sanitize on output 13 | # Technically this duplicates vuln.info, but that field 14 | # is poorly managed / handled today. Eventually we will 15 | # replace vuln.info 16 | 17 | # Nexpose-specific fields 18 | t.integer :nx_console_id # NexposeConsole table reference 19 | t.integer :nx_device_id # Reference from the Nexpose side 20 | t.string :nx_vuln_id # 'jre-java-update-flaw' 21 | t.float :nx_severity # 0-10 22 | t.float :nx_pci_severity # 0-10 23 | t.timestamp :nx_published # Normalized from "20081205T000000000" 24 | t.timestamp :nx_added # Normalized from "20081205T000000000" 25 | t.timestamp :nx_modified # Normalized from "20081205T000000000" 26 | t.text :nx_tags # Comma separated 27 | 28 | end 29 | end 30 | 31 | def self.down 32 | drop_table :vuln_details 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/models/metasploit_data_models/search/visitor/includes.rb: -------------------------------------------------------------------------------- 1 | # Gathers all the association names to pass to `ActiveRecord::Relation#includes` from a 2 | # `Metasploit::Model::Search::Query` 3 | class MetasploitDataModels::Search::Visitor::Includes 4 | include Metasploit::Model::Visitation::Visit 5 | 6 | # 7 | # Visitors 8 | # 9 | 10 | visit 'Metasploit::Model::Search::Group::Base', 11 | 'Metasploit::Model::Search::Operation::Group::Base' do |parent| 12 | parent.children.flat_map { |child| 13 | visit child 14 | } 15 | end 16 | 17 | visit 'Metasploit::Model::Search::Operation::Association' do |operation| 18 | association = visit operation.operator 19 | nested_associations = visit operation.source_operation 20 | 21 | if nested_associations.empty? 22 | [association] 23 | else 24 | [ 25 | { 26 | association => nested_associations 27 | } 28 | ] 29 | end 30 | end 31 | 32 | visit 'Metasploit::Model::Search::Operation::Base' do |operation| 33 | visit operation.operator 34 | end 35 | 36 | visit 'Metasploit::Model::Search::Operator::Association' do |operator| 37 | operator.association 38 | end 39 | 40 | visit 'Metasploit::Model::Search::Operator::Attribute', 41 | 'MetasploitDataModels::Search::Operator::IPAddress', 42 | 'MetasploitDataModels::Search::Operator::Port::List' do |_operator| 43 | [] 44 | end 45 | 46 | Metasploit::Concern.run(self) 47 | end 48 | -------------------------------------------------------------------------------- /spec/app/models/mdm/session_event_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::SessionEvent, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | context 'associations' do 5 | it { is_expected.to belong_to(:session).class_name('Mdm::Session') } 6 | end 7 | 8 | context 'factory' do 9 | it 'should be valid' do 10 | session_event = FactoryBot.build(:mdm_session_event) 11 | expect(session_event).to be_valid 12 | end 13 | end 14 | 15 | context '#destroy' do 16 | it 'should successfully destroy the object' do 17 | session_event = FactoryBot.create(:mdm_session_event) 18 | expect { 19 | session_event.destroy 20 | }.to_not raise_error 21 | expect { 22 | session_event.reload 23 | }.to raise_error(ActiveRecord::RecordNotFound) 24 | end 25 | end 26 | 27 | context 'database' do 28 | context 'timestamps'do 29 | it { is_expected.to have_db_column(:created_at).of_type(:datetime) } 30 | end 31 | 32 | context 'columns' do 33 | it { is_expected.to have_db_column(:session_id).of_type(:integer) } 34 | it { is_expected.to have_db_column(:etype).of_type(:string) } 35 | it { is_expected.to have_db_column(:command).of_type(:binary) } 36 | it { is_expected.to have_db_column(:output).of_type(:binary) } 37 | it { is_expected.to have_db_column(:remote_path).of_type(:string) } 38 | it { is_expected.to have_db_column(:local_path).of_type(:string) } 39 | end 40 | end 41 | 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/20101001000000_add_web_tables.rb: -------------------------------------------------------------------------------- 1 | class AddWebTables < ActiveRecord::Migration[4.2] 2 | 3 | def self.up 4 | create_table :web_sites do |t| 5 | t.integer :service_id, :null => false 6 | t.timestamps null: false 7 | t.string :vhost, :limit => 2048 8 | t.text :comments 9 | t.text :options 10 | end 11 | 12 | create_table :web_pages do |t| 13 | t.integer :web_site_id, :null => false 14 | t.timestamps null: false 15 | t.text :path 16 | t.text :query 17 | t.integer :code, :null => false 18 | t.text :cookie 19 | t.text :auth 20 | t.text :ctype 21 | t.timestamp :mtime 22 | t.text :location 23 | t.text :body 24 | t.text :headers 25 | end 26 | 27 | create_table :web_forms do |t| 28 | t.integer :web_site_id, :null => false 29 | t.timestamps null: false 30 | t.text :path 31 | t.string :method, :limit => 1024 32 | t.text :params 33 | end 34 | 35 | create_table :web_vulns do |t| 36 | t.integer :web_site_id, :null => false 37 | t.timestamps null: false 38 | t.text :path 39 | t.string :method, :limit => 1024 40 | t.text :params 41 | t.text :pname 42 | t.text :proof 43 | t.integer :risk 44 | t.string :name, :limit => 1024 45 | end 46 | 47 | end 48 | 49 | def self.down 50 | drop_table :web_sites 51 | drop_table :web_pages 52 | drop_table :web_forms 53 | drop_table :web_vulns 54 | end 55 | end 56 | 57 | 58 | -------------------------------------------------------------------------------- /spec/lib/metasploit_data_models/match/child_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::Match::Child do 2 | let(:extending_class) { 3 | # capture as local for Class.new block scope 4 | described_class = self.described_class 5 | 6 | Class.new(Metasploit::Model::Base) { 7 | extend described_class 8 | 9 | # 10 | # Attributes 11 | # 12 | 13 | # @!attribute value 14 | # @return [String] 15 | attr_accessor :value 16 | } 17 | } 18 | 19 | before(:example) do 20 | stub_const('ExtendingClass', extending_class) 21 | stub_const('ExtendingClass::REGEXP', /\d+-\d+/) 22 | end 23 | 24 | context '#match' do 25 | subject(:match) { 26 | extending_class.match(formatted_value) 27 | } 28 | 29 | context 'formatted value' do 30 | context 'with matching' do 31 | let(:formatted_value) { 32 | '1-2' 33 | } 34 | 35 | it 'returns instance of extending class' do 36 | expect(match).to be_an extending_class 37 | end 38 | 39 | context '#value' do 40 | subject(:value) { 41 | match.value 42 | } 43 | 44 | it 'is set to formatted value' do 45 | expect(value).to eq(formatted_value) 46 | end 47 | end 48 | end 49 | 50 | context 'without matching' do 51 | let(:formatted_value) do 52 | '1,2-3' 53 | end 54 | 55 | it { is_expected.to be_nil } 56 | end 57 | end 58 | end 59 | end -------------------------------------------------------------------------------- /db/migrate/20150317145455_rename_module_indices.rb: -------------------------------------------------------------------------------- 1 | class RenameModuleIndices < ActiveRecord::Migration[4.2] 2 | def change 3 | # This migration will only need to be run if the indices were originally 4 | # generated before Rails 4. Fresh builds can safely skip this. 5 | return if ApplicationRecord.connection.indexes(:module_actions).first.name != 'index_module_actions_on_module_detail_id' 6 | 7 | rename_index :module_actions, 8 | 'index_module_actions_on_module_detail_id', 9 | 'index_module_actions_on_detail_id' 10 | rename_index :module_archs, 11 | 'index_module_archs_on_module_detail_id', 12 | 'index_module_archs_on_detail_id' 13 | rename_index :module_authors, 14 | 'index_module_authors_on_module_detail_id', 15 | 'index_module_authors_on_detail_id' 16 | rename_index :module_mixins, 17 | 'index_module_mixins_on_module_detail_id', 18 | 'index_module_mixins_on_detail_id' 19 | rename_index :module_platforms, 20 | 'index_module_platforms_on_module_detail_id', 21 | 'index_module_platforms_on_detail_id' 22 | rename_index :module_refs, 23 | 'index_module_refs_on_module_detail_id', 24 | 'index_module_refs_on_detail_id' 25 | rename_index :module_targets, 26 | 'index_module_targets_on_module_detail_id', 27 | 'index_module_targets_on_detail_id' 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/app/models/metasploit_data_models/automatic_exploitation/match_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe MetasploitDataModels::AutomaticExploitation::Match, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | describe "associations" do 5 | describe "connecting to a Mdm::Module::Detail" do 6 | let(:vuln){ FactoryBot.create(:mdm_vuln) } 7 | let(:module_detail){FactoryBot.create(:mdm_module_detail)} 8 | 9 | subject(:automatic_exploitation_match){ described_class.new } 10 | 11 | before(:example) do 12 | automatic_exploitation_match.matchable = vuln 13 | automatic_exploitation_match.module_fullname = module_detail.fullname 14 | automatic_exploitation_match.save! 15 | end 16 | 17 | it 'should point to the Mdm::Module::Detail with a fullname corresponding to #module_fullname' do 18 | expect(automatic_exploitation_match.module_detail).to eq(module_detail) 19 | end 20 | end 21 | 22 | describe "deleting the associated Mdm::Module::Detail" do 23 | subject(:automatic_exploitation_match){ FactoryBot.create(:automatic_exploitation_match) } 24 | let(:match_id){ automatic_exploitation_match.id } 25 | 26 | before(:example) do 27 | automatic_exploitation_match.module_detail.destroy 28 | end 29 | 30 | it 'should still exist in the DB' do 31 | the_match = MetasploitDataModels::AutomaticExploitation::Match.find(match_id) 32 | expect(the_match).to_not be_blank 33 | end 34 | end 35 | 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/app/models/mdm/module/author_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::Module::Author, type: :model do 2 | 3 | it_should_behave_like 'Metasploit::Concern.run' 4 | 5 | context 'associations' do 6 | it { is_expected.to belong_to(:detail).class_name('Mdm::Module::Detail') } 7 | end 8 | 9 | context 'database' do 10 | context 'columns' do 11 | it { is_expected.to have_db_column(:detail_id).of_type(:integer) } 12 | it { is_expected.to have_db_column(:name).of_type(:text) } 13 | it { is_expected.to have_db_column(:email).of_type(:text) } 14 | end 15 | 16 | context 'indices' do 17 | it { is_expected.to have_db_index(:detail_id) } 18 | end 19 | end 20 | 21 | context 'factories' do 22 | context 'full_mdm_module_author' do 23 | subject(:full_mdm_module_author) do 24 | FactoryBot.build :full_mdm_module_author 25 | end 26 | 27 | it { is_expected.to be_valid } 28 | 29 | context 'email' do 30 | subject(:email) { 31 | full_mdm_module_author.email 32 | } 33 | 34 | it { is_expected.not_to be_nil } 35 | end 36 | end 37 | 38 | context 'mdm_module_author' do 39 | subject(:mdm_module_author) do 40 | FactoryBot.build :mdm_module_author 41 | end 42 | 43 | it { is_expected.to be_valid } 44 | end 45 | end 46 | 47 | context 'validations' do 48 | it { is_expected.to validate_presence_of(:detail) } 49 | it { is_expected.not_to validate_presence_of(:email) } 50 | it { is_expected.to validate_presence_of(:name) } 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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. 28 | -------------------------------------------------------------------------------- /lib/mdm.rb: -------------------------------------------------------------------------------- 1 | # Namespace for models 2 | module Mdm 3 | extend ActiveSupport::Autoload 4 | 5 | autoload :ApiKey 6 | autoload :AsyncCallback 7 | autoload :Client 8 | autoload :Cred 9 | autoload :Event 10 | autoload :ExploitAttempt 11 | autoload :ExploitedHost 12 | autoload :Host 13 | autoload :HostDetail 14 | autoload :HostTag 15 | autoload :Listener 16 | autoload :Loot 17 | autoload :Macro 18 | autoload :ModRef 19 | autoload :Module 20 | autoload :NexposeConsole 21 | autoload :Note 22 | autoload :Payload 23 | autoload :Profile 24 | autoload :Ref 25 | autoload :Route 26 | autoload :Service 27 | autoload :Session 28 | autoload :SessionEvent 29 | autoload :Tag 30 | autoload :Task 31 | autoload :TaskCred 32 | autoload :TaskHost 33 | autoload :TaskService 34 | autoload :TaskSession 35 | autoload :User 36 | autoload :Vuln 37 | autoload :VulnAttempt 38 | autoload :VulnDetail 39 | autoload :VulnRef 40 | autoload :WebForm 41 | autoload :WebPage 42 | autoload :WebSite 43 | autoload :WebVuln 44 | autoload :WmapRequest 45 | autoload :WmapTarget 46 | autoload :Workspace 47 | autoload :ServiceLink 48 | 49 | # Causes the model_name for all Mdm modules to not include the Mdm:: prefix in their name. 50 | # 51 | # This has been supported since ActiveSupport 3.2.1. In ActiveSupport 3.1.0, it checked for _railtie. Before that 52 | # there was no way to do relative naming without manually overriding model_name in each class. 53 | # 54 | # @return [true] 55 | def self.use_relative_model_naming? 56 | true 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/support/shared/examples/metasploit_data_models/search/visitor/where/visit/with_metasploit_model_search_group_base.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_examples_for 'MetasploitDataModels::Search::Visitor::Where#visit with Metasploit::Model::Search*::Group::Base' do |options={}| 2 | options.assert_valid_keys(:arel_class) 3 | 4 | arel_class = options.fetch(:arel_class) 5 | 6 | let(:children) do 7 | 2.times.collect { |n| 8 | double("Group Child #{n}") 9 | } 10 | end 11 | 12 | let(:node) do 13 | node_class.new( 14 | :children => children 15 | ) 16 | end 17 | 18 | it 'should visit each child' do 19 | expect(visitor).to receive(:visit).with(node).and_call_original 20 | 21 | children.each do |child| 22 | expect(visitor).to receive(:visit).with(child).and_return(Arel::Nodes::Equality.new(1, 1)) 23 | end 24 | 25 | visit 26 | end 27 | 28 | it "should combine children AREL with #{arel_class}" do 29 | allow(visitor).to receive(:visit).with(node).and_call_original 30 | child_visits = [] 31 | 32 | children.each_with_index do |child, i| 33 | child_visit = Arel::Nodes::Equality.new(i, i) 34 | allow(visitor).to receive(:visit).with(child).and_return(child_visit) 35 | child_visits << child_visit 36 | end 37 | 38 | root = visit 39 | 40 | if root.is_a? Arel::Nodes::Grouping 41 | arel_pair = root.expr 42 | else 43 | arel_pair = root 44 | end 45 | 46 | expect(arel_pair).to be_a arel_class 47 | 48 | expect(arel_pair.left).to eq(child_visits[0]) 49 | expect(arel_pair.right).to eq(child_visits[1]) 50 | end 51 | end -------------------------------------------------------------------------------- /spec/app/models/mdm/web_form_spec.rb: -------------------------------------------------------------------------------- 1 | RSpec.describe Mdm::WebForm, type: :model do 2 | it_should_behave_like 'Metasploit::Concern.run' 3 | 4 | context 'associations' do 5 | it { is_expected.to belong_to(:web_site).class_name('Mdm::WebSite') } 6 | end 7 | 8 | context 'database' do 9 | 10 | context 'timestamps'do 11 | it { is_expected.to have_db_column(:created_at).of_type(:datetime).with_options(:null => false) } 12 | it { is_expected.to have_db_column(:updated_at).of_type(:datetime).with_options(:null => false) } 13 | end 14 | 15 | context 'columns' do 16 | it { is_expected.to have_db_column(:web_site_id).of_type(:integer).with_options(:null => false) } 17 | it { is_expected.to have_db_column(:path).of_type(:text) } 18 | it { is_expected.to have_db_column(:method).of_type(:string) } 19 | it { is_expected.to have_db_column(:params).of_type(:text) } 20 | it { is_expected.to have_db_column(:query).of_type(:text) } 21 | end 22 | 23 | context 'indices' do 24 | it { is_expected.to have_db_index(:path) } 25 | end 26 | end 27 | 28 | context 'factory' do 29 | it 'should be valid' do 30 | web_form = FactoryBot.build(:mdm_web_form) 31 | expect(web_form).to be_valid 32 | end 33 | end 34 | 35 | context '#destroy' do 36 | it 'should successfully destroy the object' do 37 | web_form = FactoryBot.create(:mdm_web_form) 38 | expect { 39 | web_form.destroy 40 | }.to_not raise_error 41 | expect { 42 | web_form.reload 43 | }.to raise_error(ActiveRecord::RecordNotFound) 44 | end 45 | end 46 | end 47 | --------------------------------------------------------------------------------