contrast-agent 6.6.2 → 6.6.5

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/assess/policy/trigger_method.rb +21 -6
  3. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +2 -0
  4. data/lib/contrast/agent/at_exit_hook.rb +1 -7
  5. data/lib/contrast/agent/inventory/database_config.rb +16 -12
  6. data/lib/contrast/agent/inventory/policy/datastores.rb +1 -2
  7. data/lib/contrast/agent/middleware.rb +0 -1
  8. data/lib/contrast/agent/protect/rule/base.rb +16 -20
  9. data/lib/contrast/agent/protect/rule/cmd_injection.rb +5 -4
  10. data/lib/contrast/agent/protect/rule/deserialization.rb +5 -4
  11. data/lib/contrast/agent/protect/rule/path_traversal.rb +9 -7
  12. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +16 -14
  13. data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
  14. data/lib/contrast/agent/protect/rule/xxe.rb +9 -6
  15. data/lib/contrast/agent/reporting/attack_result/attack_result.rb +8 -0
  16. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +85 -36
  17. data/lib/contrast/agent/reporting/attack_result/user_input.rb +11 -0
  18. data/lib/contrast/agent/reporting/details/bot_blocker_details.rb +29 -0
  19. data/lib/contrast/agent/reporting/details/cmd_injection_details.rb +30 -0
  20. data/lib/contrast/agent/reporting/details/details.rb +18 -0
  21. data/lib/contrast/agent/reporting/details/http_method_tempering_details.rb +27 -0
  22. data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +27 -0
  23. data/lib/contrast/agent/reporting/details/no_sqli_details.rb +36 -0
  24. data/lib/contrast/agent/reporting/details/path_traversal_details.rb +24 -0
  25. data/lib/contrast/agent/reporting/details/path_traversal_semantic_analysis_details.rb +32 -0
  26. data/lib/contrast/agent/reporting/details/protect_rule_details.rb +17 -0
  27. data/lib/contrast/agent/reporting/details/sqli_details.rb +36 -0
  28. data/lib/contrast/agent/reporting/details/untrusted_deserialization_details.rb +27 -0
  29. data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +24 -0
  30. data/lib/contrast/agent/reporting/details/xss_details.rb +33 -0
  31. data/lib/contrast/agent/reporting/details/xss_match.rb +30 -0
  32. data/lib/contrast/agent/reporting/details/xxe_details.rb +36 -0
  33. data/lib/contrast/agent/reporting/details/xxe_match.rb +25 -0
  34. data/lib/contrast/agent/reporting/details/xxe_wrapper.rb +25 -0
  35. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +1 -1
  36. data/lib/contrast/agent/reporting/masker/masker.rb +78 -65
  37. data/lib/contrast/agent/reporting/masker/masker_utils.rb +1 -30
  38. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +84 -15
  39. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +13 -25
  40. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +17 -22
  41. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +46 -125
  42. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +5 -16
  43. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +10 -18
  44. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -14
  45. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +29 -20
  46. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +45 -10
  47. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +2 -2
  48. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -7
  49. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +1 -1
  50. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +2 -2
  51. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +2 -1
  52. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -1
  53. data/lib/contrast/agent/request.rb +2 -0
  54. data/lib/contrast/agent/request_context.rb +13 -4
  55. data/lib/contrast/agent/request_context_extend.rb +59 -40
  56. data/lib/contrast/agent/request_handler.rb +7 -9
  57. data/lib/contrast/agent/service_heartbeat.rb +1 -1
  58. data/lib/contrast/agent/version.rb +1 -1
  59. data/lib/contrast/api/decorators/message.rb +1 -1
  60. data/lib/contrast/components/app_context.rb +62 -8
  61. data/lib/contrast/components/app_context_extend.rb +8 -8
  62. data/lib/contrast/config/assess_configuration.rb +1 -1
  63. data/lib/contrast/config/root_configuration.rb +6 -4
  64. data/lib/contrast/config.rb +0 -1
  65. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -6
  66. data/lib/contrast/utils/assess/event_limit_utils.rb +26 -7
  67. data/lib/contrast/utils/log_utils.rb +16 -10
  68. data/lib/contrast/utils/net_http_base.rb +5 -6
  69. data/lib/contrast/utils/string_utils.rb +2 -6
  70. data/lib/contrast.rb +1 -1
  71. metadata +30 -14
  72. data/lib/contrast/config/application_configuration.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f00aee3e36cdb303ca9b209824fbb92386e0ca0043c0f24377f79168dca8d252
4
- data.tar.gz: 7fc3d7571246ff92a10da151ce4b723768e3f7214b5a1e57d5bb1d6a66e86e2b
3
+ metadata.gz: 9a7491020083af4de63e878defb8a57583d22258ec534fba4b6d7ad923861c55
4
+ data.tar.gz: 9c784b84420c8caa8f3123e8dc053b21a7a8964058f8e5b073cbf794275e9793
5
5
  SHA512:
6
- metadata.gz: 9fc9e69602a2706cb41bf8d13e07693afb61ad85ad03ff43182f3c79c5f9dff1c0b8ed3e0cb690d15cf8e43830920516604e9b497945963897f0ee1b82e11f9b
7
- data.tar.gz: dfd4e5146f9ac498b83d76b13a9d6ed17a5de0e659ed301acbf6a873e18d5ff75ea8aa8fa7c3789433e100903a9f6bfb4b87c9d283107c5bd04015f862e88644
6
+ metadata.gz: 8896ddef1bb19c81b279f54c3ec1f5458474d7f6a9b5b7910670c2e87e00a1bdfab2a6ab422bb585eb125ba707839b9967490b2001951b360b211d3e41f2b15e
7
+ data.tar.gz: 2a6e933028aaf9b899cc107e565a112344408563035c20fec1cd3625d02bbd1de5ca6d02566a9379a07b532bda16d64b0868f2a30b0183aaafcfc0d2d3dc1a6d
@@ -9,6 +9,7 @@ require 'contrast/utils/sha256_builder'
9
9
  require 'contrast/utils/assess/trigger_method_utils'
10
10
  require 'contrast/agent/assess/events/event_data'
11
11
  require 'contrast/agent/reporting/reporting_events/preflight'
12
+ require 'contrast/agent/reporting/reporting_events/application_activity'
12
13
  require 'contrast/agent/reporting/reporting_events/preflight_message'
13
14
  require 'contrast/agent/reporting/reporting_events/route_discovery'
14
15
  require 'contrast/agent/reporting/reporting_utilities/reporting_storage'
@@ -118,7 +119,8 @@ module Contrast
118
119
  append_to_finding(finding, event_data, request)
119
120
  logger.trace('Finding created', node_id: trigger_node.id, source_id: source.__id__,
120
121
  rule: trigger_node.rule_id)
121
- report_finding(finding, request)
122
+ # check here if we need to add that finding
123
+ report_finding(finding, request) unless not_reported?(finding)
122
124
  end
123
125
  end
124
126
 
@@ -133,22 +135,21 @@ module Contrast
133
135
  def report_finding finding, request = nil
134
136
  context = Contrast::Agent::REQUEST_TRACKER.current
135
137
  if context
136
- context.activity.findings << finding
138
+ # REMOVE_DTM_ACTIVITY
139
+ context.dtm_activity.findings << finding
137
140
  return
138
141
  end
139
142
 
140
143
  return unless ::Contrast::ASSESS.non_request_tracking? || NON_REQUEST_RULES.include?(finding.rule_id)
141
144
 
145
+ # REMOVE_DTM_ACTIVITY Findings still using dtm - REMOVE
142
146
  activity = Contrast::Api::Dtm::Activity.new
143
- activity.findings << finding
144
147
  if request
145
- activity.http_request = request.dtm
148
+ activity.request = request.dtm
146
149
  else
147
150
  logger.debug('Attempted to report finding without request', finding: finding)
148
151
  end
149
152
 
150
- # If we're out of request context, then we need to report this finding ourselves,
151
- # so we'll send it in the one-off activity we created.
152
153
  Contrast::Agent.messaging_queue&.send_event_eventually(activity)
153
154
  end
154
155
 
@@ -269,6 +270,20 @@ module Contrast
269
270
 
270
271
  MINIMUM_FINDING_VERSION
271
272
  end
273
+
274
+ # Check if the following finding was already added to context.activity
275
+ # We could use this after we get rid of the MessagingQueue.
276
+ #
277
+ # @param finding [Contrast::Api::Dtm::Finding] Finding we're about to report
278
+ # @return Boolean
279
+ def not_reported? finding
280
+ return false unless (current = Contrast::Agent::REQUEST_TRACKER.current)
281
+
282
+ currently_added_findings = current.dtm_activity.findings
283
+ return false if currently_added_findings.empty?
284
+
285
+ currently_added_findings.any? { |f| f.rule_id == finding.rule_id && f.hash_code == finding.hash_code }
286
+ end
272
287
  end
273
288
  end
274
289
  end
@@ -113,6 +113,8 @@ module Contrast
113
113
  class_name = clazz.cs__name
114
114
 
115
115
  finding = assign_finding(class_name, constant_string)
116
+ # TODO: RUBY-1705
117
+ # The only place we still use dtm activity
116
118
  activity = Contrast::Api::Dtm::Activity.new
117
119
  activity.findings << finding
118
120
  Contrast::Agent.messaging_queue.send_event_eventually(activity, force: true)
@@ -37,13 +37,7 @@ module Contrast
37
37
  ].compact.each do |event|
38
38
  Contrast::Agent.reporter&.send_event_immediately(event)
39
39
  end
40
-
41
- if Contrast::Agent::Reporter.enabled?
42
- event = Contrast::Agent::Reporting::DtmMessage.dtm_to_event(context.activity)
43
- Contrast::Agent.reporter&.send_event_immediately(event)
44
- else
45
- Contrast::Agent.messaging_queue&.send_event_immediately(context.activity)
46
- end
40
+ Contrast::Agent.reporter&.send_event_immediately(context.activity)
47
41
  end
48
42
  end
49
43
  end
@@ -30,20 +30,19 @@ module Contrast
30
30
  # Both report the same
31
31
  # Contrast::Api::Dtm::ArchitectureComponent, but have different names for their fields.
32
32
  #
33
- # @param activity_or_update [Contrast::Api::Dtm::Activity, Contrast::Agent::Reporting::ApplicationUpdate]
33
+ # @param activity_or_update [Contrast::Agent::Reporting::ApplicationUpdate]
34
34
  # @param hash_or_str [Hash, String] the database connection information
35
35
  def append_db_config activity_or_update, hash_or_str = active_record_config
36
36
  arr = build_from_db_config(hash_or_str)
37
37
  return unless arr&.any?
38
38
 
39
- arr.each do |a|
40
- next unless a
39
+ arr.each do |component|
40
+ next unless component
41
41
 
42
- if activity_or_update.is_a?(Contrast::Api::Dtm::Activity)
43
- activity_or_update.architectures << a
42
+ if activity_or_update.cs__is_a?(Contrast::Agent::Reporting::ApplicationUpdate)
43
+ activity_or_update.components << component
44
44
  else
45
- converted_comp = Contrast::Agent::Reporting::ArchitectureComponent.convert(a)
46
- activity_or_update.components << converted_comp
45
+ activity_or_update.attach_inventory(component)
47
46
  end
48
47
  end
49
48
  rescue StandardError => e
@@ -78,10 +77,15 @@ module Contrast
78
77
  # reporting.
79
78
  #
80
79
  # @param hash_or_str [Hash, String]
81
- # @return [Array<Contrast::Api::Dtm::ArchitectureComponent>, nil]
80
+ # @return [Array<Contrast::Agent::Reporting::ArchitectureComponent>, nil]
82
81
  def build_from_db_config hash_or_str
83
82
  return unless hash_or_str
84
83
 
84
+ # we need to handle types of HashConfig, which != Hash
85
+ # for example ActiveRecord::DatabaseConfigurations::HashConfig is type of active_record config
86
+ # but the method is not handling it properly
87
+ # so we need to handle it here and extract the hash
88
+ hash_or_str = hash_or_str.configuration_hash if hash_or_str.cs__respond_to?(:configuration_hash)
85
89
  if hash_or_str.is_a?(Hash)
86
90
  build_from_db_hash(hash_or_str)
87
91
  else
@@ -93,9 +97,9 @@ module Contrast
93
97
  # understandable by TeamServer.
94
98
  #
95
99
  # @param hash [Hash] the information used to open a database connection
96
- # @return [Array<Contrast::Api::Dtm::ArchitectureComponent>]
100
+ # @return [Array<Contrast::Agent::Reporting::ArchitectureComponent>]
97
101
  def build_from_db_hash hash
98
- ac = Contrast::Api::Dtm::ArchitectureComponent.build_database
102
+ ac = Contrast::Agent::Reporting::ArchitectureComponent.build_database
99
103
  ac.vendor = hash[:adapter] || hash[ADAPTER] || Contrast::Utils::ObjectShare::EMPTY_STRING
100
104
  ac.remote_host = host_from_hash(hash)
101
105
  ac.remote_port = port_from_hash(hash)
@@ -126,7 +130,7 @@ module Contrast
126
130
  # mysql+mysqlconnector://scott:tiger@localhost/foo # pragma: allowlist secret
127
131
  #
128
132
  # @param str [String] the DB connection string
129
- # @return [Array<Contrast::Api::Dtm::ArchitectureComponent>, nil]
133
+ # @return [Array<Contrast::Agent::Reporting::ArchitectureComponent>, nil]
130
134
  def build_from_db_string str
131
135
  adapter, hosts, database = split_connection_str(str)
132
136
  return unless adapter && hosts && database
@@ -135,7 +139,7 @@ module Contrast
135
139
  hosts.split(Contrast::Utils::ObjectShare::COMMA).map do |s|
136
140
  host, port = s.split(Contrast::Utils::ObjectShare::COLON)
137
141
 
138
- ac = Contrast::Api::Dtm::ArchitectureComponent.build_database
142
+ ac = Contrast::Agent::Reporting::ArchitectureComponent.build_database
139
143
  ac.vendor = Contrast::Utils::StringUtils.force_utf8(adapter)
140
144
  ac.remote_host = Contrast::Utils::StringUtils.force_utf8(host)
141
145
  ac.remote_port = port.to_i
@@ -13,9 +13,8 @@ module Contrast
13
13
  # in which database operations occur. It is responsible for deciding if
14
14
  # the given invocation is worth reporting or not.
15
15
  module DataStores
16
+ extend Contrast::Components::Logger::InstanceMethods
16
17
  class << self
17
- extend Contrast::Components::Logger::InstanceMethods
18
-
19
18
  # The key used in policy.json to indicate the database type to
20
19
  # report.
21
20
  DATA_STORE_MARKER = 'data_store'
@@ -180,7 +180,6 @@ module Contrast
180
180
  else
181
181
  request_handler.ruleset.postfilter
182
182
  request_handler.report_activity
183
- request_handler.send_activity_messages # TODO: RUBY-1438 -- remove
184
183
  end
185
184
  end
186
185
  # unsuccessful attack
@@ -169,9 +169,9 @@ module Contrast
169
169
  #
170
170
  # @param context [Contrast::Agent::RequestContext] the context of the
171
171
  # request in which this input is evaluated.
172
- # @param result [Contrast::Api::Dtm::AttackResult]
172
+ # @param result [Contrast::Agent::Reporting::AttackResult]
173
173
  def append_to_activity context, result
174
- context.activity.results << result if result
174
+ context.activity.attach_defend(result) if result
175
175
  end
176
176
 
177
177
  # With this we log to CEF
@@ -179,15 +179,11 @@ module Contrast
179
179
  # @param result [Contrast::Api::Dtm::AttackResult]
180
180
  # @param attack [Symbol] the type of message we want to send
181
181
  # @param value [String] the input value we want to log
182
- def cef_logging result, attack = :ineffective_attack, value = nil
183
- sample_to_json = Contrast::Api::Dtm::RaspRuleSample.to_controlled_hash(result.samples[0])
184
- outcome = if result.response.cs__is_a?(Hash)
185
- Contrast::Agent::Reporting::ResponseType.cs__const_get(result.response[:name])
186
- else
187
- Contrast::Api::Dtm::AttackResult::ResponseType.get_name_by_tag(result.response)
188
- end
189
- input_type = extract_input_type(sample_to_json[:user_input].input_type)
190
- input_value = value || sample_to_json[:user_input].value
182
+ def cef_logging result, attack = :ineffective_attack, value: nil
183
+ sample = result.samples[0]
184
+ outcome = result.response.to_s
185
+ input_type = sample.user_input.input_type.to_s
186
+ input_value = sample.user_input.value || value
191
187
  cef_logger.send(attack, result.rule_id, outcome, input_type, input_value)
192
188
  end
193
189
 
@@ -238,9 +234,9 @@ module Contrast
238
234
  def update_successful_attack_response context, ia_result, result, attack_string = nil
239
235
  case mode
240
236
  when Contrast::Api::Settings::ProtectionRule::Mode::MONITOR
241
- result.response = Contrast::Api::Dtm::AttackResult::ResponseType::MONITORED
237
+ result.response = Contrast::Agent::Reporting::ResponseType::MONITORED
242
238
  when Contrast::Api::Settings::ProtectionRule::Mode::BLOCK
243
- result.response = Contrast::Api::Dtm::AttackResult::ResponseType::BLOCKED
239
+ result.response = Contrast::Agent::Reporting::ResponseType::BLOCKED
244
240
  end
245
241
 
246
242
  ia_result.attack_count = ia_result.attack_count + 1 if ia_result
@@ -259,9 +255,9 @@ module Contrast
259
255
  def update_perimeter_attack_response context, ia_result, result
260
256
  if mode == Contrast::Api::Settings::ProtectionRule::Mode::BLOCK_AT_PERIMETER
261
257
  result.response = if blocked_rule?(ia_result)
262
- Contrast::Api::Dtm::AttackResult::ResponseType::BLOCKED
258
+ Contrast::Agent::Reporting::ResponseType::BLOCKED
263
259
  else
264
- Contrast::Api::Dtm::AttackResult::ResponseType::BLOCKED_AT_PERIMETER
260
+ Contrast::Agent::Reporting::ResponseType::BLOCKED_AT_PERIMETER
265
261
  end
266
262
  log_rule_matched(context, ia_result, result.response)
267
263
  elsif ia_result.nil? || ia_result.attack_count.zero?
@@ -276,9 +272,9 @@ module Contrast
276
272
  #
277
273
  # @param _context [Contrast::Agent::RequestContext] the context of
278
274
  # the current request
279
- # @return [Contrast::Api::Dtm::AttackResult]
275
+ # @return [Contrast::Agent::Reporting::AttackResult]
280
276
  def build_attack_result _context
281
- result = Contrast::Api::Dtm::AttackResult.new
277
+ result = Contrast::Agent::Reporting::AttackResult.new
282
278
  result.rule_id = rule_name
283
279
  result
284
280
  end
@@ -311,7 +307,7 @@ module Contrast
311
307
  end
312
308
 
313
309
  def build_base_sample context, ia_result
314
- Contrast::Api::Dtm::RaspRuleSample.build(context, ia_result)
310
+ Contrast::Agent::Reporting::RaspRuleSample.build(context, ia_result)
315
311
  end
316
312
 
317
313
  def log_rule_matched _context, ia_result, response, _matched_string = nil
@@ -366,9 +362,9 @@ module Contrast
366
362
  # determined to be an attack
367
363
  def assign_reporter_response_type ia_result
368
364
  if suspicious_rule?(ia_result) && Contrast::CONTRAST_SERVICE.use_agent_communication?
369
- Contrast::Api::Dtm::AttackResult::ResponseType::SUSPICIOUS
365
+ Contrast::Agent::Reporting::ResponseType::SUSPICIOUS
370
366
  else
371
- Contrast::Api::Dtm::AttackResult::ResponseType::PROBED
367
+ Contrast::Agent::Reporting::ResponseType::PROBED
372
368
  end
373
369
  end
374
370
  end
@@ -6,6 +6,7 @@ require 'contrast/utils/stack_trace_utils'
6
6
  require 'contrast/utils/object_share'
7
7
  require 'contrast/components/logger'
8
8
  require 'contrast/agent/reporting/input_analysis/input_type'
9
+ require 'contrast/agent/reporting/details/cmd_injection_details'
9
10
 
10
11
  module Contrast
11
12
  module Agent
@@ -97,17 +98,17 @@ module Contrast
97
98
  # evaluation
98
99
  def build_sample context, input_analysis_result, candidate_string, **_kwargs
99
100
  sample = build_base_sample(context, input_analysis_result)
100
- sample.cmdi = Contrast::Api::Dtm::CmdInjectionDetails.new
101
+ sample.details = Contrast::Agent::Reporting::Details::CmdInjectionDetails.new
101
102
 
102
103
  command = candidate_string || input_analysis_result.value
103
104
  command = Contrast::Utils::StringUtils.protobuf_safe_string(command)
104
- sample.cmdi.command = command
105
- sample.cmdi.end_idx = command.length
105
+ sample.details.cmd = command
106
+ sample.details.end_idx = command.length
106
107
 
107
108
  # This is a special case where the user input is UNKNOWN_USER_INPUT but
108
109
  # we want to send the attack value
109
110
  if input_analysis_result.nil?
110
- ui = Contrast::Api::Dtm::UserInput.new
111
+ ui = Contrast::Agent::Reporting::UserInput.new
111
112
  ui.input_type = :UNKNOWN
112
113
  ui.value = command
113
114
  sample.user_input = ui
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/protect/rule/base'
5
+ require 'contrast/agent/reporting/details/untrusted_deserialization_details'
5
6
  require 'contrast/components/logger'
6
7
 
7
8
  module Contrast
@@ -116,7 +117,7 @@ module Contrast
116
117
  ia_result = build_evaluation(gadget_command)
117
118
  result = build_attack_with_match(context, ia_result, nil, gadget_command, **kwargs)
118
119
  append_to_activity(context, result)
119
- cef_logging(result, :successful_attack, gadget_command)
120
+ cef_logging(result, :successful_attack, value: gadget_command)
120
121
  raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE)) if blocked?
121
122
  end
122
123
 
@@ -135,13 +136,13 @@ module Contrast
135
136
  # to render this attack event in TeamServer.
136
137
  def build_sample context, input_analysis_result, _candidate_string, **kwargs
137
138
  sample = build_base_sample(context, input_analysis_result)
138
- sample.untrusted_deserialization = Contrast::Api::Dtm::UntrustedDeserializationDetails.new
139
+ sample.details = Contrast::Agent::Reporting::Details::UntrustedDeserializationDetails.new
139
140
 
140
141
  deserializer = Contrast::Utils::StringUtils.protobuf_safe_string(kwargs[:GADGET_TYPE])
141
- sample.untrusted_deserialization.deserializer = deserializer
142
+ sample.details.deserializer = deserializer
142
143
 
143
144
  command = !!kwargs[:COMMAND_SCOPE]
144
- sample.untrusted_deserialization.command = command
145
+ sample.details.cmd = command
145
146
 
146
147
  sample
147
148
  end
@@ -3,6 +3,8 @@
3
3
 
4
4
  require 'contrast/agent/protect/rule/base_service'
5
5
  require 'contrast/utils/stack_trace_utils'
6
+ require 'contrast/agent/reporting/details/path_traversal_details'
7
+ require 'contrast/agent/reporting/details/path_traversal_semantic_analysis_details'
6
8
 
7
9
  module Contrast
8
10
  module Agent
@@ -48,7 +50,7 @@ module Contrast
48
50
  append_to_activity(context, result)
49
51
  return unless blocked?
50
52
 
51
- cef_logging(result, :successful_attack, path)
53
+ cef_logging(result, :successful_attack)
52
54
  raise(Contrast::SecurityException.new(self,
53
55
  "Path Traversal rule triggered. Call to File.#{ method } blocked."))
54
56
  end
@@ -65,9 +67,9 @@ module Contrast
65
67
  # evaluation
66
68
  def build_sample context, input_analysis_result, path, **_kwargs
67
69
  sample = build_base_sample(context, input_analysis_result)
68
- sample.path_traversal = Contrast::Api::Dtm::PathTraversalDetails.new
70
+ sample.details = Contrast::Agent::Reporting::Details::PathTraversalDetails.new
69
71
  path ||= input_analysis_result.value
70
- sample.path_traversal.path = Contrast::Utils::StringUtils.protobuf_safe_string(path)
72
+ sample.details.path = Contrast::Utils::StringUtils.protobuf_safe_string(path)
71
73
  sample
72
74
  end
73
75
 
@@ -76,17 +78,17 @@ module Contrast
76
78
  # Build a subclass of the RaspRuleSample if the sample matches
77
79
  def build_rep_sample context, path
78
80
  sample = build_base_sample(context, nil)
79
- sample.path_traversal_semantic = Contrast::Api::Dtm::PathTraversalSemanticAnalysisDetails.new
81
+ sample.details = Contrast::Agent::Reporting::Details::PathTraversalSemanticAnalysisDetails.new
80
82
  path = Contrast::Utils::StringUtils.protobuf_safe_string(path)
81
- sample.path_traversal_semantic.path = path
83
+ sample.details.path = path
82
84
 
83
85
  if custom_code_access_sysfile_enabled? && custom_code_accessing_system_file?(path)
84
- sample.path_traversal_semantic.findings << :CUSTOM_CODE_ACCESSING_SYSTEM_FILES
86
+ sample.details.findings << :CUSTOM_CODE_ACCESSING_SYSTEM_FILES
85
87
  return sample
86
88
  end
87
89
 
88
90
  if common_file_exploits_enabled? && contains_known_attack_signatures?(path)
89
- sample.path_traversal_semantic.findings << :COMMON_FILE_EXPLOITS
91
+ sample.details.findings << :COMMON_FILE_EXPLOITS
90
92
  return sample
91
93
  end
92
94
 
@@ -3,6 +3,8 @@
3
3
 
4
4
  require 'contrast/agent/protect/rule/base'
5
5
  require 'contrast/agent/protect/rule/base_service'
6
+ require 'contrast/agent/reporting/details/sqli_details'
7
+ require 'contrast/agent/reporting/details/no_sqli_details'
6
8
 
7
9
  module Contrast
8
10
  module Agent
@@ -18,16 +20,16 @@ module Contrast
18
20
  # @candidate_string [String] the value of the input which may be an attack
19
21
  # @kwargs [Hash] key - value pairs of context individual rules need to build out details
20
22
  # to send to the Service to tell the story of the attack
21
- # @return [Contrast::Api::Dtm::RaspRuleSample] the sample from this attack
23
+ # @return [Contrast::Agent::Reporting::RaspRuleSample] the sample from this attack
22
24
  module SqliSample
23
25
  def build_sample context, input_analysis_result, candidate_string, **kwargs
24
26
  sqli_sample = build_base_sample(context, input_analysis_result)
25
- sqli_sample.sqli = Contrast::Api::Dtm::SqlInjectionDetails.new
26
- sqli_sample.sqli.query = Contrast::Utils::StringUtils.protobuf_safe_string(candidate_string)
27
- sqli_sample.sqli.start_idx = kwargs[:start_idx]
28
- sqli_sample.sqli.end_idx = kwargs[:end_idx]
29
- sqli_sample.sqli.boundary_overrun_idx = kwargs[:boundary_overrun_idx].to_i
30
- sqli_sample.sqli.input_boundary_idx = kwargs[:input_boundary_idx].to_i
27
+ sqli_sample.details = Contrast::Agent::Reporting::Details::SqliDetails.new
28
+ sqli_sample.details.query = Contrast::Utils::StringUtils.protobuf_safe_string(candidate_string)
29
+ sqli_sample.details.start_idx = kwargs[:start_idx]
30
+ sqli_sample.details.end_idx = kwargs[:end_idx]
31
+ sqli_sample.details.boundary_overrun_idx = kwargs[:boundary_overrun_idx].to_i
32
+ sqli_sample.details.input_boundary_idx = kwargs[:input_boundary_idx].to_i
31
33
  sqli_sample
32
34
  end
33
35
  end
@@ -41,16 +43,16 @@ module Contrast
41
43
  # @candidate_string [String] the value of the input which may be an attack
42
44
  # @kwargs [Hash] key - value pairs of context individual rules need to build out details
43
45
  # to send to the Service to tell the story of the attack
44
- # @return [Contrast::Api::Dtm::RaspRuleSample] the sample from this attack
46
+ # @return [Contrast::Agent::Reporting::RaspRuleSample] the sample from this attack
45
47
  module NoSqliSample
46
48
  def build_sample context, input_analysis_result, candidate_string, **kwargs
47
49
  no_sqli_sample = build_base_sample(context, input_analysis_result)
48
- no_sqli_sample.no_sqli = Contrast::Api::Dtm::NoSqlInjectionDetails.new
49
- no_sqli_sample.no_sqli.query = Contrast::Utils::StringUtils.protobuf_safe_string(candidate_string)
50
- no_sqli_sample.no_sqli.start_idx = kwargs[:start_idx].to_i
51
- no_sqli_sample.no_sqli.end_idx = kwargs[:end_idx].to_i
52
- no_sqli_sample.no_sqli.boundary_overrun_idx = kwargs[:boundary_overrun_idx].to_i
53
- no_sqli_sample.no_sqli.input_boundary_idx = kwargs[:input_boundary_idx].to_i
50
+ no_sqli_sample.details = Contrast::Agent::Reporting::Details::NoSqliDetails.new
51
+ no_sqli_sample.details.query = Contrast::Utils::StringUtils.protobuf_safe_string(candidate_string)
52
+ no_sqli_sample.details.start_idx = kwargs[:start_idx].to_i
53
+ no_sqli_sample.details.end_idx = kwargs[:end_idx].to_i
54
+ no_sqli_sample.details.boundary_overrun_idx = kwargs[:boundary_overrun_idx].to_i
55
+ no_sqli_sample.details.input_boundary_idx = kwargs[:input_boundary_idx].to_i
54
56
  no_sqli_sample
55
57
  end
56
58
  end
@@ -61,7 +61,7 @@ module Contrast
61
61
 
62
62
  append_to_activity(context, result)
63
63
 
64
- cef_logging(result, :successful_attack, query_string)
64
+ cef_logging(result, :successful_attack, value: query_string)
65
65
  raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE)) if blocked?
66
66
  end
67
67
  end
@@ -2,6 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/protect/rule/base'
5
+ require 'contrast/agent/reporting/details/xxe_details'
6
+ require 'contrast/agent/reporting/details/xxe_match'
7
+ require 'contrast/agent/reporting/details/xxe_wrapper'
5
8
  require 'contrast/utils/timer'
6
9
  require 'contrast/components/logger'
7
10
 
@@ -62,7 +65,7 @@ module Contrast
62
65
  append_to_activity(context, result)
63
66
  return unless blocked?
64
67
 
65
- cef_logging(result, :successful_attack, xml)
68
+ cef_logging(result, :successful_attack, value: xml)
66
69
  raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE))
67
70
  end
68
71
 
@@ -105,7 +108,7 @@ module Contrast
105
108
  entity_wrapper = Contrast::Agent::Protect::Rule::Xxe::EntityWrapper.new(ss.matched)
106
109
  next unless entity_wrapper.external_entity?
107
110
 
108
- xxe_details ||= Contrast::Api::Dtm::XxeDetails.new
111
+ xxe_details ||= Contrast::Agent::Reporting::Details::XxeDetails.new
109
112
  xxe_details.declared_entities << build_match(ss)
110
113
  xxe_details.entities_resolved << build_wrapper(entity_wrapper)
111
114
  end
@@ -119,12 +122,12 @@ module Contrast
119
122
  def build_sample context, ia_result, _url, **kwargs
120
123
  sample = build_base_sample(context, ia_result)
121
124
  sample.user_input = build_user_input(ia_result)
122
- sample.xxe = kwargs[:details]
125
+ sample.details = kwargs[:details]
123
126
  sample
124
127
  end
125
128
 
126
129
  def build_user_input ia_result
127
- input = Contrast::Api::Dtm::UserInput.new
130
+ input = Contrast::Agent::Reporting::UserInput.new
128
131
  input.key = INPUT_NAME
129
132
  input.input_type = :UNKNOWN
130
133
  input.document_type = :XML
@@ -146,14 +149,14 @@ module Contrast
146
149
  end
147
150
 
148
151
  def build_match string_scanner
149
- match = Contrast::Api::Dtm::XxeMatch.new
152
+ match = Contrast::Agent::Reporting::Details::XxeMatch.new
150
153
  match.end_idx = string_scanner.pos.to_i
151
154
  match.start_idx = match.end_idx - string_scanner.matched_size
152
155
  match
153
156
  end
154
157
 
155
158
  def build_wrapper entity_wrapper
156
- wrapper = Contrast::Api::Dtm::XxeWrapper.new
159
+ wrapper = Contrast::Agent::Reporting::Details::XxeWrapper.new
157
160
  wrapper.system_id = Contrast::Utils::StringUtils.protobuf_safe_string(entity_wrapper.system_id)
158
161
  wrapper.public_id = Contrast::Utils::StringUtils.protobuf_safe_string(entity_wrapper.public_id)
159
162
  wrapper
@@ -57,6 +57,14 @@ module Contrast
57
57
  def tags= tags
58
58
  @_tags = tags if tags.is_a?(String)
59
59
  end
60
+
61
+ def details
62
+ @_details ||= {}
63
+ end
64
+
65
+ def details= protect_details
66
+ @_details = protect_details if protect_details.is_a?(Contrast::Agent::Reporting::Details::ProtectRuleDetails)
67
+ end
60
68
  end
61
69
  end
62
70
  end