diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index c09959ee..9367da2b 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,5 +1,21 @@ name: Verify +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions +permissions: + actions: none + checks: none + contents: none + deployments: none + id-token: none + issues: none + discussions: none + packages: none + pages: none + pull-requests: none + repository-projects: none + security-events: none + statuses: none + on: push: branches: @@ -10,7 +26,7 @@ on: jobs: test: - runs-on: ubuntu-18.04 + runs-on: ${{ matrix.os }} timeout-minutes: 40 services: @@ -34,11 +50,18 @@ jobs: - 2.7 - 3.0 - 3.1 + os: + - ubuntu-18.04 + - ubuntu-22.04 + exclude: + - { os: ubuntu-22.04, ruby: 2.6 } + - { os: ubuntu-22.04, ruby: 2.7 } + - { os: ubuntu-22.04, ruby: 3.0 } env: RAILS_ENV: test - name: Ruby ${{ matrix.ruby }} + name: ${{ matrix.os }} - Ruby ${{ matrix.ruby }} steps: - name: Install system dependencies run: sudo apt-get install libpcap-dev graphviz diff --git a/Gemfile b/Gemfile index e8e89374..19530ba0 100755 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,6 @@ source "https://rubygems.org" # Specify your gem's dependencies in metasploit_data_models.gemspec gemspec - group :development do #gem 'metasploit-erd' # embed ERDs on index, namespace Module and Class pages @@ -13,7 +12,7 @@ end # used by dummy application group :development, :test do # Upload coverage reports to coveralls.io - gem 'coveralls', require: false + gem 'coveralls', require: false # supplies factories for producing model instance for specs # Version 4.1.0 or newer is needed to support generate calls without the 'FactoryBot.' in factory definitions syntax. gem 'factory_bot' @@ -21,6 +20,8 @@ group :development, :test do gem 'factory_bot_rails' gem 'rails', '~> 6.0' + gem 'net-smtp', require: false + # Used to create fake data gem "faker" diff --git a/app/models/mdm/web_page.rb b/app/models/mdm/web_page.rb index 69ed3847..45dd6210 100755 --- a/app/models/mdm/web_page.rb +++ b/app/models/mdm/web_page.rb @@ -1,6 +1,6 @@ # Web page requested from a {#web_site}. class Mdm::WebPage < ApplicationRecord - + # # Associations # diff --git a/lib/metasploit_data_models.rb b/lib/metasploit_data_models.rb index 42dc4443..93d0ab49 100755 --- a/lib/metasploit_data_models.rb +++ b/lib/metasploit_data_models.rb @@ -39,6 +39,7 @@ module MetasploitDataModels autoload :ModuleRun autoload :Search autoload :SerializedPrefs + autoload :YAML # The root directory of `metasploit_data_models` gem in both development and gem installs. # diff --git a/lib/metasploit_data_models/base64_serializer.rb b/lib/metasploit_data_models/base64_serializer.rb index 7093ea64..4d62c55e 100755 --- a/lib/metasploit_data_models/base64_serializer.rb +++ b/lib/metasploit_data_models/base64_serializer.rb @@ -27,7 +27,7 @@ class MetasploitDataModels::Base64Serializer }, lambda { |serialized| # Support legacy YAML encoding for existing data - YAML.load(serialized) + YAML.safe_load(serialized, permitted_classes: Rails.application.config.active_record.yaml_column_permitted_classes) }, lambda { |serialized| # Fall back to string decoding diff --git a/lib/metasploit_data_models/serialized_prefs.rb b/lib/metasploit_data_models/serialized_prefs.rb index e92c89b1..0ff766ac 100755 --- a/lib/metasploit_data_models/serialized_prefs.rb +++ b/lib/metasploit_data_models/serialized_prefs.rb @@ -24,4 +24,4 @@ def #{method_name}=(value) class_eval method_declarations, __FILE__, __LINE__ end end -end \ No newline at end of file +end diff --git a/lib/metasploit_data_models/yaml.rb b/lib/metasploit_data_models/yaml.rb new file mode 100644 index 00000000..84c2d482 --- /dev/null +++ b/lib/metasploit_data_models/yaml.rb @@ -0,0 +1,31 @@ +# Namespace for YAML configuration +class MetasploitDataModels::YAML + # + # CONSTANTS + # + + # List of supported classes when deserializing YAML classes + # See: https://discuss.rubyonrails.org/t/cve-2022-32224-possible-rce-escalation-bug-with-serialized-columns-in-active-record/81017 + # + PERMITTED_CLASSES = [ + Range, + Set, + Symbol, + Time, + 'WEBrick::Cookie'.to_sym, + 'ActionController::Parameters'.to_sym, + 'ActiveModel::Attribute::FromDatabase'.to_sym, + 'ActiveModel::Attribute::FromUser'.to_sym, + 'ActiveModel::Attribute::WithCastValue'.to_sym, + 'ActiveModel::Type::Boolean'.to_sym, + 'ActiveModel::Type::Integer'.to_sym, + 'ActiveModel::Type::String'.to_sym, + 'ActiveRecord::Coders::JSON'.to_sym, + 'ActiveSupport::TimeWithZone'.to_sym, + 'ActiveSupport::TimeZone'.to_sym, + 'ActiveRecord::Type::Serialized'.to_sym, + 'ActiveRecord::Type::Text'.to_sym, + 'ActiveSupport::HashWithIndifferentAccess'.to_sym, + 'Mdm::Workspace'.to_sym + ].freeze +end diff --git a/metasploit_data_models.gemspec b/metasploit_data_models.gemspec index 9e07ade6..7bada57d 100644 --- a/metasploit_data_models.gemspec +++ b/metasploit_data_models.gemspec @@ -41,7 +41,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'webrick' # os fingerprinting - s.add_runtime_dependency 'recog', '~> 2.0' + s.add_runtime_dependency 'recog' # arel-helpers: Useful tools to help construct database queries with ActiveRecord and Arel. s.add_runtime_dependency 'arel-helpers' diff --git a/spec/app/models/mdm/host_spec.rb b/spec/app/models/mdm/host_spec.rb index e3624fda..58216152 100644 --- a/spec/app/models/mdm/host_spec.rb +++ b/spec/app/models/mdm/host_spec.rb @@ -547,14 +547,14 @@ def search_for(str) it "when the string contains 'ppc'" do expect(host.send(:get_arch_from_string, 'blahppcblah')).to eq('PowerPC') end - end - context 'should return nil' do it 'when PowerPC is cased incorrectly' do - expect(host.send(:get_arch_from_string, 'powerPC')).to eq(nil) - expect(host.send(:get_arch_from_string, 'Powerpc')).to eq(nil) + expect(host.send(:get_arch_from_string, 'powerPC')).to eq('PowerPC') + expect(host.send(:get_arch_from_string, 'Powerpc')).to eq('PowerPC') end + end + context 'should return nil' do it 'when no recognized arch string is present' do expect(host.send(:get_arch_from_string, 'blahblah')).to eq(nil) end diff --git a/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb b/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb index b85673e0..4f3a9cbc 100644 --- a/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb +++ b/spec/app/models/metasploit_data_models/ip_address/v4/range_spec.rb @@ -185,7 +185,7 @@ end context '#to_s' do - subject(:to_s) { + subject(:to_s_result) { range.to_s } @@ -195,7 +195,7 @@ } it 'equals the original formatted value' do - expect(to_s).to eq(formatted_value) + expect(to_s_result).to eq(formatted_value) end end @@ -295,4 +295,4 @@ it { is_expected.not_to be_a Range } end end -end \ No newline at end of file +end diff --git a/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb b/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb index 4d51547d..c0aaa41b 100644 --- a/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb +++ b/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/list_spec.rb @@ -135,7 +135,7 @@ end context '#to_s' do - subject(:to_s) do + subject(:to_s_value) do nmap.to_s end @@ -145,7 +145,7 @@ } it 'returns a string equal to the original formatted value' do - expect(to_s).to eq(formatted_value) + expect(to_s_value).to eq(formatted_value) end end @@ -155,7 +155,7 @@ } it 'returned the formatted value as a string' do - expect(to_s).to eq(formatted_value.to_s) + expect(to_s_value).to eq(formatted_value.to_s) end end end @@ -273,4 +273,4 @@ end end end -end \ No newline at end of file +end diff --git a/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb b/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb index 371ab6c0..6c99fb8d 100644 --- a/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb +++ b/spec/app/models/metasploit_data_models/ip_address/v4/segment/nmap/range_spec.rb @@ -185,7 +185,7 @@ end context '#to_s' do - subject(:to_s) { + subject(:to_s_result) { range.to_s } @@ -195,7 +195,7 @@ } it 'equals the original formatted value' do - expect(to_s).to eq(formatted_value) + expect(to_s_result).to eq(formatted_value) end end @@ -299,4 +299,4 @@ it { is_expected.not_to be_a Range } end end -end \ No newline at end of file +end diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index f893631f..4d425080 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -39,13 +39,15 @@ class Application < Rails::Application # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] - + # Raise deprecations as errors config.active_support.deprecation = :raise # Enable escaping HTML in JSON. config.active_support.escape_html_entities_in_json = true + config.active_record.yaml_column_permitted_classes = MetasploitDataModels::YAML::PERMITTED_CLASSES + # Use SQL instead of Active Record's schema dumper when creating the database. # This is necessary if your schema can't be completely dumped by the schema dumper, # like if you have constraints or database-specific column types