├── 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 |
--------------------------------------------------------------------------------