contrast-agent 6.1.0 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -1
  3. data/Rakefile +1 -1
  4. data/ext/build_funchook.rb +3 -3
  5. data/ext/cs__assess_basic_object/cs__assess_basic_object.c +5 -1
  6. data/ext/extconf_common.rb +1 -1
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +2 -2
  8. data/lib/contrast/agent/assess/policy/policy.rb +9 -10
  9. data/lib/contrast/agent/assess/policy/policy_node.rb +9 -10
  10. data/lib/contrast/agent/assess/policy/propagation_method.rb +3 -3
  11. data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -3
  12. data/lib/contrast/agent/assess/policy/propagator/base.rb +1 -1
  13. data/lib/contrast/agent/assess/policy/propagator/buffer.rb +2 -1
  14. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -1
  15. data/lib/contrast/agent/assess/policy/propagator/splat.rb +1 -1
  16. data/lib/contrast/agent/assess/policy/propagator/split.rb +2 -2
  17. data/lib/contrast/agent/assess/policy/propagator/trim.rb +1 -1
  18. data/lib/contrast/agent/assess/policy/source_node.rb +1 -1
  19. data/lib/contrast/agent/assess/policy/trigger_method.rb +7 -7
  20. data/lib/contrast/agent/assess/policy/trigger_node.rb +16 -16
  21. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
  22. data/lib/contrast/agent/assess/property/evented.rb +2 -2
  23. data/lib/contrast/agent/assess/property/tagged.rb +2 -2
  24. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +6 -8
  25. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +6 -7
  26. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +5 -5
  27. data/lib/contrast/agent/assess/rule/response/base_rule.rb +2 -3
  28. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +8 -9
  29. data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +4 -4
  30. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +6 -6
  31. data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +4 -4
  32. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +4 -4
  33. data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +4 -4
  34. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +3 -4
  35. data/lib/contrast/agent/assess/tag.rb +13 -14
  36. data/lib/contrast/agent/at_exit_hook.rb +13 -1
  37. data/lib/contrast/agent/inventory/database_config.rb +12 -4
  38. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +9 -5
  39. data/lib/contrast/agent/middleware.rb +6 -3
  40. data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -3
  41. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +2 -2
  42. data/lib/contrast/agent/patching/policy/method_policy_extend.rb +4 -4
  43. data/lib/contrast/agent/patching/policy/patch.rb +9 -9
  44. data/lib/contrast/agent/patching/policy/patch_status.rb +10 -3
  45. data/lib/contrast/agent/patching/policy/policy.rb +13 -15
  46. data/lib/contrast/agent/patching/policy/policy_node.rb +19 -21
  47. data/lib/contrast/agent/patching/policy/trigger_node.rb +1 -1
  48. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +125 -125
  49. data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -2
  50. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -1
  51. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  52. data/lib/contrast/agent/protect/policy/rule_applicator.rb +4 -4
  53. data/lib/contrast/agent/protect/rule/base.rb +30 -18
  54. data/lib/contrast/agent/protect/rule/base_service.rb +31 -14
  55. data/lib/contrast/agent/protect/rule/cmd_injection.rb +16 -9
  56. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +3 -3
  57. data/lib/contrast/agent/protect/rule/default_scanner.rb +2 -1
  58. data/lib/contrast/agent/protect/rule/deserialization.rb +18 -7
  59. data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +74 -74
  60. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +71 -53
  61. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +3 -3
  62. data/lib/contrast/agent/protect/rule/no_sqli.rb +15 -16
  63. data/lib/contrast/agent/protect/rule/path_traversal.rb +13 -3
  64. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -2
  65. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +1 -1
  66. data/lib/contrast/agent/protect/rule/sqli.rb +16 -23
  67. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +61 -61
  68. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +29 -29
  69. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +32 -32
  70. data/lib/contrast/agent/protect/rule/xss.rb +21 -0
  71. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +14 -13
  72. data/lib/contrast/agent/protect/rule/xxe.rb +25 -3
  73. data/lib/contrast/agent/reaction_processor.rb +1 -1
  74. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +36 -36
  75. data/lib/contrast/agent/reporting/masker/masker.rb +10 -10
  76. data/lib/contrast/agent/reporting/masker/masker_utils.rb +2 -2
  77. data/lib/contrast/agent/reporting/reporter.rb +2 -11
  78. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +8 -10
  79. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +53 -5
  80. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +25 -19
  81. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +129 -17
  82. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +20 -21
  83. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_stack.rb +22 -0
  84. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +26 -12
  85. data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +7 -22
  86. data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +7 -5
  87. data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +4 -10
  88. data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +75 -15
  89. data/lib/contrast/agent/reporting/reporting_events/finding.rb +2 -2
  90. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +5 -19
  91. data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +6 -22
  92. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +1 -1
  93. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +2 -3
  94. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +1 -3
  95. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +9 -0
  96. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -2
  97. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -10
  98. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -2
  99. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +6 -7
  100. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +61 -3
  101. data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +33 -11
  102. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +8 -8
  103. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +64 -32
  104. data/lib/contrast/agent/reporting/settings/application_settings.rb +8 -23
  105. data/lib/contrast/agent/reporting/settings/assess.rb +5 -5
  106. data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +28 -34
  107. data/lib/contrast/agent/reporting/settings/bot_blocker.rb +68 -0
  108. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +27 -0
  109. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +33 -0
  110. data/lib/contrast/agent/reporting/settings/exclusions.rb +39 -57
  111. data/lib/contrast/agent/reporting/settings/helpers.rb +56 -0
  112. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +37 -0
  113. data/lib/contrast/agent/reporting/settings/ip_filter.rb +35 -0
  114. data/lib/contrast/agent/reporting/settings/keyword.rb +74 -0
  115. data/lib/contrast/agent/reporting/settings/log_enhancer.rb +65 -0
  116. data/lib/contrast/agent/reporting/settings/protect.rb +22 -5
  117. data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +62 -115
  118. data/lib/contrast/agent/reporting/settings/reaction.rb +13 -4
  119. data/lib/contrast/agent/reporting/settings/rule_definition.rb +63 -0
  120. data/lib/contrast/agent/reporting/settings/sampling.rb +10 -0
  121. data/lib/contrast/agent/reporting/settings/sanitizer.rb +38 -0
  122. data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +11 -3
  123. data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +9 -2
  124. data/lib/contrast/agent/reporting/settings/server_features.rb +10 -2
  125. data/lib/contrast/agent/reporting/settings/syslog.rb +176 -0
  126. data/lib/contrast/agent/reporting/settings/url_exclusion.rb +42 -0
  127. data/lib/contrast/agent/reporting/settings/validator.rb +17 -0
  128. data/lib/contrast/agent/request.rb +2 -2
  129. data/lib/contrast/agent/request_context.rb +27 -19
  130. data/lib/contrast/agent/request_context_extend.rb +10 -23
  131. data/lib/contrast/agent/request_handler.rb +9 -5
  132. data/lib/contrast/agent/rule_set.rb +2 -2
  133. data/lib/contrast/agent/scope.rb +1 -1
  134. data/lib/contrast/agent/static_analysis.rb +4 -8
  135. data/lib/contrast/agent/telemetry/base.rb +9 -5
  136. data/lib/contrast/agent/telemetry/events/exceptions/obfuscate.rb +119 -0
  137. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -2
  138. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +1 -1
  139. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +1 -1
  140. data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +16 -18
  141. data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +2 -2
  142. data/lib/contrast/agent/thread_watcher.rb +4 -5
  143. data/lib/contrast/agent/version.rb +1 -1
  144. data/lib/contrast/agent.rb +1 -3
  145. data/lib/contrast/api/communication/messaging_queue.rb +1 -1
  146. data/lib/contrast/api/communication/service_lifecycle.rb +1 -1
  147. data/lib/contrast/api/communication/socket.rb +1 -1
  148. data/lib/contrast/api/communication/socket_client.rb +1 -1
  149. data/lib/contrast/api/communication/speedracer.rb +2 -2
  150. data/lib/contrast/api/decorators/agent_startup.rb +10 -9
  151. data/lib/contrast/api/decorators/application_settings.rb +1 -1
  152. data/lib/contrast/api/decorators/application_startup.rb +4 -4
  153. data/lib/contrast/api/decorators/application_update.rb +0 -8
  154. data/lib/contrast/api/decorators/response_type.rb +4 -17
  155. data/lib/contrast/api/decorators.rb +0 -1
  156. data/lib/contrast/components/agent.rb +1 -1
  157. data/lib/contrast/components/base.rb +1 -1
  158. data/lib/contrast/components/config.rb +6 -6
  159. data/lib/contrast/components/contrast_service.rb +4 -1
  160. data/lib/contrast/components/sampling.rb +1 -1
  161. data/lib/contrast/components/settings.rb +52 -28
  162. data/lib/contrast/config/assess_rules_configuration.rb +1 -1
  163. data/lib/contrast/config/protect_rules_configuration.rb +1 -1
  164. data/lib/contrast/config/root_configuration.rb +1 -1
  165. data/lib/contrast/configuration.rb +4 -4
  166. data/lib/contrast/extension/assess/array.rb +1 -1
  167. data/lib/contrast/extension/assess/erb.rb +1 -1
  168. data/lib/contrast/extension/assess/marshal.rb +1 -1
  169. data/lib/contrast/extension/assess/string.rb +1 -1
  170. data/lib/contrast/extension/extension.rb +2 -2
  171. data/lib/contrast/framework/base_support.rb +13 -12
  172. data/lib/contrast/framework/grape/support.rb +9 -9
  173. data/lib/contrast/framework/manager.rb +7 -9
  174. data/lib/contrast/framework/manager_extend.rb +2 -1
  175. data/lib/contrast/framework/rack/patch/session_cookie.rb +1 -1
  176. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +15 -3
  177. data/lib/contrast/framework/rails/patch/assess_configuration.rb +3 -3
  178. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +1 -1
  179. data/lib/contrast/framework/rails/patch/support.rb +1 -1
  180. data/lib/contrast/framework/rails/support.rb +11 -4
  181. data/lib/contrast/framework/sinatra/support.rb +4 -3
  182. data/lib/contrast/logger/aliased_logging.rb +27 -15
  183. data/lib/contrast/logger/cef_log.rb +14 -14
  184. data/lib/contrast/logger/format.rb +1 -1
  185. data/lib/contrast/logger/log.rb +8 -8
  186. data/lib/contrast/tasks/config.rb +12 -12
  187. data/lib/contrast/tasks/service.rb +2 -2
  188. data/lib/contrast/utils/assess/tracking_util.rb +4 -4
  189. data/lib/contrast/utils/class_util.rb +4 -4
  190. data/lib/contrast/utils/findings.rb +3 -3
  191. data/lib/contrast/utils/hash_digest.rb +6 -7
  192. data/lib/contrast/utils/head_dump_utils_extend.rb +1 -1
  193. data/lib/contrast/utils/invalid_configuration_util.rb +1 -1
  194. data/lib/contrast/utils/log_utils.rb +4 -4
  195. data/lib/contrast/utils/lru_cache.rb +1 -1
  196. data/lib/contrast/utils/metrics_hash.rb +1 -1
  197. data/lib/contrast/utils/middleware_utils.rb +5 -5
  198. data/lib/contrast/utils/net_http_base.rb +4 -4
  199. data/lib/contrast/utils/os.rb +1 -1
  200. data/lib/contrast/utils/patching/policy/patch_utils.rb +2 -2
  201. data/lib/contrast/utils/request_utils.rb +2 -2
  202. data/lib/contrast/utils/response_utils.rb +14 -1
  203. data/lib/contrast/utils/sha256_builder.rb +4 -4
  204. data/lib/contrast/utils/stack_trace_utils.rb +31 -13
  205. data/lib/contrast/utils/telemetry.rb +15 -9
  206. data/lib/contrast/utils/telemetry_client.rb +5 -5
  207. data/lib/contrast/utils/telemetry_hash.rb +37 -13
  208. data/lib/contrast/utils/telemetry_identifier.rb +10 -2
  209. data/lib/contrast/utils/thread_tracker.rb +26 -9
  210. data/lib/contrast/utils/timer.rb +7 -2
  211. data/lib/contrast.rb +1 -3
  212. data/resources/assess/policy.json +1 -1
  213. metadata +28 -14
  214. data/lib/contrast/api/decorators/library_usage_update.rb +0 -31
@@ -0,0 +1,63 @@
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/agent/reporting/settings/helpers'
5
+ require 'contrast/agent/reporting/settings/keyword'
6
+
7
+ module Contrast
8
+ module Agent
9
+ module Reporting
10
+ module Settings
11
+ # The keywords and patterns required for the input analysis of each rule with that capability.
12
+ class RuleDefinition
13
+ ATTRIBUTES = %i[name keywords patterns].cs__freeze
14
+
15
+ # @return name [String] Name of the rule
16
+ attr_accessor :name
17
+
18
+ # The words to search for in input that indicate an attack
19
+ #
20
+ # @return [array<Contrast::Agent::Reporting::Settings::Keyword>]
21
+ def keywords
22
+ @_keywords ||= []
23
+ end
24
+
25
+ # A word or pattern whose presence in an input represents an attack
26
+ #
27
+ # @return [array<Contrast::Agent::Reporting::Settings::Pattern>]
28
+ def patterns
29
+ @_patterns ||= []
30
+ end
31
+
32
+ # Set keywords.
33
+ #
34
+ # @param keywords_array [Array]
35
+ # @return [array<Contrast::Agent::Reporting::Settings::Keyword>]
36
+ def keywords= keywords_array
37
+ Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(Contrast::Agent::Reporting::Settings::Keyword,
38
+ keywords,
39
+ keywords_array)
40
+ end
41
+
42
+ # Set patterns.
43
+ #
44
+ # @param patterns_array [Array]
45
+ # @return [array<Contrast::Agent::Reporting::Settings::Pattern>]
46
+ def patterns= patterns_array
47
+ Contrast::Agent::Reporting::Settings::Helpers.array_to_iv(Contrast::Agent::Reporting::Settings::Pattern,
48
+ patterns,
49
+ patterns_array)
50
+ end
51
+
52
+ def to_controlled_hash
53
+ {
54
+ name: name, # rubocop:disable Security/Module/Name
55
+ keywords: keywords.map(&:to_controlled_hash),
56
+ patterns: patterns.map(&:to_controlled_hash)
57
+ }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -29,6 +29,16 @@ module Contrast
29
29
  @response_frequency = hsh[:responseFrequency]
30
30
  @window_ms = hsh[:window]
31
31
  end
32
+
33
+ def to_controlled_hash
34
+ {
35
+ baseline: baseline,
36
+ enabled: enabled,
37
+ frequency: request_frequency,
38
+ responseFrequency: response_frequency,
39
+ window: window_ms
40
+ }
41
+ end
32
42
  end
33
43
  end
34
44
  end
@@ -0,0 +1,38 @@
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 Agent
6
+ module Reporting
7
+ module Settings
8
+ # The sanitizers defined by the user for use by the agent on this server for this organization.
9
+ class Sanitizer
10
+ ATTRIBUTES = %i[uuid api tags rules].cs__freeze
11
+
12
+ # @return uuid [String]
13
+ attr_accessor :uuid
14
+ # @return api [String]
15
+ attr_accessor :api
16
+ # @return uuid [Array<String>]
17
+ attr_accessor :tags
18
+ # @return uuid [Array<String>]
19
+ attr_accessor :rules
20
+
21
+ def initialize
22
+ @tags = []
23
+ @rules = []
24
+ end
25
+
26
+ def to_controlled_hash
27
+ {
28
+ api: api,
29
+ rules: rules,
30
+ tags: tags,
31
+ uuid: uuid
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -58,7 +58,7 @@ module Contrast
58
58
  # @param rules [Array<Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule>]
59
59
  # @return rules [Array<Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule>, []]
60
60
  def rules= rules
61
- @_rules = rules if rules_array? rules
61
+ @_rules = rules if rules_array?(rules)
62
62
  end
63
63
 
64
64
  # Build rules from hash
@@ -66,7 +66,7 @@ module Contrast
66
66
  # @param settings_rules [Hash] Response settings under Settings/sensitive_data_masking_policy/rules
67
67
  # @return rules [Array<Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule>, nil
68
68
  def build_rules_form_settings settings_rules
69
- return unless settings_rules || settings_rules.empty?
69
+ return if settings_rules.nil? || settings_rules.empty?
70
70
 
71
71
  settings_rules.each do |rule|
72
72
  instance = Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule.new
@@ -77,6 +77,14 @@ module Contrast
77
77
  rules
78
78
  end
79
79
 
80
+ def to_controlled_hash
81
+ {
82
+ rules: rules.map(&:to_controlled_hash),
83
+ mask_attack_vector: mask_attack_vector?,
84
+ mask_http_body: mask_http_body?
85
+ }
86
+ end
87
+
80
88
  private
81
89
 
82
90
  # Determine if parameter is array of Rules.
@@ -99,7 +107,7 @@ module Contrast
99
107
  # @param item [Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule]
100
108
  # @return itself [Array<Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule>]
101
109
  def << item
102
- return itself unless item.instance_of? Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule
110
+ return itself unless item.instance_of?(Contrast::Agent::Reporting::Settings::SensitiveDataMaskingRule)
103
111
 
104
112
  super
105
113
  end
@@ -37,7 +37,14 @@ module Contrast
37
37
  # @param words_array [Array<String>]
38
38
  # @return keywords [Array<String>] set of keywords
39
39
  def keywords= words_array
40
- @_keywords = words_array if string_array? words_array
40
+ @_keywords = words_array if string_array?(words_array)
41
+ end
42
+
43
+ def to_controlled_hash
44
+ {
45
+ id: rule_id,
46
+ keywords: keywords
47
+ }
41
48
  end
42
49
 
43
50
  private
@@ -49,7 +56,7 @@ module Contrast
49
56
  def string_array? array
50
57
  return false unless array.is_a?(Array) && array.any?
51
58
 
52
- array.all? String
59
+ array.all?(String)
53
60
  end
54
61
  end
55
62
  end
@@ -27,7 +27,7 @@ module Contrast
27
27
  # @param log_level [String]
28
28
  # @return log_level [String] [ ERROR, WARN, INFO, DEBUG, TRACE ]
29
29
  def log_level= log_level
30
- @_log_level = log_level if log_level.is_a? String
30
+ @_log_level = log_level if log_level.is_a?(String)
31
31
  end
32
32
 
33
33
  # Where to log the agent's log file, if set by the user. Overridden by agent.logger.path
@@ -43,7 +43,7 @@ module Contrast
43
43
  # @param log_file [String] path
44
44
  # @return log_file [String] path
45
45
  def log_file= log_file
46
- @_log_file = log_file if log_file.is_a? String
46
+ @_log_file = log_file if log_file.is_a?(String)
47
47
  end
48
48
 
49
49
  # Controls for the reporting of telemetry events from the agent to TeamServer.
@@ -71,6 +71,14 @@ module Contrast
71
71
  def protect
72
72
  @_protect ||= Contrast::Agent::Reporting::Settings::ProtectServerFeature.new
73
73
  end
74
+
75
+ def to_controlled_hash
76
+ {
77
+ assessment: @_assess ? assess.to_controlled_hash : {},
78
+ defend: @_protect ? protect.to_controlled_hash : {},
79
+ telemetry: telemetry
80
+ }.compact
81
+ end
74
82
  end
75
83
  end
76
84
  end
@@ -0,0 +1,176 @@
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/utils/object_share'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Reporting
9
+ module Settings
10
+ # Controls for the syslogging feature in the agent
11
+ class Syslog
12
+ CONNECTION_TYPE = %w[UNENCRYPTED ENCRYPTED].cs__freeze
13
+ # Used for:
14
+ # severity_blocked, severity_blocked_perimeter, severity_exploited, severity_probed,
15
+ # severity_probed_perimeter
16
+ SEVERITIES = %w[ALERT CRITICAL ERROR WARNING NOTICE INFO DEBUG].cs__freeze
17
+ SYSLOG_METHODS = %i[
18
+ enable= ip= port= facility= protocol= connection_type= severity_exploited= severity_blocked=
19
+ severity_probed= severity_probed_suspicious= severity_blocked_perimeter= severity_probed_perimeter=
20
+ ].cs__freeze
21
+ SYSLOG_RESPONSE_KEYS = %i[
22
+ syslogEnabled syslogIpAddress syslogPortNumber syslogFacilityCode syslogProtocol
23
+ syslogConnectionType syslogSeverityExploited syslogSeverityBlocked syslogSeverityProbed
24
+ syslogSeveritySuspicious syslogSeverityBlockedPerimeter syslogSeverityProbedPerimeter
25
+ ].cs__freeze
26
+
27
+ # @return enable [Boolean]
28
+ attr_accessor :enable
29
+ # @return ip [Integer]
30
+ attr_accessor :ip
31
+ # @return port [Integer]
32
+ attr_accessor :port
33
+ # @return facility [Integer]
34
+ attr_accessor :facility
35
+ # @return protocol [String]
36
+ attr_accessor :protocol
37
+
38
+ def initialize
39
+ @enable = false
40
+ @ip = Contrast::Utils::ObjectShare::EMPTY_STRING
41
+ @port = 0
42
+ @facility = 0
43
+ end
44
+
45
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
46
+ def connection_type
47
+ @_connection_type ||= Contrast::Utils::ObjectShare::EMPTY_STRING
48
+ end
49
+
50
+ # Set the connection type
51
+ #
52
+ # @param type [String, Symbol] one of UNENCRYPTED, ENCRYPTED
53
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
54
+ def connection_type= type
55
+ @_connection_type = type if valid_entry?(type, CONNECTION_TYPE)
56
+ end
57
+
58
+ # @return severity_blocked [String]
59
+ def severity_blocked
60
+ @_severity_blocked ||= Contrast::Utils::ObjectShare::EMPTY_STRING
61
+ end
62
+
63
+ # Set the severity type
64
+ #
65
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
66
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
67
+ def severity_blocked= severity
68
+ @_severity_blocked = severity if valid_entry?(severity, SEVERITIES)
69
+ end
70
+
71
+ # @return severity_blocked [String]
72
+ def severity_blocked_perimeter
73
+ @_severity_blocked_perimeter ||= Contrast::Utils::ObjectShare::EMPTY_STRING
74
+ end
75
+
76
+ # Set the severity type
77
+ #
78
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
79
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
80
+ def severity_blocked_perimeter= severity
81
+ @_severity_blocked_perimeter = severity if valid_entry?(severity, SEVERITIES)
82
+ end
83
+
84
+ # @return severity_blocked [String]
85
+ def severity_exploited
86
+ @_severity_exploited ||= Contrast::Utils::ObjectShare::EMPTY_STRING
87
+ end
88
+
89
+ # Set the severity type
90
+ #
91
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
92
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
93
+ def severity_exploited= severity
94
+ @_severity_exploited = severity if valid_entry?(severity, SEVERITIES)
95
+ end
96
+
97
+ # @return severity_blocked [String]
98
+ def severity_probed
99
+ @_severity_probed ||= Contrast::Utils::ObjectShare::EMPTY_STRING
100
+ end
101
+
102
+ # Set the severity type
103
+ #
104
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
105
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
106
+ def severity_probed= severity
107
+ @_severity_probed = severity if valid_entry?(severity, SEVERITIES)
108
+ end
109
+
110
+ # @return severity_blocked [String]
111
+ def severity_probed_perimeter
112
+ @_severity_probed_perimeter ||= Contrast::Utils::ObjectShare::EMPTY_STRING
113
+ end
114
+
115
+ # Set the severity type
116
+ #
117
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
118
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
119
+ def severity_probed_perimeter= severity
120
+ @_severity_probed_perimeter = severity if valid_entry?(severity, SEVERITIES)
121
+ end
122
+
123
+ # @return severity_blocked [String]
124
+ def severity_probed_suspicious
125
+ @_severity_probed_suspicious ||= Contrast::Utils::ObjectShare::EMPTY_STRING
126
+ end
127
+
128
+ # Set the severity type
129
+ #
130
+ # @param severity [String, Symbol] one of UNENCRYPTED, ENCRYPTED
131
+ # @return connection_type [String] one of UNENCRYPTED, ENCRYPTED
132
+ def severity_probed_suspicious= severity
133
+ @_severity_probed_suspicious = severity if valid_entry?(severity, SEVERITIES)
134
+ end
135
+
136
+ # @param settings_array [Array] Settings retrieved from response
137
+ def assign_array settings_array
138
+ Contrast::Agent::Reporting::Settings::Syslog::SYSLOG_METHODS.each_with_index do |method, index|
139
+ send(method, settings_array[SYSLOG_RESPONSE_KEYS[index]])
140
+ end
141
+ end
142
+
143
+ def to_controlled_hash
144
+ {
145
+ syslogEnabled: enable,
146
+ syslogIpAddress: ip,
147
+ syslogPortNumber: port,
148
+ syslogFacilityCode: facility,
149
+ syslogConnectionType: connection_type,
150
+ syslogProtocol: protocol,
151
+ syslogSeverityExploited: severity_exploited,
152
+ syslogSeverityBlocked: severity_blocked,
153
+ syslogSeverityProbed: severity_probed,
154
+ syslogSeveritySuspicious: severity_probed_suspicious,
155
+ syslogSeverityBlockedPerimeter: severity_blocked_perimeter,
156
+ syslogSeverityProbedPerimeter: severity_probed_perimeter
157
+ }
158
+ end
159
+
160
+ private
161
+
162
+ # Gets String or Symbol value and assigns it to iv after
163
+ # validation with allowed types.
164
+ #
165
+ # @param value [String, Symbol] value to write
166
+ # @param validation_hash [Hash] to validate against
167
+ def valid_entry? value, validation_hash
168
+ return false unless value && validation_hash
169
+
170
+ validation_hash.include?(value)
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,42 @@
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/agent/reporting/settings/exclusion_base'
5
+ require 'contrast/utils/object_share'
6
+
7
+ module Contrast
8
+ module Agent
9
+ module Reporting
10
+ module Settings
11
+ # UrlExclusions class
12
+ class UrlExclusion < ExclusionBase
13
+ ATTRIBUTES = BASE_ATTRIBUTES.dup << :urls
14
+ ATTRIBUTES << :match_strategy
15
+ ATTRIBUTES.cs__freeze
16
+ STRATEGIES = %w[ALL ONLY].cs__freeze
17
+
18
+ # @return urls [Array<String>]
19
+ attr_accessor :urls
20
+
21
+ # @return match_strategy [String] The type of the input
22
+ def match_strategy
23
+ @_match_strategy ||= Contrast::Utils::ObjectShare::EMPTY_STRING
24
+ end
25
+
26
+ # @param new_strategy [String] Set new input type.
27
+ # @return type [String] The type of the input.
28
+ def match_strategy= new_strategy
29
+ @_match_strategy = new_strategy if STRATEGIES.include?(new_strategy)
30
+ end
31
+
32
+ def to_controlled_hash
33
+ hash = super
34
+ hash[:urls] = urls
35
+ hash[:matchStrategy] = match_strategy
36
+ hash
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,17 @@
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/agent/reporting/settings/sanitizer'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Reporting
9
+ module Settings
10
+ # The validators defined by the user for use by the agent on this server for this organization.
11
+ class Validator < Sanitizer
12
+ # This uses the same fields as Sanitizer.
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -34,6 +34,8 @@ module Contrast
34
34
  LAST_REST_TOKEN = %r{/\d+$}.cs__freeze
35
35
  INNER_NUMBER_MARKER = '/{n}/'
36
36
  LAST_NUMBER_MARKER = '/{n}'
37
+ STATIC_SUFFIXES = /\.(?:js|css|jpeg|jpg|gif|png|ico|woff|svg|pdf|eot|ttf|jar)$/i.cs__freeze
38
+ MEDIA_TYPE_MARKERS = %w[image/ text/css text/javascript].cs__freeze
37
39
 
38
40
  attr_reader :rack_request
39
41
  attr_accessor :route, :observed_route, :new_observed_route
@@ -181,8 +183,6 @@ module Contrast
181
183
  @_hash_id ||= Contrast::Utils::HashDigest.generate_request_hash(self)
182
184
  end
183
185
 
184
- STATIC_SUFFIXES = /\.(?:js|css|jpeg|jpg|gif|png|ico|woff|svg|pdf|eot|ttf|jar)$/i.cs__freeze
185
- MEDIA_TYPE_MARKERS = %w[image/ text/css text/javascript].cs__freeze
186
186
  # Utility method for checking if a request is for a static resource.
187
187
  # @return [Boolean] true, if the request is for a well-known static
188
188
  # type as determined by the request suffix or the accept header.
@@ -1,6 +1,7 @@
1
1
  # Copyright (c) 2022 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/api/dtm.pb'
4
5
  require 'contrast/utils/timer'
5
6
  require 'contrast/agent/request'
6
7
  require 'contrast/agent/response'
@@ -16,20 +17,6 @@ module Contrast
16
17
  module Agent
17
18
  # This class acts to encapsulate information about the currently executed request, making it available to the Agent
18
19
  # for the duration of the request in a standardized and normalized format which the Agent understands.
19
- #
20
- # @attr_reader timer [Contrast::Utils::Timer] when the context was created
21
- # @attr_reader logging_hash [Hash] context used to log the request
22
- # @attr_reader speedracer_input_analysis [Contrast::Api::Settings::InputAnalysis] the protect input analysis of
23
- # sources on this request
24
- # @attr_reader request [Contrast::Agent::Request] our wrapper around the Rack::Request for this context
25
- # @attr_reader response [Contrast::Agent::Response] our wrapper aroudn the Rack::Response or Array for this context,
26
- # only available after the application has finished its processing
27
- # @attr_reader activity [Contrast::Api::Dtm::Activity] the application activity found in this request
28
- # @attr_reader server_activity [Contrast::Api::Dtm::ServerActivity] the server activity found in this request
29
- # @attr_reader route [Contrast::Api::Dtm::RouteCoverage] the route, used for findings, of this request
30
- # @attr_reader observed_route [Contrast::Api::Dtm::ObservedRoute] the route, used for coverage, of this request
31
- # @attr_reader new_observed_route [Contrast::Agent::Reporting::ObservedRoute] the route, used for coverage, of this
32
- # request
33
20
  class RequestContext
34
21
  include Contrast::Components::Logger::InstanceMethods
35
22
  include Contrast::Components::Scope::InstanceMethods
@@ -37,10 +24,31 @@ module Contrast
37
24
  include Contrast::Agent::RequestContextExtend
38
25
 
39
26
  EMPTY_INPUT_ANALYSIS_PB = Contrast::Api::Settings::InputAnalysis.new
40
- INPUT_ANALYSIS = Contrast::Agent::Reporting::InputAnalysis.new
41
27
 
42
- attr_reader :activity, :logging_hash, :observed_route, :new_observed_route, :request, :response, :route,
43
- :speedracer_input_analysis, :agent_input_analysis, :server_activity, :timer
28
+ # @return [Contrast::Api::Dtm::Activity] the application activity found in this request
29
+ attr_reader :activity
30
+ # @return [Hash] context used to log the request
31
+ attr_reader :logging_hash
32
+ # @return [Contrast::Agent::Reporting::ObservedRoute] the route, used for coverage, of this request
33
+ attr_reader :new_observed_route
34
+ # @return [Contrast::Api::Dtm::ObservedRoute] the route, used for coverage, of this request
35
+ attr_reader :observed_route
36
+ # @return [Contrast::Agent::Request] our wrapper around the Rack::Request for this context
37
+ attr_reader :request
38
+ # @return [Contrast::Agent::Response] our wrapper around the Rack::Response or Array for this context,
39
+ # only available after the application has finished its processing
40
+ attr_reader :response
41
+ # @return [Contrast::Api::Dtm::RouteCoverage] the route, used for findings, of this request
42
+ attr_reader :route
43
+ # @return [Contrast::Api::Dtm::ServerActivity] the server activity found in this request
44
+ attr_reader :server_activity
45
+ # @return [Contrast::Api::Settings::InputAnalysis] the protect input analysis of sources on this request
46
+ attr_reader :speedracer_input_analysis
47
+ # @return [Contrast::Utils::Timer] when the context was created
48
+ attr_reader :timer
49
+ # @return [Contrast::Agent::Reporting::ObservedLibraryUsage] List of the libraries that have been observed to be
50
+ # executed or to have something loaded. This here replaces part of the Activity Dtm
51
+ attr_reader :observed_library_usage
44
52
 
45
53
  def initialize rack_request, app_loaded: true
46
54
  with_contrast_scope do
@@ -55,14 +63,14 @@ module Contrast
55
63
  @activity.http_request = request.dtm
56
64
 
57
65
  @server_activity = Contrast::Api::Dtm::ServerActivity.new
66
+ @observed_library_usage = Contrast::Agent::Reporting::ObservedLibraryUsage.new
58
67
 
59
68
  # build analyzer
60
69
  @do_not_track = false
61
70
  @speedracer_input_analysis = EMPTY_INPUT_ANALYSIS_PB
62
71
  speedracer_input_analysis.request = request
63
72
 
64
- @agent_input_analysis = INPUT_ANALYSIS
65
- agent_input_analysis.request = request
73
+ # TODO: RUBY-1627
66
74
 
67
75
  # flag to indicate whether the app is fully loaded
68
76
  @app_loaded = !!app_loaded
@@ -82,9 +82,10 @@ module Contrast
82
82
  handle_protect_state(service_response)
83
83
  ia = service_response.input_analysis
84
84
  if ia
85
- service_extract_logging ia
85
+ service_extract_logging(ia)
86
+ # TODO: RUBY-1629
86
87
  # using Agent analysis
87
- initialize_agent_input_analysis request
88
+ # initialize_agent_input_analysis request
88
89
 
89
90
  @speedracer_input_analysis = ia
90
91
  speedracer_input_analysis.request = request
@@ -93,7 +94,7 @@ module Contrast
93
94
  false
94
95
  end
95
96
  rescue Contrast::SecurityException => e
96
- raise e
97
+ raise(e)
97
98
  rescue StandardError => e
98
99
  logger.warn('Unable to extract Contrast Service information from request', e)
99
100
  false
@@ -115,7 +116,7 @@ module Contrast
115
116
  # If Contrast Service has NOT handled the input analysis, handle them here
116
117
  build_attack_results(agent_settings)
117
118
  logger.debug('Contrast Service said to block this request')
118
- raise Contrast::SecurityException.new(nil, (state.security_message || 'Blocking suspicious behavior'))
119
+ raise(Contrast::SecurityException.new(nil, (state.security_message || 'Blocking suspicious behavior')))
119
120
  end
120
121
 
121
122
  # append anything we've learned to the request seen message this is the sum-total of all inventory information
@@ -147,7 +148,7 @@ module Contrast
147
148
 
148
149
  # This here is for things we don't have implemented
149
150
  def log_to_cef
150
- activity.results.each { |attack_result| logging_logic attack_result, attack_result.rule_id.downcase }
151
+ activity.results.each { |attack_result| logging_logic(attack_result, attack_result.rule_id.downcase) }
151
152
  end
152
153
 
153
154
  # @param input_analysis [Contrast::Api::Settings::InputAnalysis]
@@ -172,7 +173,7 @@ module Contrast
172
173
  next unless rule
173
174
 
174
175
  logger.debug(BUILD_ATTACK_LOGGER_MESSAGE, result: ia_result.inspect) if logger.debug?
175
- results_by_rule[rule_id] = attack_result rule, rule_id, ia_result, results_by_rule
176
+ results_by_rule[rule_id] = attack_result(rule, rule_id, ia_result, results_by_rule)
176
177
  end
177
178
 
178
179
  results_by_rule.each_pair do |_, attack_result|
@@ -199,20 +200,6 @@ module Contrast
199
200
  end
200
201
  end
201
202
 
202
- # Sets request to be used with agent and service input analysis.
203
- #
204
- # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request
205
- # for this context
206
- def initialize_agent_input_analysis request
207
- # using Agent analysis
208
- ia = Contrast::Agent::Protect::InputAnalyzer.analyse request
209
- if ia
210
- @agent_input_analysis = ia
211
- else
212
- logger.trace('Analysis from Agent was empty.')
213
- end
214
- end
215
-
216
203
  def logging_logic result, rule_id
217
204
  rules = %w[bot_blocker virtual_patch ip_denylist]
218
205
  return unless rules.include?(rule_id)
@@ -221,14 +208,14 @@ module Contrast
221
208
  outcome = Contrast::Api::Dtm::AttackResult::ResponseType.get_name_by_tag(result.response)
222
209
  case rule_id
223
210
  when /bot_blocker/i
224
- blocker_to_json = Contrast::Api::Dtm::BotBlockerDetails.to_controlled_hash rule_details
211
+ blocker_to_json = Contrast::Api::Dtm::BotBlockerDetails.to_controlled_hash(rule_details)
225
212
  cef_logger.bot_blocking_message(blocker_to_json, outcome)
226
213
  when /virtual_patch/i
227
- virtual_patch_to_json = Contrast::Api::Dtm::VirtualPatchDetails.to_controlled_hash rule_details
214
+ virtual_patch_to_json = Contrast::Api::Dtm::VirtualPatchDetails.to_controlled_hash(rule_details)
228
215
  cef_logger.virtual_patch_message(virtual_patch_to_json, outcome)
229
216
  when /ip_denylist/i
230
217
  sender_ip = extract_sender_ip
231
- ip_denylist_to_json = Contrast::Api::Dtm::IpDenylistDetails.to_controlled_hash rule_details
218
+ ip_denylist_to_json = Contrast::Api::Dtm::IpDenylistDetails.to_controlled_hash(rule_details)
232
219
  return unless sender_ip
233
220
  return unless sender_ip.include?(ip_denylist_to_json[:ip])
234
221