contrast-agent 6.6.5 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.gitmodules +0 -3
- data/ext/cs__scope/cs__scope.c +1 -1
- data/lib/contrast/agent/assess/contrast_event.rb +2 -24
- data/lib/contrast/agent/assess/events/source_event.rb +7 -61
- data/lib/contrast/agent/assess/finalizers/hash.rb +11 -0
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +0 -55
- data/lib/contrast/agent/assess/policy/policy_node.rb +3 -3
- data/lib/contrast/agent/assess/policy/policy_node_utils.rb +0 -1
- data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
- data/lib/contrast/agent/assess/policy/source_method.rb +24 -1
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -5
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +6 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +36 -132
- data/lib/contrast/agent/assess/policy/trigger_node.rb +3 -3
- data/lib/contrast/agent/assess/property/evented.rb +2 -12
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +42 -84
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -27
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +1 -3
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +77 -62
- data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +6 -1
- data/lib/contrast/agent/assess/rule/response/header_rule.rb +5 -5
- data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +1 -7
- data/lib/contrast/agent/excluder.rb +206 -0
- data/lib/contrast/agent/exclusion_matcher.rb +6 -0
- data/lib/contrast/agent/inventory/database_config.rb +6 -10
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +4 -0
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -0
- data/lib/contrast/agent/protect/rule/base.rb +49 -5
- data/lib/contrast/agent/protect/rule/base_service.rb +1 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -105
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +129 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +169 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +2 -1
- data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +51 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +67 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +6 -31
- data/lib/contrast/agent/protect/rule/xxe.rb +2 -0
- data/lib/contrast/agent/protect/rule.rb +3 -1
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +6 -0
- data/lib/contrast/agent/reporting/details/sqli_dangerous_functions.rb +22 -0
- data/lib/contrast/agent/reporting/reporter.rb +1 -2
- data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -4
- data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -23
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +19 -49
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +12 -9
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +23 -21
- data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +5 -18
- data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +1 -0
- data/lib/contrast/{api/decorators/trace_taint_range_tags.rb → agent/reporting/reporting_events/finding_event_taint_range_tags.rb} +7 -6
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -14
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +11 -0
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +3 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +11 -23
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +8 -26
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -7
- data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +3 -3
- data/lib/contrast/agent/request.rb +2 -2
- data/lib/contrast/agent/request_context.rb +8 -20
- data/lib/contrast/agent/request_context_extend.rb +15 -36
- data/lib/contrast/agent/request_handler.rb +0 -8
- data/lib/contrast/agent/response.rb +0 -18
- data/lib/contrast/agent/telemetry/events/event.rb +1 -1
- data/lib/contrast/agent/telemetry/events/metric_event.rb +1 -1
- data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +3 -3
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/communication/messaging_queue.rb +2 -3
- data/lib/contrast/api/communication/socket_client.rb +4 -4
- data/lib/contrast/api/communication/speedracer.rb +4 -8
- data/lib/contrast/api/decorators/agent_startup.rb +5 -6
- data/lib/contrast/api/decorators/application_settings.rb +2 -1
- data/lib/contrast/api/decorators/application_startup.rb +6 -6
- data/lib/contrast/api/decorators/message.rb +0 -4
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -6
- data/lib/contrast/api/decorators.rb +0 -6
- data/lib/contrast/api/dtm.pb.rb +0 -489
- data/lib/contrast/components/agent.rb +16 -12
- data/lib/contrast/components/api.rb +10 -10
- data/lib/contrast/components/app_context.rb +3 -3
- data/lib/contrast/components/app_context_extend.rb +1 -1
- data/lib/contrast/components/assess.rb +92 -38
- data/lib/contrast/components/assess_rules.rb +36 -0
- data/lib/contrast/components/config.rb +54 -12
- data/lib/contrast/components/contrast_service.rb +8 -8
- data/lib/contrast/components/heap_dump.rb +1 -1
- data/lib/contrast/components/protect.rb +5 -5
- data/lib/contrast/components/ruby_component.rb +81 -0
- data/lib/contrast/components/sampling.rb +1 -1
- data/lib/contrast/components/security_logger.rb +23 -0
- data/lib/contrast/components/service.rb +55 -0
- data/lib/contrast/components/settings.rb +12 -4
- data/lib/contrast/config/base_configuration.rb +1 -1
- data/lib/contrast/config/protect_rules_configuration.rb +17 -3
- data/lib/contrast/config/server_configuration.rb +1 -1
- data/lib/contrast/config.rb +0 -6
- data/lib/contrast/configuration.rb +81 -17
- data/lib/contrast/extension/assess/exec_trigger.rb +3 -1
- data/lib/contrast/extension/assess/marshal.rb +3 -2
- data/lib/contrast/extension/assess/string.rb +0 -1
- data/lib/contrast/extension/extension.rb +1 -1
- data/lib/contrast/framework/base_support.rb +0 -5
- data/lib/contrast/framework/grape/support.rb +1 -23
- data/lib/contrast/framework/manager.rb +0 -10
- data/lib/contrast/framework/rails/support.rb +5 -58
- data/lib/contrast/framework/sinatra/support.rb +2 -21
- data/lib/contrast/logger/cef_log.rb +21 -3
- data/lib/contrast/logger/log.rb +1 -11
- data/lib/contrast/tasks/config.rb +4 -2
- data/lib/contrast/utils/assess/event_limit_utils.rb +5 -8
- data/lib/contrast/utils/assess/trigger_method_utils.rb +10 -18
- data/lib/contrast/utils/findings.rb +6 -5
- data/lib/contrast/utils/hash_digest.rb +9 -24
- data/lib/contrast/utils/hash_digest_extend.rb +6 -6
- data/lib/contrast/utils/invalid_configuration_util.rb +21 -58
- data/lib/contrast/utils/log_utils.rb +32 -8
- data/lib/contrast/utils/net_http_base.rb +2 -2
- data/lib/contrast/utils/patching/policy/patch_utils.rb +3 -2
- data/lib/contrast/utils/stack_trace_utils.rb +0 -25
- data/lib/contrast/utils/string_utils.rb +9 -0
- data/lib/contrast/utils/telemetry_client.rb +13 -7
- data/lib/contrast.rb +5 -10
- metadata +22 -28
- data/lib/contrast/agent/reporting/reporting_events/trace_event_source.rb +0 -30
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -36
- data/lib/contrast/api/decorators/activity.rb +0 -33
- data/lib/contrast/api/decorators/architecture_component.rb +0 -36
- data/lib/contrast/api/decorators/finding.rb +0 -29
- data/lib/contrast/api/decorators/route_coverage.rb +0 -91
- data/lib/contrast/api/decorators/trace_event.rb +0 -120
- data/lib/contrast/api/decorators/trace_event_object.rb +0 -63
- data/lib/contrast/api/decorators/trace_event_signature.rb +0 -69
- data/lib/contrast/api/decorators/trace_taint_range.rb +0 -52
- data/lib/contrast/config/assess_configuration.rb +0 -93
- data/lib/contrast/config/assess_rules_configuration.rb +0 -32
- data/lib/contrast/config/root_configuration.rb +0 -90
- data/lib/contrast/config/ruby_configuration.rb +0 -81
- data/lib/contrast/config/service_configuration.rb +0 -49
- data/lib/contrast/utils/preflight_util.rb +0 -13
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Components
|
|
6
|
+
module Ruby
|
|
7
|
+
# A wrapper build around the Common Agent Configuration project to allow
|
|
8
|
+
# for access of the values contained in its
|
|
9
|
+
# parent_configuration_spec.yaml.
|
|
10
|
+
# Those in this section pertain to the specific settings that apply to Ruby
|
|
11
|
+
class Interface
|
|
12
|
+
include Contrast::Components::ComponentBase
|
|
13
|
+
|
|
14
|
+
DISABLED_RAKE_TASK_LIST = %w[
|
|
15
|
+
about assets:clean assets:clobber assets:environment
|
|
16
|
+
assets:precompile assets:precompile:all db:create db:drop db:fixtures:load db:migrate
|
|
17
|
+
db:migrate:status db:rollback db:schema:cache:clear db:schema:cache:dump db:schema:dump
|
|
18
|
+
db:schema:load db:seed db:setup db:structure:dump db:version doc:app graphql:install graphql:object
|
|
19
|
+
log:clear middleware notes notes:custom rails:template rails:update routes secret spec spec:features
|
|
20
|
+
spec:requests spec:controllers spec:helpers spec:models spec:views spec:routing spec:rcov stats
|
|
21
|
+
test test:all test:all:db test:recent test:single test:uncommitted time:zones:all tmp:clear
|
|
22
|
+
tmp:create webpacker:compile contrast:service:start contrast:service:status contrast:service:stop
|
|
23
|
+
].cs__freeze
|
|
24
|
+
|
|
25
|
+
DEFAULT_UNINSTRUMENTED_NAMESPACES = %w[FactoryGirl FactoryBot].cs__freeze
|
|
26
|
+
|
|
27
|
+
attr_writer :disabled_agent_rake_tasks, :exceptions, :propagate_yield, :require_scan,
|
|
28
|
+
:non_request_tracking, :uninstrument_namespace
|
|
29
|
+
|
|
30
|
+
def initialize hsh = {}
|
|
31
|
+
return unless hsh
|
|
32
|
+
|
|
33
|
+
@disabled_agent_rake_tasks = hsh[:disabled_agent_rake_tasks]
|
|
34
|
+
@exceptions = Contrast::Config::ExceptionConfiguration.new(hsh[:exceptions])
|
|
35
|
+
@propagate_yield = hsh[:propagate_yield]
|
|
36
|
+
@require_scan = hsh[:require_scan]
|
|
37
|
+
@non_request_tracking = hsh[:non_request_tracking]
|
|
38
|
+
@uninstrument_namespace = hsh[:uninstrument_namespace]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# These commands being detected will result the agent disabling instrumentation, generally any command
|
|
42
|
+
# that doesn't result in the application listening on a port can be added here, this normally includes tasks
|
|
43
|
+
# that are ran pre-startup(like migrations) or to show information about the application(such as routes)
|
|
44
|
+
# @return [Array, DISABLED_RAKE_TASK_LIST]
|
|
45
|
+
def disabled_agent_rake_tasks
|
|
46
|
+
@disabled_agent_rake_tasks.nil? ? DISABLED_RAKE_TASK_LIST : @disabled_agent_rake_tasks
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# rubocop:disable Naming/MemoizedInstanceVariableName
|
|
50
|
+
# @return [Contrast::Config::ExceptionConfiguration]
|
|
51
|
+
def exceptions
|
|
52
|
+
@exceptions ||= Contrast::Config::ExceptionConfiguration.new
|
|
53
|
+
end
|
|
54
|
+
# rubocop:enable Naming/MemoizedInstanceVariableName
|
|
55
|
+
|
|
56
|
+
# controls whether or not we patch the rb_yield block to track split propagation
|
|
57
|
+
# @return [Boolean, Contrast::Utils::ObjectShare::TRUE]
|
|
58
|
+
def propagate_yield
|
|
59
|
+
@propagate_yield.nil? ? Contrast::Utils::ObjectShare::TRUE : @propagate_yield
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# control whether or not we run file scanning rules on require
|
|
63
|
+
# @return [Boolean, Contrast::Utils::ObjectShare::TRUE]
|
|
64
|
+
def require_scan
|
|
65
|
+
@require_scan.nil? ? Contrast::Utils::ObjectShare::TRUE : @require_scan
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# controls tracking outside of request
|
|
69
|
+
# @return [Boolean, Contrast::Utils::ObjectShare::FALSE]
|
|
70
|
+
def non_request_tracking
|
|
71
|
+
@non_request_tracking.nil? ? Contrast::Utils::ObjectShare::FALSE : @non_request_tracking
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @return [Array, DEFAULT_UNINSTRUMENTED_NAMESPACES]
|
|
75
|
+
def uninstrument_namespace
|
|
76
|
+
@uninstrument_namespace.nil? ? DEFAULT_UNINSTRUMENTED_NAMESPACES : @uninstrument_namespace
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -24,7 +24,7 @@ module Contrast
|
|
|
24
24
|
|
|
25
25
|
def sampling_control
|
|
26
26
|
@_sampling_control ||= begin
|
|
27
|
-
config_settings = ::Contrast::CONFIG.
|
|
27
|
+
config_settings = ::Contrast::CONFIG.assess&.sampling
|
|
28
28
|
settings = ::Contrast::SETTINGS&.assess_state&.sampling_settings
|
|
29
29
|
{
|
|
30
30
|
enabled: enabled?(config_settings, settings),
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Contrast
|
|
5
|
+
module Components
|
|
6
|
+
module SecurityLogger
|
|
7
|
+
# Here we will read and store the setting for the CEF Logging functionality
|
|
8
|
+
class Interface
|
|
9
|
+
# @return [String, nil]
|
|
10
|
+
attr_accessor :path
|
|
11
|
+
# @return [String, nil]
|
|
12
|
+
attr_accessor :level
|
|
13
|
+
|
|
14
|
+
def initialize hsh = {}
|
|
15
|
+
return unless hsh
|
|
16
|
+
|
|
17
|
+
@path = hsh[:path]
|
|
18
|
+
@level = hsh[:level]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'contrast/components/base'
|
|
5
|
+
require 'contrast/components/logger'
|
|
6
|
+
|
|
7
|
+
module Contrast
|
|
8
|
+
module Components
|
|
9
|
+
module Service
|
|
10
|
+
# A wrapper build around the Common Agent Configuration project to allow
|
|
11
|
+
# for access of the values contained in its
|
|
12
|
+
# parent_configuration_spec.yaml.
|
|
13
|
+
# Those in this section pertain to the communication between the Agent & the Service
|
|
14
|
+
class Interface
|
|
15
|
+
include Contrast::Components::ComponentBase
|
|
16
|
+
|
|
17
|
+
# We don't set these b/c we've been asked to handle the default values of these settings differently, logging
|
|
18
|
+
# when we have to use them.
|
|
19
|
+
DEFAULT_HOST = '127.0.0.1' # rubocop:disable Style/IpAddresses
|
|
20
|
+
DEFAULT_PORT = '30555'
|
|
21
|
+
|
|
22
|
+
attr_writer :logger, :bypass
|
|
23
|
+
# @return [String, nil]
|
|
24
|
+
attr_accessor :socket
|
|
25
|
+
# @return [String, nil]
|
|
26
|
+
attr_accessor :port
|
|
27
|
+
# @return [String, nil]
|
|
28
|
+
attr_accessor :host
|
|
29
|
+
# @return [Boolean, nil]
|
|
30
|
+
attr_accessor :enable
|
|
31
|
+
|
|
32
|
+
def initialize hsh = {}
|
|
33
|
+
return unless hsh
|
|
34
|
+
|
|
35
|
+
@enable = hsh[:enable]
|
|
36
|
+
@host = hsh[:host]
|
|
37
|
+
@port = hsh[:port]
|
|
38
|
+
@socket = hsh[:socket]
|
|
39
|
+
@logger = Contrast::Components::Logger::Interface.new(hsh[:logger])
|
|
40
|
+
@bypass = hsh[:bypass]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Contrast::Components::Logger::Interface]
|
|
44
|
+
def logger
|
|
45
|
+
@logger ||= Contrast::Components::Logger::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [Boolean, false]
|
|
49
|
+
def bypass
|
|
50
|
+
@bypass.nil? ? false : @bypass
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/api/settings.pb'
|
|
5
|
+
require 'contrast/agent/excluder'
|
|
5
6
|
require 'contrast/agent/reporting/settings/sensitive_data_masking'
|
|
7
|
+
require 'contrast/components/config'
|
|
6
8
|
|
|
7
9
|
module Contrast
|
|
8
10
|
module Components
|
|
@@ -24,7 +26,7 @@ module Contrast
|
|
|
24
26
|
SENSITIVE_DATA_MASKING_BASE = Contrast::Agent::Reporting::Settings::SensitiveDataMasking.new
|
|
25
27
|
|
|
26
28
|
# This is a class.
|
|
27
|
-
class Interface
|
|
29
|
+
class Interface # rubocop:disable Metrics/ClassLength
|
|
28
30
|
extend Contrast::Components::Config
|
|
29
31
|
|
|
30
32
|
# tainted_columns are database columns that receive unsanitized input.
|
|
@@ -90,6 +92,8 @@ module Contrast
|
|
|
90
92
|
attr_reader :last_app_update_ms
|
|
91
93
|
# @return [Integer] the time, in ms, that server settings last changed
|
|
92
94
|
attr_reader :last_server_update_ms
|
|
95
|
+
# @return [Contrast::Agent::Excluder] a wrapper around the exclusion rules for the application
|
|
96
|
+
attr_reader :excluder
|
|
93
97
|
|
|
94
98
|
def initialize
|
|
95
99
|
reset_state
|
|
@@ -120,7 +124,11 @@ module Contrast
|
|
|
120
124
|
new_vals = settings_response.application_state_translation
|
|
121
125
|
@application_state.modes_by_id = new_vals[:modes_by_id]
|
|
122
126
|
@application_state.exclusion_matchers = new_vals[:exclusion_matchers]
|
|
127
|
+
@excluder = Contrast::Agent::Excluder.new(@application_state.exclusion_matchers)
|
|
123
128
|
@assess_state.disabled_assess_rules = new_vals[:disabled_assess_rules]
|
|
129
|
+
if settings_response.session_id && !settings_response.session_id.blank?
|
|
130
|
+
@assess_state.session_id = settings_response.session_id
|
|
131
|
+
end
|
|
124
132
|
@last_app_update_ms = Contrast::Utils::Timer.now_ms
|
|
125
133
|
end
|
|
126
134
|
@last_app_update_ms = Contrast::Utils::Timer.now_ms
|
|
@@ -133,6 +141,7 @@ module Contrast
|
|
|
133
141
|
@application_state = APPLICATION_STATE_BASE.dup
|
|
134
142
|
@tainted_columns = {}
|
|
135
143
|
@sensitive_data_masking = SENSITIVE_DATA_MASKING_BASE.dup
|
|
144
|
+
@excluder = Contrast::Agent::Excluder.new
|
|
136
145
|
end
|
|
137
146
|
|
|
138
147
|
def build_protect_rules
|
|
@@ -202,9 +211,8 @@ module Contrast
|
|
|
202
211
|
# @application_state.exclusion_matchers = new_vals[:exclusion_matchers]
|
|
203
212
|
update_sensitive_data_policy(app_settings.sensitive_data_masking)
|
|
204
213
|
@assess_state.disabled_assess_rules = app_settings.assess.disabled_rules
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
end
|
|
214
|
+
new_session_id = app_settings.assess.session_id
|
|
215
|
+
@assess_state.session_id = new_session_id if new_session_id && !new_session_id.blank?
|
|
208
216
|
@last_app_update_ms = Contrast::Utils::Timer.now_ms
|
|
209
217
|
end
|
|
210
218
|
|
|
@@ -11,11 +11,12 @@ module Contrast
|
|
|
11
11
|
|
|
12
12
|
attr_accessor :disabled_rules
|
|
13
13
|
attr_writer :bot_blocker, :cmd_injection, :sql_injection, :nosql_injection, :untrusted_deserialization,
|
|
14
|
-
:xxe, :path_traversal, :reflected_xss, :unsafe_file_upload, :rule_base
|
|
14
|
+
:xxe, :path_traversal, :reflected_xss, :unsafe_file_upload, :rule_base, :cmdi_command_backdoors,
|
|
15
|
+
:sqli_dangerous_function
|
|
15
16
|
|
|
16
17
|
BASE_RULE = 'Contrast::Agent::Protect::Rule::Base'.cs__freeze
|
|
17
18
|
|
|
18
|
-
def initialize hsh = {}
|
|
19
|
+
def initialize hsh = {} # rubocop:disable Metrics/AbcSize
|
|
19
20
|
return unless hsh
|
|
20
21
|
|
|
21
22
|
@disabled_rules = hsh[:disabled_rules]
|
|
@@ -27,8 +28,13 @@ module Contrast
|
|
|
27
28
|
@path_traversal = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'path-traversal'])
|
|
28
29
|
@reflected_xss = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'reflected-xss'])
|
|
29
30
|
@sql_injection = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'sql-injection'])
|
|
31
|
+
@sqli_dangerous_function =
|
|
32
|
+
Contrast::Config::ProtectRuleConfiguration.new(hsh[:'sql-injection-semantic-dangerous-functions'])
|
|
30
33
|
@unsafe_file_upload = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'unsafe-file-upload'])
|
|
31
34
|
@untrusted_deserialization = Contrast::Config::ProtectRuleConfiguration.new(hsh[:'untrusted-deserialization'])
|
|
35
|
+
@cmdi_command_backdoors = Contrast::Config::ProtectRuleConfiguration.new(hsh[
|
|
36
|
+
:'cmd-injection-command-backdoors'
|
|
37
|
+
])
|
|
32
38
|
@xxe = Contrast::Config::ProtectRuleConfiguration.new(hsh[:xxe])
|
|
33
39
|
end
|
|
34
40
|
|
|
@@ -72,10 +78,18 @@ module Contrast
|
|
|
72
78
|
@unsafe_file_upload ||= Contrast::Config::ProtectRuleConfiguration.new
|
|
73
79
|
end
|
|
74
80
|
|
|
81
|
+
def cmdi_command_backdoors
|
|
82
|
+
@cmdi_command_backdoors ||= Contrast::Config::ProtectRuleConfiguration.new
|
|
83
|
+
end
|
|
84
|
+
|
|
75
85
|
def rule_base
|
|
76
86
|
@rule_base ||= Contrast::Config::ProtectRuleConfiguration.new
|
|
77
87
|
end
|
|
78
88
|
|
|
89
|
+
def sqli_dangerous_function
|
|
90
|
+
@sqli_dangerous_function = Contrast::Config::ProtectRuleConfiguration.new
|
|
91
|
+
end
|
|
92
|
+
|
|
79
93
|
def []= key, value
|
|
80
94
|
instance_variable_set("@#{ convert_key(key) }".to_sym, value)
|
|
81
95
|
end
|
|
@@ -90,7 +104,7 @@ module Contrast
|
|
|
90
104
|
|
|
91
105
|
# Convert instance variable names to format expected by TS
|
|
92
106
|
# for adding to the hash
|
|
93
|
-
def
|
|
107
|
+
def to_contrast_hash
|
|
94
108
|
hsh = {}
|
|
95
109
|
instance_variables.each do |iv|
|
|
96
110
|
# strip the '@' to get the key
|
data/lib/contrast/config.rb
CHANGED
|
@@ -11,13 +11,7 @@ module Contrast
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
require 'contrast/config/base_configuration'
|
|
14
|
-
require 'contrast/config/service_configuration'
|
|
15
14
|
require 'contrast/config/exception_configuration'
|
|
16
|
-
require 'contrast/config/assess_rules_configuration'
|
|
17
15
|
require 'contrast/config/protect_rule_configuration'
|
|
18
16
|
require 'contrast/config/protect_rules_configuration'
|
|
19
|
-
|
|
20
|
-
require 'contrast/config/ruby_configuration'
|
|
21
17
|
require 'contrast/config/server_configuration'
|
|
22
|
-
require 'contrast/config/assess_configuration'
|
|
23
|
-
require 'contrast/config/root_configuration'
|
|
@@ -6,7 +6,15 @@ require 'fileutils'
|
|
|
6
6
|
|
|
7
7
|
require 'contrast/config'
|
|
8
8
|
require 'contrast/utils/object_share'
|
|
9
|
+
require 'contrast/components/agent'
|
|
10
|
+
require 'contrast/components/api'
|
|
11
|
+
require 'contrast/components/app_context'
|
|
9
12
|
require 'contrast/components/scope'
|
|
13
|
+
require 'contrast/components/inventory'
|
|
14
|
+
require 'contrast/components/protect'
|
|
15
|
+
require 'contrast/components/assess'
|
|
16
|
+
require 'contrast/components/service'
|
|
17
|
+
require 'contrast/config/server_configuration'
|
|
10
18
|
|
|
11
19
|
module Contrast
|
|
12
20
|
# This is how we read in the local settings for the Agent, both ENV/ CMD line
|
|
@@ -18,7 +26,28 @@ module Contrast
|
|
|
18
26
|
include Contrast::Components::Scope::InstanceMethods
|
|
19
27
|
extend Contrast::Components::Scope::InstanceMethods
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
include Contrast::Config::BaseConfiguration
|
|
30
|
+
|
|
31
|
+
attr_reader :default_name
|
|
32
|
+
|
|
33
|
+
# @return [Contrast::Components::Api::Interface]
|
|
34
|
+
attr_writer :api
|
|
35
|
+
# @return [Contrast::Components::Agent::Interface]
|
|
36
|
+
attr_writer :agent
|
|
37
|
+
# @return [Contrast::Components::AppContext::Interface]
|
|
38
|
+
attr_writer :application
|
|
39
|
+
# @return [Contrast::Config::ServerConfiguration]
|
|
40
|
+
attr_writer :server
|
|
41
|
+
# @return [Contrast::Components::Assess::Interface]
|
|
42
|
+
attr_writer :assess
|
|
43
|
+
# @return [Contrast::Components::Inventory::Interface]
|
|
44
|
+
attr_writer :inventory
|
|
45
|
+
# @return [Contrast::Components::Protect::Interface]
|
|
46
|
+
attr_writer :protect
|
|
47
|
+
# @return [Contrast::Components::Service::Interface]
|
|
48
|
+
attr_writer :service
|
|
49
|
+
# @return [Boolean, nil]
|
|
50
|
+
attr_accessor :enable
|
|
22
51
|
|
|
23
52
|
DEFAULT_YAML_PATH = 'contrast_security.yaml'
|
|
24
53
|
MILLISECOND_MARKER = '_ms'
|
|
@@ -40,20 +69,15 @@ module Contrast
|
|
|
40
69
|
# Some in-flight rewrites to maintain backwards compatibility
|
|
41
70
|
config_kv = update_prop_keys(config_kv)
|
|
42
71
|
|
|
43
|
-
@
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def respond_to_missing? method_name, *args
|
|
56
|
-
root&.cs__respond_to?(method_name) || super
|
|
72
|
+
@api = Contrast::Components::Api::Interface.new(config_kv[:api])
|
|
73
|
+
@enable = config_kv[:enable]
|
|
74
|
+
@agent = Contrast::Components::Agent::Interface.new(config_kv[:agent])
|
|
75
|
+
@application = Contrast::Components::AppContext::Interface.new(config_kv[:application])
|
|
76
|
+
@server = Contrast::Config::ServerConfiguration.new(config_kv[:server])
|
|
77
|
+
@assess = Contrast::Components::Assess::Interface.new(config_kv[:assess])
|
|
78
|
+
@inventory = Contrast::Components::Inventory::Interface.new(config_kv[:inventory])
|
|
79
|
+
@protect = Contrast::Components::Protect::Interface.new(config_kv[:protect])
|
|
80
|
+
@service = Contrast::Components::Service::Interface.new(config_kv[:service])
|
|
57
81
|
end
|
|
58
82
|
|
|
59
83
|
# Get a loggable YAML format of this configuration
|
|
@@ -63,6 +87,46 @@ module Contrast
|
|
|
63
87
|
convert_to_hash.to_yaml
|
|
64
88
|
end
|
|
65
89
|
|
|
90
|
+
# @return [Contrast::Components::Api::Interface]
|
|
91
|
+
def api
|
|
92
|
+
@api ||= Contrast::Components::Api::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @return [Contrast::Components::Agent::Interface]
|
|
96
|
+
def agent
|
|
97
|
+
@agent ||= Contrast::Components::Agent::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @return [Contrast::Components::AppContext::Interface]
|
|
101
|
+
def application
|
|
102
|
+
@application ||= Contrast::Components::AppContext::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @return [Contrast::Config::ServerConfiguration]
|
|
106
|
+
def server
|
|
107
|
+
@server ||= Contrast::Config::ServerConfiguration.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @return [Contrast::Components::Assess::Interface]
|
|
111
|
+
def assess
|
|
112
|
+
@assess ||= Contrast::Components::Assess::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Contrast::Components::Inventory::Interface]
|
|
116
|
+
def inventory
|
|
117
|
+
@inventory ||= Contrast::Components::Inventory::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @return [Contrast::Components::Protect::Interface]
|
|
121
|
+
def protect
|
|
122
|
+
@protect ||= Contrast::Components::Protect::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @return [Contrast::Components::Service::Interface]
|
|
126
|
+
def service
|
|
127
|
+
@service ||= Contrast::Components::Service::Interface.new # rubocop:disable Naming/MemoizedInstanceVariableName
|
|
128
|
+
end
|
|
129
|
+
|
|
66
130
|
protected
|
|
67
131
|
|
|
68
132
|
# TODO: RUBY-546 move utility methods to auxiliary classes
|
|
@@ -213,11 +277,11 @@ module Contrast
|
|
|
213
277
|
# @return [Hash, Object] the leaf of each
|
|
214
278
|
# Contrast::Config::BaseConfiguration will be returned in the N > 0 steps
|
|
215
279
|
# the Hash will be returned at the end of the 0 level
|
|
216
|
-
def convert_to_hash convert =
|
|
280
|
+
def convert_to_hash convert = self, hash = {}
|
|
217
281
|
case convert
|
|
218
282
|
when Contrast::Config::BaseConfiguration
|
|
219
283
|
# to_hash returns @configuration_map
|
|
220
|
-
convert.
|
|
284
|
+
convert.to_contrast_hash.each_key do |key|
|
|
221
285
|
# change '-' to '_' for ProtectRulesConfiguration
|
|
222
286
|
hash[key] = convert_to_hash(convert.send(key.tr('-', '_').to_sym), {})
|
|
223
287
|
hash[key] = REDACTED if redactable?(key)
|
|
@@ -19,7 +19,9 @@ module Contrast
|
|
|
19
19
|
# source might not be all the args passed in, but it is the one we care
|
|
20
20
|
# about. we could pass in all the args in the last param here if it
|
|
21
21
|
# becomes an issue in rendering on TS
|
|
22
|
-
Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node,
|
|
22
|
+
finding = Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node,
|
|
23
|
+
source, Kernel, nil, source)
|
|
24
|
+
Contrast::Agent::Assess::Policy::TriggerMethod.report_finding(finding) if finding
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
private
|
|
@@ -36,8 +36,9 @@ module Contrast
|
|
|
36
36
|
# source might not be all the args passed in, but it is the one we care
|
|
37
37
|
# about. we could pass in all the args in the last param here if it
|
|
38
38
|
# becomes an issue in rendering on TS
|
|
39
|
-
Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node('Marshal', :load),
|
|
40
|
-
|
|
39
|
+
finding = Contrast::Agent::Assess::Policy::TriggerMethod.build_finding(trigger_node('Marshal', :load),
|
|
40
|
+
source, self, ret, *args)
|
|
41
|
+
Contrast::Agent::Assess::Policy::TriggerMethod.report_finding(finding) if finding
|
|
41
42
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(ret))
|
|
42
43
|
|
|
43
44
|
properties.copy_from(source, ret)
|
|
@@ -37,7 +37,6 @@ module Contrast
|
|
|
37
37
|
# @param inputs [Array<String>] Inputs for interpolation.
|
|
38
38
|
# @param result [String] The result from the interpolation.
|
|
39
39
|
def track_interpolation inputs, result
|
|
40
|
-
return unless ::Contrast::AGENT.interpolation_enabled?
|
|
41
40
|
return unless inputs.any? { |input| Contrast::Agent::Assess::Tracker.tracked?(input) }
|
|
42
41
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(result))
|
|
43
42
|
|
|
@@ -41,11 +41,6 @@ module Contrast
|
|
|
41
41
|
raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
# @raise [NoMethodError] raises error if subclass does not implement this method
|
|
45
|
-
def current_route
|
|
46
|
-
raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
|
|
47
|
-
end
|
|
48
|
-
|
|
49
44
|
# @raise [NoMethodError] raises error if subclass does not implement this method
|
|
50
45
|
def retrieve_request _env
|
|
51
46
|
raise(NoMethodError, 'Subclasses of BaseSupport should implement this method')
|
|
@@ -68,29 +68,6 @@ module Contrast
|
|
|
68
68
|
routes
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
# Given the current request return a RouteCoverage dtm.
|
|
72
|
-
#
|
|
73
|
-
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
|
74
|
-
# @param controller [::Grape::API] optionally use this controller instead of global ::Grape::API.
|
|
75
|
-
# @return [Contrast::Api::Dtm::RouteCoverage, nil] a Dtm describing the route
|
|
76
|
-
# matched to the request if a match was found.
|
|
77
|
-
def current_route request, controller = ::Grape::API, full_route = nil
|
|
78
|
-
return unless grape_controller?(controller)
|
|
79
|
-
|
|
80
|
-
method = request.env[::Rack::REQUEST_METHOD] # GET, PUT, POST, etc...
|
|
81
|
-
|
|
82
|
-
# Find final controller - actually we gotta match the route to the scanned application
|
|
83
|
-
# Initially Grape compiles all routes on startup, so we can use the url from the request
|
|
84
|
-
# and create the observed route
|
|
85
|
-
# Class < Grape::API, Grape::Router::Route
|
|
86
|
-
final_controller, route_pattern = _route_recurse(method, _cleaned_route(request), grape_controllers)
|
|
87
|
-
return unless final_controller
|
|
88
|
-
|
|
89
|
-
full_route ||= request.env[::Rack::PATH_INFO]
|
|
90
|
-
|
|
91
|
-
Contrast::Api::Dtm::RouteCoverage.from_grape_controller(final_controller, method, route_pattern, full_route)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
71
|
# Given the current request - return a RouteCoverage object
|
|
95
72
|
|
|
96
73
|
# @param request [Contrast::Agent::Request] a contrast tracked request.
|
|
@@ -113,6 +90,7 @@ module Contrast
|
|
|
113
90
|
|
|
114
91
|
new_route_coverage = Contrast::Agent::Reporting::RouteCoverage.new
|
|
115
92
|
new_route_coverage.attach_rack_based_data(final_controller, method, route_pattern, full_route)
|
|
93
|
+
new_route_coverage
|
|
116
94
|
end
|
|
117
95
|
|
|
118
96
|
# Search object space for grape controllers--any class that subclasses ::Grape::API.
|
|
@@ -108,16 +108,6 @@ module Contrast
|
|
|
108
108
|
result
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
# Iterate through current frameworks and return the current request's route. This will be the first non-nil
|
|
112
|
-
# result.
|
|
113
|
-
#
|
|
114
|
-
# @param request [Contrast::Agent::Request] the current request.
|
|
115
|
-
# @return [Contrast::Api::Dtm::RouteCoverage] the current route as a Dtm.
|
|
116
|
-
def get_route_dtm request
|
|
117
|
-
@_frameworks.lazy.map { |framework_support| framework_support.current_route(request) }.
|
|
118
|
-
reject(&:nil?).first # rubocop:disable Style/CollectionCompact
|
|
119
|
-
end
|
|
120
|
-
|
|
121
111
|
# Iterate through current frameworks and return the current request's route. This will be the first non-nil
|
|
122
112
|
# result.
|
|
123
113
|
#
|