contrast-agent 6.14.0 → 6.15.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/{assess.rb → assess/assess.rb} +1 -1
  3. data/lib/contrast/agent/{module_data.rb → assess/module_data.rb} +0 -0
  4. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +3 -0
  5. data/lib/contrast/agent/assess/policy/policy_node.rb +3 -2
  6. data/lib/contrast/agent/assess/policy/propagation_method.rb +2 -2
  7. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +0 -1
  8. data/lib/contrast/agent/assess/policy/source_method.rb +1 -1
  9. data/lib/contrast/agent/assess/policy/trigger_method.rb +36 -1
  10. data/lib/contrast/agent/{excluder.rb → excluder/excluder.rb} +0 -0
  11. data/lib/contrast/agent/{exclusion_matcher.rb → excluder/exclusion_matcher.rb} +0 -0
  12. data/lib/contrast/agent/{at_exit_hook.rb → hooks/at_exit_hook.rb} +0 -0
  13. data/lib/contrast/agent/{tracepoint_hook.rb → hooks/tracepoint_hook.rb} +0 -0
  14. data/lib/contrast/agent/inventory/database_config.rb +1 -0
  15. data/lib/contrast/agent/{inventory.rb → inventory/inventory.rb} +0 -0
  16. data/lib/contrast/agent/{middleware.rb → middleware/middleware.rb} +3 -3
  17. data/lib/contrast/agent/{static_analysis.rb → middleware/static_analysis.rb} +0 -0
  18. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +5 -5
  19. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +1 -1
  20. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +1 -1
  21. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +1 -1
  22. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
  23. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -1
  24. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -1
  25. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  26. data/lib/contrast/agent/protect/rule/base.rb +121 -134
  27. data/lib/contrast/agent/protect/rule/{bot_blocker.rb → bot_blocker/bot_blocker.rb} +2 -2
  28. data/lib/contrast/agent/protect/rule/{cmd_injection.rb → cmdi/cmd_injection.rb} +1 -1
  29. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +3 -3
  30. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +1 -1
  31. data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +2 -2
  32. data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +2 -2
  33. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +1 -1
  34. data/lib/contrast/agent/protect/rule/{deserialization.rb → deserialization/deserialization.rb} +2 -2
  35. data/lib/contrast/agent/protect/rule/{no_sqli.rb → no_sqli/no_sqli.rb} +3 -3
  36. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +1 -1
  37. data/lib/contrast/agent/protect/rule/{path_traversal.rb → path_traversal/path_traversal.rb} +2 -2
  38. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +3 -3
  39. data/lib/contrast/agent/protect/rule/{sql_sample_builder.rb → sqli/sql_sample_builder.rb} +0 -1
  40. data/lib/contrast/agent/protect/rule/{sqli.rb → sqli/sqli.rb} +2 -2
  41. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +1 -1
  42. data/lib/contrast/agent/protect/rule/{unsafe_file_upload.rb → unsafe_file_upload/unsafe_file_upload.rb} +2 -2
  43. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +1 -1
  44. data/lib/contrast/agent/protect/rule/utils/builders.rb +111 -0
  45. data/lib/contrast/agent/protect/rule/utils/filters.rb +110 -0
  46. data/lib/contrast/agent/protect/rule/{xss.rb → xss/xss.rb} +2 -2
  47. data/lib/contrast/agent/protect/rule/{xxe.rb → xxe/xxe.rb} +2 -2
  48. data/lib/contrast/agent/protect/rule.rb +8 -9
  49. data/lib/contrast/agent/{disable_reaction.rb → reactions/disable_reaction.rb} +0 -0
  50. data/lib/contrast/agent/reporting/reporter.rb +1 -1
  51. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +3 -3
  52. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -1
  53. data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +1 -1
  54. data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +1 -1
  55. data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +1 -1
  56. data/lib/contrast/agent/{request.rb → request/request.rb} +0 -0
  57. data/lib/contrast/agent/{request_context.rb → request/request_context.rb} +3 -3
  58. data/lib/contrast/agent/{request_context_extend.rb → request/request_context_extend.rb} +0 -0
  59. data/lib/contrast/agent/{request_handler.rb → request/request_handler.rb} +0 -0
  60. data/lib/contrast/agent/{response.rb → response/response.rb} +0 -0
  61. data/lib/contrast/agent/{scope.rb → scope/scope.rb} +0 -0
  62. data/lib/contrast/agent/telemetry/base.rb +2 -2
  63. data/lib/contrast/agent/{telemetry.rb → telemetry/telemetry.rb} +0 -0
  64. data/lib/contrast/agent/{thread.rb → thread/thread.rb} +0 -0
  65. data/lib/contrast/agent/{thread_watcher.rb → thread/thread_watcher.rb} +0 -0
  66. data/lib/contrast/agent/{worker_thread.rb → thread/worker_thread.rb} +0 -0
  67. data/lib/contrast/agent/version.rb +1 -1
  68. data/lib/contrast/agent.rb +11 -11
  69. data/lib/contrast/components/agent.rb +1 -1
  70. data/lib/contrast/components/assess.rb +1 -0
  71. data/lib/contrast/{agent → components}/rule_set.rb +0 -0
  72. data/lib/contrast/components/scope.rb +1 -1
  73. data/lib/contrast/components/settings.rb +1 -1
  74. data/lib/contrast/extension/assess/exec_trigger.rb +1 -1
  75. data/lib/contrast/extension/assess/string.rb +4 -3
  76. data/lib/contrast.rb +1 -1
  77. data/ruby-agent.gemspec +4 -2
  78. metadata +53 -58
  79. data/lib/contrast/agent/protect/rule/base_service.rb +0 -175
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 577b0810f45b302615af1f151ebb6b772d76c0bccd460057022f5fbadf065d73
4
- data.tar.gz: f3e882dd5e3d7e63e4cf09f37733acd02ad3b70b2d195b8a9377175cfe1b4330
3
+ metadata.gz: e4f1f41a4e9c4b720867bf41832aceec4b4d4b2e55efafc086f5bf9a14f56401
4
+ data.tar.gz: 575fbbe0b929cc700daa495403325a27ff90cd92b44f549c9fd44dde7f25ec55
5
5
  SHA512:
6
- metadata.gz: 168ea3d43d19acbe29a80b9b244a91c29b0f7c091137b7a0575edd39f763ec013e1402bc1337c167e8147738428813b7d1010e92a8e102aa3b72570685d73605
7
- data.tar.gz: ddbf43ffe314bfd53c19687dc7bfc549a1b5374a43ede461a73487519ef263672f6dc7fe449140159c5e26587a55052b132242c20b1673d2dbed3d882340f157
6
+ metadata.gz: a6a321d684f4a220f3eed2cc85ddac8985a4720216beb062d9bc9c75322bbf9d626b96c83f8f0698acdf611fe0ba4dabfa3f908cb6d12a400c3ee05e3d850c05
7
+ data.tar.gz: 6de14c43bfd6bb54f6fc6da174c1affe91e2712dc6438d69fa6b87404336e8d68691f84339ba756a4a85f5d70ac8b17488a96e786faa77099c5e34963c8e0ffd
@@ -9,7 +9,7 @@ module Contrast
9
9
  # point of require for this functionality.
10
10
  module Assess
11
11
  require 'contrast/agent/assess/tracker'
12
- require 'contrast/agent/module_data'
12
+ require 'contrast/agent/assess/module_data'
13
13
  require 'contrast/agent/assess/policy/preshift'
14
14
 
15
15
  # Dynamic Sources
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/patching/policy/method_policy'
5
+ require 'contrast/components/logger'
5
6
 
6
7
  module Contrast
7
8
  module Agent
@@ -15,6 +16,8 @@ module Contrast
15
16
  READ_TABLE = 'readTable'
16
17
  READ_COLUMN = 'readColumn'
17
18
  class << self
19
+ include Contrast::Components::Logger::InstanceMethods
20
+
18
21
  # Given a Class representing a table in a Database and a map of
19
22
  # methods representing columns, generate sources for each method
20
23
  # such that calls to that method will result in a Source Event.
@@ -38,6 +38,7 @@ module Contrast
38
38
  capitalize!
39
39
  chomp
40
40
  to_s
41
+ to_str
41
42
  downcase
42
43
  downcase!
43
44
  lstrip
@@ -45,7 +46,7 @@ module Contrast
45
46
  upcase!
46
47
  upcase
47
48
  ].cs__freeze
48
- TO_S = 'to_s'
49
+ TO_S = %w[to_s to_str].cs__freeze
49
50
 
50
51
  def initialize policy_hash = {}
51
52
  super(policy_hash)
@@ -63,7 +64,7 @@ module Contrast
63
64
  # String#to_s => self or string. This method is included here to cover the situations such as
64
65
  # String.to_s.html_safe, where normally the dynamic sources properties get lost. To solve this
65
66
  # we will simply return the original object here.
66
- return true if @_use_original_object && policy_hash[JSON_METHOD_NAME] == TO_S
67
+ return true if @_use_original_object && TO_S.include?(policy_hash[JSON_METHOD_NAME])
67
68
 
68
69
  @_use_original_object &&
69
70
  # Check if method name ends with a (!) bang unless is the to_s method:
@@ -92,11 +92,11 @@ module Contrast
92
92
  # propagation event.
93
93
  # @param target [Object] the Target to which to propagate.
94
94
  def apply_tags propagation_node, target
95
- return unless propagation_node.tags
95
+ return unless (propagation_tags = propagation_node.tags)
96
96
  return unless (properties = Contrast::Agent::Assess::Tracker.properties(target))
97
97
 
98
98
  length = Contrast::Utils::StringUtils.ret_length(target)
99
- propagation_node.tags.each do |tag|
99
+ propagation_tags.each do |tag|
100
100
  properties.add_tag(tag, 0...length)
101
101
  end
102
102
  end
@@ -50,7 +50,6 @@ module Contrast
50
50
  next if known_tainted&.include?(key)
51
51
  next unless (properties = Contrast::Agent::Assess::Tracker.properties!(value))
52
52
 
53
- # TODO: RUBY-540 handle sanitization, handle nested objects
54
53
  Contrast::Agent::Assess::Policy::PropagationMethod.apply_tags(propagation_node, value)
55
54
  event_data = Contrast::Agent::Assess::Events::EventData.new(propagation_node,
56
55
  value, preshift.object,
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'set'
5
5
  require 'contrast/agent/assess/policy/source_validation/source_validation'
6
- require 'contrast/agent/excluder'
6
+ require 'contrast/agent/excluder/excluder'
7
7
  require 'contrast/components/logger'
8
8
  require 'contrast/utils/object_share'
9
9
  require 'contrast/utils/sha256_builder'
@@ -2,9 +2,10 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/assess/policy/trigger_validation/trigger_validation'
5
- require 'contrast/agent/excluder'
5
+ require 'contrast/agent/excluder/excluder'
6
6
  require 'contrast/components/logger'
7
7
  require 'contrast/utils/object_share'
8
+ require 'contrast/utils/duck_utils'
8
9
  require 'contrast/utils/sha256_builder'
9
10
  require 'contrast/utils/assess/trigger_method_utils'
10
11
  require 'contrast/agent/assess/events/event_data'
@@ -99,6 +100,7 @@ module Contrast
99
100
  return if excluded_by_input_and_rule?(request, finding, trigger_node.rule_id)
100
101
 
101
102
  finding.hash_code = Contrast::Utils::HashDigest.generate_event_hash(finding, source, request)
103
+ check_for_stored_xss(finding)
102
104
  finding
103
105
  rescue StandardError => e
104
106
  logger.error('Unable to build a finding', e, rule: trigger_node.rule_id, node_id: trigger_node.id)
@@ -188,6 +190,39 @@ module Contrast
188
190
  def excluded_by_input_and_rule? request, finding, rule_id
189
191
  Contrast::SETTINGS.excluder.assess_excluded_by_input_and_rule?(request, finding, rule_id)
190
192
  end
193
+
194
+ # Handles the Stored Xss rule. If a vector is stored in the database
195
+ def check_for_stored_xss finding
196
+ return unless finding && finding.rule_id == 'reflected-xss'
197
+
198
+ # Check for database tainted event propagation:
199
+ if finding.events.select { |event| event.reportable_tags.include?('DATABASE_WRITE') }.
200
+ any? && !Contrast::ASSESS.disabled_rules.include?('stored-xss')
201
+
202
+ # Override 'reflected-xss' => 'stored-xss'
203
+ finding.instance_variable_set(:@rule_id, 'stored-xss')
204
+ extract_dynamic_source_info(finding)
205
+ finding
206
+ end
207
+ end
208
+
209
+ def extract_dynamic_source_info finding
210
+ return unless finding
211
+
212
+ creation_events = finding.events.select { |e| e.action == :CREATION }
213
+ source_event_policy = creation_events[0].policy_node if creation_events.any?
214
+ properties = source_event_policy.properties if source_event_policy
215
+ # Properties example:
216
+ # => {"dynamic_source_id"=>"Assess:Source:Comment#message",
217
+ # "dynamic_source_name"=>"Comment.message",
218
+ # "readTable"=>"Comment",
219
+ # "readColumn"=>:message,
220
+ # "writeDateTimeUtc"=>1675087341948,
221
+ # "writeRequestUrl"=>"/comments"}
222
+ return if Contrast::Utils::DuckUtils.empty_duck?(properties)
223
+
224
+ finding.instance_variable_set(:@properties, finding.properties.merge(properties))
225
+ end
191
226
  end
192
227
  end
193
228
  end
@@ -54,6 +54,7 @@ module Contrast
54
54
  # @return [Hash]
55
55
  def active_record_config
56
56
  return @_active_record_config if instance_variable_defined?(:@_active_record_config)
57
+ return unless defined?(ActiveRecord) && defined?(ActiveRecord::Base)
57
58
 
58
59
  @_active_record_config = if ActiveRecord::Base.cs__respond_to?(:connection_db_config)
59
60
  ActiveRecord::Base.connection_db_config
@@ -10,9 +10,9 @@ require 'contrast/utils/object_share'
10
10
  require 'contrast/components/logger'
11
11
  require 'contrast/components/scope'
12
12
  require 'contrast/utils/heap_dump_util'
13
- require 'contrast/agent/telemetry'
14
- require 'contrast/agent/request_handler'
15
- require 'contrast/agent/static_analysis'
13
+ require 'contrast/agent/telemetry/telemetry'
14
+ require 'contrast/agent/request/request_handler'
15
+ require 'contrast/agent/middleware/static_analysis'
16
16
  require 'contrast/agent/telemetry/startup_metrics_event'
17
17
  require 'contrast/agent/protect/input_analyzer/input_analyzer'
18
18
  require 'contrast/utils/middleware_utils'
@@ -4,18 +4,18 @@
4
4
  require 'contrast/agent/reporting/input_analysis/input_type'
5
5
  require 'contrast/agent/reporting/input_analysis/score_level'
6
6
  require 'contrast/agent/reporting/input_analysis/input_analysis'
7
- require 'contrast/agent/protect/rule/bot_blocker'
7
+ require 'contrast/agent/protect/rule/bot_blocker/bot_blocker'
8
8
  require 'contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification'
9
9
  require 'contrast/agent/protect/rule/cmdi/cmdi_input_classification'
10
- require 'contrast/agent/protect/rule/no_sqli'
10
+ require 'contrast/agent/protect/rule/no_sqli/no_sqli'
11
11
  require 'contrast/agent/protect/rule/no_sqli/no_sqli_input_classification'
12
12
  require 'contrast/agent/protect/rule/sqli/sqli_input_classification'
13
13
  require 'contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification'
14
- require 'contrast/agent/protect/rule/unsafe_file_upload'
15
- require 'contrast/agent/protect/rule/path_traversal'
14
+ require 'contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload'
15
+ require 'contrast/agent/protect/rule/path_traversal/path_traversal'
16
16
  require 'contrast/agent/protect/rule/path_traversal/path_traversal_input_classification'
17
17
  require 'contrast/agent/protect/rule/xss/reflected_xss_input_classification'
18
- require 'contrast/agent/protect/rule/xss'
18
+ require 'contrast/agent/protect/rule/xss/xss'
19
19
  require 'contrast/components/logger'
20
20
  require 'contrast/utils/object_share'
21
21
  require 'json'
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/worker_thread'
4
+ require 'contrast/agent/thread/worker_thread'
5
5
  require 'contrast/agent/reporting/input_analysis/input_analysis_result'
6
6
  require 'contrast/agent/reporting/input_analysis/score_level'
7
7
  require 'contrast/agent/reporting/reporting_events/application_activity'
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/cmd_injection'
4
+ require 'contrast/agent/protect/rule/cmdi/cmd_injection'
5
5
  require 'contrast/agent/protect/policy/applies_deserialization_rule'
6
6
  require 'contrast/agent/protect/policy/rule_applicator'
7
7
 
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/deserialization'
4
+ require 'contrast/agent/protect/rule/deserialization/deserialization'
5
5
  require 'contrast/agent/protect/policy/rule_applicator'
6
6
 
7
7
  module Contrast
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/no_sqli'
4
+ require 'contrast/agent/protect/rule/no_sqli/no_sqli'
5
5
  require 'contrast/agent/protect/policy/rule_applicator'
6
6
 
7
7
  module Contrast
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/path_traversal'
4
+ require 'contrast/agent/protect/rule/path_traversal/path_traversal'
5
5
  require 'contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass'
6
6
  require 'contrast/agent/protect/policy/rule_applicator'
7
7
  require 'contrast/utils/object_share'
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/sqli'
4
+ require 'contrast/agent/protect/rule/sqli/sqli'
5
5
  require 'contrast/agent/protect/policy/rule_applicator'
6
6
 
7
7
  module Contrast
@@ -1,7 +1,7 @@
1
1
  # Copyright (c) 2023 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/agent/protect/rule/xxe'
4
+ require 'contrast/agent/protect/rule/xxe/xxe'
5
5
  require 'contrast/agent/protect/policy/rule_applicator'
6
6
  require 'contrast/utils/object_share'
7
7