contrast-agent 6.6.3 → 6.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +0 -3
  4. data/ext/cs__scope/cs__scope.c +1 -1
  5. data/lib/contrast/agent/assess/contrast_event.rb +2 -24
  6. data/lib/contrast/agent/assess/events/source_event.rb +7 -61
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +11 -0
  8. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +0 -55
  9. data/lib/contrast/agent/assess/policy/policy_node.rb +3 -3
  10. data/lib/contrast/agent/assess/policy/policy_node_utils.rb +0 -1
  11. data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
  12. data/lib/contrast/agent/assess/policy/source_method.rb +24 -1
  13. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -5
  14. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +6 -1
  15. data/lib/contrast/agent/assess/policy/trigger_method.rb +38 -119
  16. data/lib/contrast/agent/assess/policy/trigger_node.rb +3 -3
  17. data/lib/contrast/agent/assess/property/evented.rb +2 -12
  18. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +42 -82
  19. data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -27
  20. data/lib/contrast/agent/assess/rule/response/body_rule.rb +1 -3
  21. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +77 -62
  22. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +1 -1
  23. data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +6 -1
  24. data/lib/contrast/agent/assess/rule/response/header_rule.rb +5 -5
  25. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +1 -1
  26. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -1
  27. data/lib/contrast/agent/assess/tracker.rb +1 -7
  28. data/lib/contrast/agent/at_exit_hook.rb +1 -7
  29. data/lib/contrast/agent/excluder.rb +206 -0
  30. data/lib/contrast/agent/exclusion_matcher.rb +6 -0
  31. data/lib/contrast/agent/inventory/database_config.rb +18 -23
  32. data/lib/contrast/agent/middleware.rb +0 -1
  33. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +4 -0
  34. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -0
  35. data/lib/contrast/agent/protect/rule/base.rb +64 -24
  36. data/lib/contrast/agent/protect/rule/base_service.rb +1 -0
  37. data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -104
  38. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +129 -0
  39. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +169 -0
  40. data/lib/contrast/agent/protect/rule/deserialization.rb +7 -5
  41. data/lib/contrast/agent/protect/rule/path_traversal.rb +9 -7
  42. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +16 -14
  43. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +51 -0
  44. data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +67 -0
  45. data/lib/contrast/agent/protect/rule/sqli.rb +6 -31
  46. data/lib/contrast/agent/protect/rule/xxe.rb +11 -6
  47. data/lib/contrast/agent/protect/rule.rb +3 -1
  48. data/lib/contrast/agent/reporting/attack_result/attack_result.rb +8 -0
  49. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +91 -36
  50. data/lib/contrast/agent/reporting/attack_result/user_input.rb +11 -0
  51. data/lib/contrast/agent/reporting/details/bot_blocker_details.rb +29 -0
  52. data/lib/contrast/agent/reporting/details/cmd_injection_details.rb +30 -0
  53. data/lib/contrast/agent/reporting/details/details.rb +18 -0
  54. data/lib/contrast/agent/reporting/details/http_method_tempering_details.rb +27 -0
  55. data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +27 -0
  56. data/lib/contrast/agent/reporting/details/no_sqli_details.rb +36 -0
  57. data/lib/contrast/agent/reporting/details/path_traversal_details.rb +24 -0
  58. data/lib/contrast/agent/reporting/details/path_traversal_semantic_analysis_details.rb +32 -0
  59. data/lib/contrast/agent/reporting/details/protect_rule_details.rb +17 -0
  60. data/lib/contrast/agent/reporting/details/sqli_dangerous_functions.rb +22 -0
  61. data/lib/contrast/agent/reporting/details/sqli_details.rb +36 -0
  62. data/lib/contrast/agent/reporting/details/untrusted_deserialization_details.rb +27 -0
  63. data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +24 -0
  64. data/lib/contrast/agent/reporting/details/xss_details.rb +33 -0
  65. data/lib/contrast/agent/reporting/details/xss_match.rb +30 -0
  66. data/lib/contrast/agent/reporting/details/xxe_details.rb +36 -0
  67. data/lib/contrast/agent/reporting/details/xxe_match.rb +25 -0
  68. data/lib/contrast/agent/reporting/details/xxe_wrapper.rb +25 -0
  69. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +1 -1
  70. data/lib/contrast/agent/reporting/masker/masker.rb +78 -65
  71. data/lib/contrast/agent/reporting/masker/masker_utils.rb +1 -30
  72. data/lib/contrast/agent/reporting/reporter.rb +1 -2
  73. data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +2 -2
  74. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +81 -15
  75. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +13 -25
  76. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +17 -22
  77. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +46 -125
  78. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +5 -16
  79. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +10 -18
  80. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -14
  81. data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +1 -1
  82. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +7 -21
  83. data/lib/contrast/agent/reporting/reporting_events/finding.rb +19 -49
  84. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +12 -9
  85. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +1 -1
  86. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +23 -21
  87. data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +5 -18
  88. data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +1 -0
  89. data/lib/contrast/{api/decorators/trace_taint_range_tags.rb → agent/reporting/reporting_events/finding_event_taint_range_tags.rb} +7 -6
  90. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +45 -10
  91. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +1 -1
  92. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +2 -2
  93. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -14
  94. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +11 -0
  95. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +3 -1
  96. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +11 -23
  97. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +8 -26
  98. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
  99. data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -7
  100. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -1
  101. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +2 -1
  102. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +3 -3
  103. data/lib/contrast/agent/request.rb +4 -2
  104. data/lib/contrast/agent/request_context.rb +12 -15
  105. data/lib/contrast/agent/request_context_extend.rb +67 -69
  106. data/lib/contrast/agent/request_handler.rb +1 -11
  107. data/lib/contrast/agent/response.rb +0 -18
  108. data/lib/contrast/agent/service_heartbeat.rb +1 -1
  109. data/lib/contrast/agent/telemetry/events/event.rb +1 -1
  110. data/lib/contrast/agent/telemetry/events/metric_event.rb +1 -1
  111. data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +3 -3
  112. data/lib/contrast/agent/version.rb +1 -1
  113. data/lib/contrast/api/communication/messaging_queue.rb +2 -3
  114. data/lib/contrast/api/communication/socket_client.rb +4 -4
  115. data/lib/contrast/api/communication/speedracer.rb +4 -8
  116. data/lib/contrast/api/decorators/agent_startup.rb +5 -6
  117. data/lib/contrast/api/decorators/application_settings.rb +2 -1
  118. data/lib/contrast/api/decorators/application_startup.rb +6 -6
  119. data/lib/contrast/api/decorators/message.rb +0 -4
  120. data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -6
  121. data/lib/contrast/api/decorators.rb +0 -6
  122. data/lib/contrast/api/dtm.pb.rb +0 -489
  123. data/lib/contrast/components/agent.rb +16 -12
  124. data/lib/contrast/components/api.rb +10 -10
  125. data/lib/contrast/components/app_context.rb +9 -9
  126. data/lib/contrast/components/app_context_extend.rb +1 -1
  127. data/lib/contrast/components/assess.rb +92 -38
  128. data/lib/contrast/components/assess_rules.rb +36 -0
  129. data/lib/contrast/components/config.rb +54 -12
  130. data/lib/contrast/components/contrast_service.rb +8 -8
  131. data/lib/contrast/components/heap_dump.rb +1 -1
  132. data/lib/contrast/components/protect.rb +5 -5
  133. data/lib/contrast/components/ruby_component.rb +81 -0
  134. data/lib/contrast/components/sampling.rb +1 -1
  135. data/lib/contrast/components/security_logger.rb +23 -0
  136. data/lib/contrast/components/service.rb +55 -0
  137. data/lib/contrast/components/settings.rb +12 -4
  138. data/lib/contrast/config/base_configuration.rb +1 -1
  139. data/lib/contrast/config/protect_rules_configuration.rb +17 -3
  140. data/lib/contrast/config/server_configuration.rb +1 -1
  141. data/lib/contrast/config.rb +0 -6
  142. data/lib/contrast/configuration.rb +81 -17
  143. data/lib/contrast/extension/assess/exec_trigger.rb +3 -1
  144. data/lib/contrast/extension/assess/marshal.rb +3 -2
  145. data/lib/contrast/extension/assess/string.rb +0 -1
  146. data/lib/contrast/extension/extension.rb +1 -1
  147. data/lib/contrast/framework/base_support.rb +0 -5
  148. data/lib/contrast/framework/grape/support.rb +1 -23
  149. data/lib/contrast/framework/manager.rb +0 -10
  150. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -6
  151. data/lib/contrast/framework/rails/support.rb +5 -58
  152. data/lib/contrast/framework/sinatra/support.rb +2 -21
  153. data/lib/contrast/logger/cef_log.rb +21 -3
  154. data/lib/contrast/logger/log.rb +1 -11
  155. data/lib/contrast/tasks/config.rb +4 -2
  156. data/lib/contrast/utils/assess/event_limit_utils.rb +28 -12
  157. data/lib/contrast/utils/assess/trigger_method_utils.rb +10 -18
  158. data/lib/contrast/utils/findings.rb +6 -5
  159. data/lib/contrast/utils/hash_digest.rb +9 -24
  160. data/lib/contrast/utils/hash_digest_extend.rb +6 -6
  161. data/lib/contrast/utils/invalid_configuration_util.rb +21 -58
  162. data/lib/contrast/utils/log_utils.rb +47 -17
  163. data/lib/contrast/utils/net_http_base.rb +7 -8
  164. data/lib/contrast/utils/patching/policy/patch_utils.rb +3 -2
  165. data/lib/contrast/utils/stack_trace_utils.rb +0 -25
  166. data/lib/contrast/utils/string_utils.rb +9 -0
  167. data/lib/contrast/utils/telemetry_client.rb +13 -7
  168. data/lib/contrast.rb +5 -10
  169. metadata +39 -28
  170. data/lib/contrast/agent/reporting/reporting_events/trace_event_source.rb +0 -30
  171. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -43
  172. data/lib/contrast/api/decorators/activity.rb +0 -33
  173. data/lib/contrast/api/decorators/architecture_component.rb +0 -36
  174. data/lib/contrast/api/decorators/finding.rb +0 -29
  175. data/lib/contrast/api/decorators/route_coverage.rb +0 -91
  176. data/lib/contrast/api/decorators/trace_event.rb +0 -120
  177. data/lib/contrast/api/decorators/trace_event_object.rb +0 -63
  178. data/lib/contrast/api/decorators/trace_event_signature.rb +0 -69
  179. data/lib/contrast/api/decorators/trace_taint_range.rb +0 -52
  180. data/lib/contrast/config/assess_configuration.rb +0 -93
  181. data/lib/contrast/config/assess_rules_configuration.rb +0 -32
  182. data/lib/contrast/config/root_configuration.rb +0 -90
  183. data/lib/contrast/config/ruby_configuration.rb +0 -81
  184. data/lib/contrast/config/service_configuration.rb +0 -49
  185. 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.root.assess&.sampling
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
- if app_settings.assess.session_id && !app_settings.assess.session_id.blank?
206
- @assess_state.session_id = app_settings.assess.session_id
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
 
@@ -12,7 +12,7 @@ module Contrast
12
12
  extend Forwardable
13
13
  AT_UNDERSCORE = '@_'
14
14
 
15
- def to_hash
15
+ def to_contrast_hash
16
16
  hsh = {}
17
17
  instance_variables.each do |iv|
18
18
  # strip the '@' of '@_' to get the key
@@ -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 to_hash
107
+ def to_contrast_hash
94
108
  hsh = {}
95
109
  instance_variables.each do |iv|
96
110
  # strip the '@' to get the key
@@ -9,7 +9,7 @@ module Contrast
9
9
  include Contrast::Config::BaseConfiguration
10
10
 
11
11
  # @return [String, nil]
12
- attr_accessor :name
12
+ attr_reader :name
13
13
  # @return [String, nil]
14
14
  attr_accessor :path
15
15
  # @return [String, nil]
@@ -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
- attr_reader :default_name, :root
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
- @root = Contrast::Config::RootConfiguration.new(config_kv)
44
- end
45
-
46
- # Because we call this method to determine the need for scoping, it itself
47
- # must be executed inside a Contrast scope. Failure to do so could result
48
- # in an infinite loop on the to_sym method used later.
49
- def method_missing symbol, *args
50
- with_contrast_scope do
51
- root.public_send(symbol, *args) if root.cs__respond_to?(symbol)
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 = root, hash = {}
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.to_hash.each_key do |key|
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, source, Kernel, nil, source)
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), source,
40
- self, ret, *args)
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
 
@@ -36,7 +36,7 @@ module Contrast
36
36
  # conditions
37
37
  def assign_value path
38
38
  case path
39
- when /fiber/, /interpolation26/
39
+ when /fiber/, /interpolation/
40
40
  require(path) if Funchook.available?
41
41
  else
42
42
  require(path)
@@ -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
  #
@@ -20,12 +20,7 @@ module Contrast
20
20
  Contrast::Agent.reporter&.send_event_immediately(event)
21
21
  end
22
22
 
23
- if Contrast::Agent::Reporter.enabled?
24
- event = Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
25
- Contrast::Agent.reporter&.send_event_immediately(event)
26
- else
27
- Contrast::Agent.messaging_queue&.send_event_immediately(context.activity)
28
- end
23
+ Contrast::Agent.reporter&.send_event_immediately(context.activity)
29
24
  end
30
25
 
31
26
  def instrument