contrast-agent 6.13.0 → 6.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) 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/assess/policy/trigger_validation/redos_validator.rb +1 -1
  11. data/lib/contrast/agent/{excluder.rb → excluder/excluder.rb} +0 -0
  12. data/lib/contrast/agent/{exclusion_matcher.rb → excluder/exclusion_matcher.rb} +0 -0
  13. data/lib/contrast/agent/{at_exit_hook.rb → hooks/at_exit_hook.rb} +0 -0
  14. data/lib/contrast/agent/{tracepoint_hook.rb → hooks/tracepoint_hook.rb} +0 -0
  15. data/lib/contrast/agent/inventory/database_config.rb +1 -0
  16. data/lib/contrast/agent/{inventory.rb → inventory/inventory.rb} +0 -0
  17. data/lib/contrast/agent/{middleware.rb → middleware/middleware.rb} +3 -3
  18. data/lib/contrast/agent/{static_analysis.rb → middleware/static_analysis.rb} +0 -0
  19. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +5 -5
  20. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +1 -1
  21. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +1 -1
  22. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +1 -1
  23. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
  24. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -1
  25. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -1
  26. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  27. data/lib/contrast/agent/protect/rule/base.rb +121 -134
  28. data/lib/contrast/agent/protect/rule/{bot_blocker.rb → bot_blocker/bot_blocker.rb} +2 -2
  29. data/lib/contrast/agent/protect/rule/{cmd_injection.rb → cmdi/cmd_injection.rb} +1 -1
  30. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +3 -3
  31. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +1 -1
  32. data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +2 -2
  33. data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +2 -2
  34. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +1 -1
  35. data/lib/contrast/agent/protect/rule/{deserialization.rb → deserialization/deserialization.rb} +2 -2
  36. data/lib/contrast/agent/protect/rule/{no_sqli.rb → no_sqli/no_sqli.rb} +3 -3
  37. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +1 -1
  38. data/lib/contrast/agent/protect/rule/{path_traversal.rb → path_traversal/path_traversal.rb} +2 -2
  39. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +3 -3
  40. data/lib/contrast/agent/protect/rule/{sql_sample_builder.rb → sqli/sql_sample_builder.rb} +0 -1
  41. data/lib/contrast/agent/protect/rule/{sqli.rb → sqli/sqli.rb} +2 -2
  42. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +1 -1
  43. data/lib/contrast/agent/protect/rule/{unsafe_file_upload.rb → unsafe_file_upload/unsafe_file_upload.rb} +2 -2
  44. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +1 -1
  45. data/lib/contrast/agent/protect/rule/utils/builders.rb +111 -0
  46. data/lib/contrast/agent/protect/rule/utils/filters.rb +110 -0
  47. data/lib/contrast/agent/protect/rule/{xss.rb → xss/xss.rb} +2 -2
  48. data/lib/contrast/agent/protect/rule/{xxe.rb → xxe/xxe.rb} +2 -2
  49. data/lib/contrast/agent/protect/rule.rb +8 -9
  50. data/lib/contrast/agent/{disable_reaction.rb → reactions/disable_reaction.rb} +0 -0
  51. data/lib/contrast/agent/reporting/reporter.rb +1 -1
  52. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +3 -3
  53. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -1
  54. data/lib/contrast/agent/reporting/reporting_workers/application_server_worker.rb +1 -1
  55. data/lib/contrast/agent/reporting/reporting_workers/reporter_heartbeat.rb +1 -1
  56. data/lib/contrast/agent/reporting/reporting_workers/server_settings_worker.rb +1 -1
  57. data/lib/contrast/agent/{request.rb → request/request.rb} +0 -0
  58. data/lib/contrast/agent/{request_context.rb → request/request_context.rb} +3 -3
  59. data/lib/contrast/agent/{request_context_extend.rb → request/request_context_extend.rb} +0 -0
  60. data/lib/contrast/agent/{request_handler.rb → request/request_handler.rb} +0 -0
  61. data/lib/contrast/agent/{response.rb → response/response.rb} +0 -0
  62. data/lib/contrast/agent/{scope.rb → scope/scope.rb} +0 -0
  63. data/lib/contrast/agent/telemetry/base.rb +2 -2
  64. data/lib/contrast/agent/{telemetry.rb → telemetry/telemetry.rb} +0 -0
  65. data/lib/contrast/agent/{thread.rb → thread/thread.rb} +0 -0
  66. data/lib/contrast/agent/{thread_watcher.rb → thread/thread_watcher.rb} +0 -0
  67. data/lib/contrast/agent/{worker_thread.rb → thread/worker_thread.rb} +0 -0
  68. data/lib/contrast/agent/version.rb +1 -1
  69. data/lib/contrast/agent.rb +11 -11
  70. data/lib/contrast/components/agent.rb +1 -1
  71. data/lib/contrast/components/assess.rb +1 -0
  72. data/lib/contrast/{agent → components}/rule_set.rb +0 -0
  73. data/lib/contrast/components/scope.rb +1 -1
  74. data/lib/contrast/components/settings.rb +1 -1
  75. data/lib/contrast/config/validate.rb +140 -0
  76. data/lib/contrast/config/yaml_file.rb +129 -0
  77. data/lib/contrast/extension/assess/exec_trigger.rb +1 -1
  78. data/lib/contrast/extension/assess/string.rb +4 -3
  79. data/lib/contrast/tasks/config.rb +7 -118
  80. data/lib/contrast/utils/middleware_utils.rb +4 -0
  81. data/lib/contrast.rb +1 -1
  82. data/ruby-agent.gemspec +6 -3
  83. metadata +56 -60
  84. 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: bf537fe7f51e1701577cb567c81862d9ed3b9eaadf89d45da26ddc65e9135afb
4
- data.tar.gz: b344f21256b15416fb395ed6f91880d4579b39d9bdb331df9492965ddf385129
3
+ metadata.gz: e4f1f41a4e9c4b720867bf41832aceec4b4d4b2e55efafc086f5bf9a14f56401
4
+ data.tar.gz: 575fbbe0b929cc700daa495403325a27ff90cd92b44f549c9fd44dde7f25ec55
5
5
  SHA512:
6
- metadata.gz: cab435e1cfaf07a8f5c101805d3ca0046062071e10d61e3fcef4012e989e145bca2d586113176c89a96019eb32c2a6487de7149a01b4139d95c3b31d648a3ec5
7
- data.tar.gz: 5270af8f8b5c398d974857194adff85b826c75cd603006eac060d8762985220f13d095cd4b01ae94976b22a261c6250daa4ee05176b2bc635f7455bbd5eeeaf0
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
@@ -7,7 +7,7 @@ module Contrast
7
7
  module Policy
8
8
  module TriggerValidation
9
9
  # Validator used to assert a REDOS finding is actually vulnerable
10
- # before serializing that finding as a DTM to report to the TeamServer.
10
+ # before serializing that finding as a Event to report to the TeamServer.
11
11
  module REDOSValidator
12
12
  RULE_NAME = 'redos'
13
13
  # If Regexp is set to Float::Infinite this is the maximum number it will receive
@@ -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