contrast-agent 5.0.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -2
  3. data/ext/cs__assess_kernel/cs__assess_kernel.c +7 -4
  4. data/ext/cs__assess_module/cs__assess_module.c +48 -38
  5. data/ext/cs__common/cs__common.c +4 -0
  6. data/ext/cs__common/cs__common.h +1 -0
  7. data/ext/cs__contrast_patch/cs__contrast_patch.c +52 -27
  8. data/ext/cs__contrast_patch/cs__contrast_patch.h +2 -0
  9. data/ext/cs__scope/cs__scope.c +747 -0
  10. data/ext/cs__scope/cs__scope.h +88 -0
  11. data/ext/cs__scope/extconf.rb +5 -0
  12. data/lib/contrast/agent/assess/contrast_event.rb +20 -13
  13. data/lib/contrast/agent/assess/contrast_object.rb +4 -1
  14. data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -5
  15. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +6 -0
  16. data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -1
  17. data/lib/contrast/agent/assess/rule/response/auto_complete_rule.rb +69 -0
  18. data/lib/contrast/agent/assess/rule/response/base_rule.rb +25 -12
  19. data/lib/contrast/agent/assess/rule/response/body_rule.rb +109 -0
  20. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +157 -0
  21. data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +26 -0
  22. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +100 -0
  23. data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +26 -0
  24. data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +29 -0
  25. data/lib/contrast/agent/assess/rule/response/header_rule.rb +70 -0
  26. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +36 -0
  27. data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +61 -0
  28. data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +26 -0
  29. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +35 -0
  30. data/lib/contrast/agent/middleware.rb +1 -0
  31. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +1 -3
  32. data/lib/contrast/agent/patching/policy/patch.rb +2 -6
  33. data/lib/contrast/agent/patching/policy/patcher.rb +1 -1
  34. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +94 -0
  35. data/lib/contrast/agent/protect/rule/base.rb +28 -1
  36. data/lib/contrast/agent/protect/rule/base_service.rb +10 -1
  37. data/lib/contrast/agent/protect/rule/cmd_injection.rb +2 -0
  38. data/lib/contrast/agent/protect/rule/deserialization.rb +6 -0
  39. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +5 -1
  40. data/lib/contrast/agent/protect/rule/no_sqli.rb +1 -0
  41. data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -0
  42. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +124 -0
  43. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +121 -0
  44. data/lib/contrast/agent/protect/rule/sqli.rb +33 -0
  45. data/lib/contrast/agent/protect/rule/xxe.rb +4 -0
  46. data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +44 -0
  47. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +115 -0
  48. data/lib/contrast/agent/reporting/input_analysis/input_type.rb +44 -0
  49. data/lib/contrast/agent/reporting/input_analysis/score_level.rb +21 -0
  50. data/lib/contrast/agent/reporting/report.rb +1 -0
  51. data/lib/contrast/agent/reporting/reporter.rb +8 -1
  52. data/lib/contrast/agent/reporting/reporting_events/finding.rb +77 -34
  53. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +88 -59
  54. data/lib/contrast/agent/reporting/reporting_events/{finding_object.rb → finding_event_object.rb} +24 -20
  55. data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +39 -0
  56. data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +40 -0
  57. data/lib/contrast/agent/reporting/reporting_events/{finding_signature.rb → finding_event_signature.rb} +29 -24
  58. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +12 -8
  59. data/lib/contrast/agent/reporting/reporting_events/{finding_stack.rb → finding_event_stack.rb} +23 -19
  60. data/lib/contrast/agent/reporting/reporting_events/{finding_taint_range.rb → finding_event_taint_range.rb} +17 -15
  61. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +26 -53
  62. data/lib/contrast/agent/reporting/reporting_events/poll.rb +29 -0
  63. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +5 -4
  64. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +1 -0
  65. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +1 -1
  66. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
  67. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +0 -1
  68. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -0
  69. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +28 -20
  70. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
  71. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +13 -1
  72. data/lib/contrast/agent/request_context.rb +6 -1
  73. data/lib/contrast/agent/request_context_extend.rb +87 -10
  74. data/lib/contrast/agent/scope.rb +102 -107
  75. data/lib/contrast/agent/service_heartbeat.rb +45 -2
  76. data/lib/contrast/agent/version.rb +1 -1
  77. data/lib/contrast/api/decorators/bot_blocker.rb +37 -0
  78. data/lib/contrast/api/decorators/ip_denylist.rb +37 -0
  79. data/lib/contrast/api/decorators/rasp_rule_sample.rb +29 -0
  80. data/lib/contrast/api/decorators/user_input.rb +11 -1
  81. data/lib/contrast/api/decorators/virtual_patch.rb +34 -0
  82. data/lib/contrast/components/logger.rb +5 -0
  83. data/lib/contrast/components/protect.rb +4 -2
  84. data/lib/contrast/components/scope.rb +98 -91
  85. data/lib/contrast/config/agent_configuration.rb +58 -12
  86. data/lib/contrast/config/api_configuration.rb +100 -12
  87. data/lib/contrast/config/api_proxy_configuration.rb +55 -3
  88. data/lib/contrast/config/application_configuration.rb +114 -15
  89. data/lib/contrast/config/assess_configuration.rb +106 -12
  90. data/lib/contrast/config/assess_rules_configuration.rb +44 -3
  91. data/lib/contrast/config/base_configuration.rb +1 -0
  92. data/lib/contrast/config/certification_configuration.rb +74 -3
  93. data/lib/contrast/config/exception_configuration.rb +61 -3
  94. data/lib/contrast/config/heap_dump_configuration.rb +101 -17
  95. data/lib/contrast/config/inventory_configuration.rb +64 -3
  96. data/lib/contrast/config/logger_configuration.rb +46 -3
  97. data/lib/contrast/config/protect_rule_configuration.rb +36 -9
  98. data/lib/contrast/config/protect_rules_configuration.rb +120 -17
  99. data/lib/contrast/config/request_audit_configuration.rb +68 -3
  100. data/lib/contrast/config/ruby_configuration.rb +96 -22
  101. data/lib/contrast/config/sampling_configuration.rb +76 -10
  102. data/lib/contrast/config/server_configuration.rb +56 -11
  103. data/lib/contrast/config/service_configuration.rb +66 -11
  104. data/lib/contrast/configuration.rb +6 -3
  105. data/lib/contrast/extension/assess/erb.rb +17 -0
  106. data/lib/contrast/logger/cef_log.rb +151 -0
  107. data/lib/contrast/utils/hash_digest.rb +14 -6
  108. data/lib/contrast/utils/log_utils.rb +114 -0
  109. data/lib/contrast/utils/middleware_utils.rb +6 -7
  110. data/lib/contrast/utils/net_http_base.rb +12 -9
  111. data/lib/contrast/utils/patching/policy/patch_utils.rb +0 -4
  112. data/lib/contrast.rb +4 -3
  113. data/resources/assess/policy.json +10 -0
  114. data/ruby-agent.gemspec +2 -2
  115. data/service_executables/VERSION +1 -1
  116. data/service_executables/linux/contrast-service +0 -0
  117. data/service_executables/mac/contrast-service +0 -0
  118. metadata +47 -19
  119. data/lib/contrast/agent/assess/rule/response/autocomplete_rule.rb +0 -130
  120. data/lib/contrast/extension/kernel.rb +0 -54
@@ -0,0 +1,151 @@
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 'logger'
5
+ require 'singleton'
6
+
7
+ require 'contrast/extension/module'
8
+ require 'contrast/logger/application'
9
+ require 'contrast/logger/format'
10
+ require 'contrast/logger/request'
11
+ require 'contrast/logger/time'
12
+ require 'contrast/logger/log'
13
+ require 'contrast/components/config'
14
+ require 'contrast/utils/log_utils'
15
+
16
+ module Contrast
17
+ # Used as a wrapper around our logging. The module option specifically adds in a new method for error that raises the
18
+ # logged exception, used in testing so that we can see if anything unexpected happens without it being swallowed
19
+ # while still providing safe options for customers.
20
+ module Logger
21
+ # For development set following env var to raise logged exceptions instead of just logging.
22
+ if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
23
+ ::Logger.class_eval do
24
+ alias_method :cs__error, :error
25
+ alias_method :cs__warn, :warn
26
+
27
+ def error *args, **kwargs
28
+ if kwargs.empty?
29
+ cs__error(*args)
30
+ else
31
+ cs__error(*args, **kwargs)
32
+ end
33
+ args.each { |arg| raise arg if arg && arg.cs__class < Exception }
34
+ end
35
+ end
36
+ end
37
+
38
+ # This is the CEF Logger implementation. It uses the default ::Logger.
39
+ class CEFLog
40
+ include Singleton
41
+ include ::Contrast::Utils::LogUtils
42
+ include ::Contrast::Utils::CEFLogUtils
43
+
44
+ attr_reader :previous_path, :previous_level
45
+
46
+ def initialize
47
+ build_logger
48
+ end
49
+
50
+ # Given new settings from TeamServer, update our logging to use the new file and level, assuming they weren't
51
+ # set by local configuration.
52
+ #
53
+ # @param log_level [String] the level at which to log, as provided by TeamServer settings
54
+ def build_logger log_level = nil
55
+ current_level_const = find_valid_level(log_level)
56
+ level_change = current_level_const != previous_level
57
+
58
+ # don't needlessly recreate logger
59
+ return if @cef_logger && !level_change
60
+
61
+ @previous_level = current_level_const
62
+
63
+ @_cef_logger = build(path: DEFAULT_CEF_NAME, level_const: current_level_const)
64
+ # If we're logging to a new path, then let's start it w/ our helpful
65
+ # data gathering messages
66
+ # log_update if path_change
67
+ rescue StandardError => e
68
+ # rubocop:disable Rails/Output
69
+ if @_cef_logger
70
+ @_cef_logger.error('Unable to process update to LoggerManager.', e)
71
+ else
72
+ puts 'Unable to process update to LoggerManager.'
73
+ raise e if ENV['CONTRAST__AGENT__RUBY_MORE_COWBELL']
74
+
75
+ puts e.message
76
+ puts e.backtrace.join("\n")
77
+ end
78
+ # rubocop:enable Rails/Output
79
+ end
80
+
81
+ def cef_logger
82
+ @_cef_logger
83
+ end
84
+
85
+ def log msg, level = @_cef_logger.level
86
+ case level
87
+ when ::Logger::Severity::INFO
88
+ @_cef_logger.info(msg)
89
+ when ::Logger::Severity::ERROR
90
+ @_cef_logger.error(msg)
91
+ when ::Logger::Severity::WARN
92
+ @_cef_logger.warn(msg)
93
+ when ::Logger::Severity::FATAL
94
+ @_cef_logger.fatal(msg)
95
+ else
96
+ @_cef_logger.debug(msg)
97
+ end
98
+ end
99
+
100
+ def virtual_patch_message patch, outcome
101
+ message = "Virtual Patch #{ patch.fetch(:name, '') } - #{ patch[:uuid] } was triggered by this request."
102
+ log [message, patch, outcome], ::Logger::Severity::DEBUG
103
+ end
104
+
105
+ def bot_blocking_message matching_bot, outcome
106
+ message = "User agent #{ matching_bot[:user_agent] } matched the disallowed value #{ matching_bot[:bot] }"
107
+ log [message, matching_bot, outcome], ::Logger::Severity::DEBUG
108
+ end
109
+
110
+ def ip_denylisted_message remote_ip, block_entry, outcome
111
+ message = "IP Address #{ remote_ip } matched the disallowed value" \
112
+ "#{ block_entry[:ip] } in the IP Blacklist #{ block_entry[:uuid] }"
113
+ log [message, block_entry, outcome], ::Logger::Severity::DEBUG
114
+ end
115
+
116
+ def successful_attack rule_id, outcome, input_type = nil, input_value = nil
117
+ if input_type.present? && input_value.present?
118
+ successful_attack_with_input = "#{ input_type } had a value that successfully exploited" \
119
+ "#{ rule_id } - #{ input_value }"
120
+ log [successful_attack_with_input, rule_id, outcome], ::Logger::Severity::WARN
121
+ else
122
+ successful_attack_wo_input = "An effective attack was detected against #{ rule_id }"
123
+ log [successful_attack_wo_input, rule_id, outcome], ::Logger::Severity::WARN
124
+ end
125
+ end
126
+
127
+ def ineffective_attack rule_id, outcome, input_type = nil, input_value = nil
128
+ if input_type.present? && input_value.present?
129
+ ineffective_attack_with_input = "#{ input_type } had a value that matched a signature for, " \
130
+ "but did not successfully exploit #{ rule_id } - #{ input_value }"
131
+ log [ineffective_attack_with_input, rule_id, outcome], ::Logger::Severity::WARN
132
+ else
133
+ ineffective_attack_wo_input = "An unsuccessful attack was detected against #{ rule_id }"
134
+ log [ineffective_attack_wo_input, rule_id, outcome], ::Logger::Severity::WARN
135
+ end
136
+ end
137
+
138
+ # newer - currently not in the agent, currently is a probe for us
139
+ def suspicious_attack rule_id, outcome, input_type = nil, input_value = nil
140
+ if input_type.present? && input_value.present?
141
+ suspicious_attack_with = "#{ input_type } included a potential attack value that was detected" \
142
+ "as suspicious using #{ rule_id } - #{ input_value }"
143
+ log [suspicious_attack_with, rule_id, outcome], ::Logger::WARN
144
+ elsif input_value.present?
145
+ suspicious_attack_without = 'Suspicious activity indicates a potential attack using ' + rule_id.to_s
146
+ log [suspicious_attack_without, rule_id, outcome], ::Logger::WARN
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -29,7 +29,7 @@ module Contrast
29
29
  # request or Contrast::REQUEST_TRACKER.current.request uri and used request
30
30
  # method.
31
31
  #
32
- # @param finding [Contrast::Api::Dtm::Finding] finding to be reported
32
+ # @param finding [Contrast::Api::Dtm::Finding, Contrast::Agent::Reporting::Finding] finding to be reported
33
33
  # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request.
34
34
  # @return checksum [Integer, nil] returns nil if there is no request context or tracking
35
35
  # is disabled.
@@ -38,12 +38,20 @@ module Contrast
38
38
  return unless context || ::Contrast::ASSESS.non_request_tracking?
39
39
 
40
40
  if (route = finding.routes[0])
41
- update(route.route) # the normalized URL used to access the method in the route.
42
- update(route.verb) # the HTTP Verb used to access the method in the route.
43
- elsif request ||= context&.request
44
- update(request.normalized_uri) # the normalized URL used to access the method in the route.
45
- update(request.request_method) # The HTTP method used in the request
41
+ if finding.cs__is_a?(Contrast::Agent::Reporting::Finding) && (observation = route.observations[0])
42
+ update(observation.url)
43
+ update(observation.verb)
44
+ else
45
+ update(route.route) # the normalized URL used to access the method in the route.
46
+ update(route.verb) # the HTTP Verb used to access the method in the route.
47
+ end
48
+ return
46
49
  end
50
+
51
+ return unless request ||= context&.request
52
+
53
+ update(request.normalized_uri) # the normalized URL used to access the method in the route.
54
+ update(request.request_method) # The HTTP method used in the request
47
55
  end
48
56
 
49
57
  # Update to CRC checksum the event source name and source type.
@@ -1,6 +1,9 @@
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 'socket'
5
+ require 'contrast/agent/version'
6
+
4
7
  module Contrast
5
8
  module Utils
6
9
  # Method utility used by Contrast::Logger::log
@@ -106,3 +109,114 @@ module Contrast
106
109
  end
107
110
  end
108
111
  end
112
+
113
+ module Contrast
114
+ module Utils
115
+ # These are the utilities for the CEF Logger, which will use the default ruby logger as we are not
116
+ # interested in special logging. We have the format we need and that's all we need. It would be useless
117
+ # to use Ougai
118
+ module CEFLogUtils
119
+ include Contrast::Utils::LogUtils
120
+ # <date> <host> CEF:<version>|<company>|<product>|<agent version>|<event type>
121
+ # |<event message>|<severity>|<other name-value pairs>
122
+ DEFAULT_CEF_NAME = 'security.log'
123
+ DEFAULT_LEVEL = ::Logger::Severity::INFO
124
+ VALID_LEVELS = ::Logger::SEV_LABEL
125
+ PROGNAME = 'Contrast Agent Ruby'
126
+ DATE_TIME_FORMAT = '%b %d %Y %H:%M:%S.%L%z'
127
+ AGENT_VERSION = Contrast::Agent::VERSION
128
+ EVENT_TYPE = 'SECURITY'
129
+ DEFAULT_METADATA = '-'
130
+
131
+ private
132
+
133
+ def build path: STDOUT_STR, level_const: DEFAULT_LEVEL
134
+ logger = case path
135
+ when STDOUT_STR, STDERR_STR
136
+ ::Logger.new(Object.cs__const_get(path))
137
+ else
138
+ ::Logger.new(path)
139
+ end
140
+ logger.progname = PROGNAME
141
+ logger.level = level_const
142
+ change_logger_formatter logger
143
+ logger
144
+ end
145
+
146
+ def context
147
+ Contrast::Agent::REQUEST_TRACKER.current
148
+ end
149
+
150
+ def change_logger_formatter logger
151
+ ip_address = extract_ip_address
152
+ logger.formatter = proc do |severity, datetime, progname, msg|
153
+ date_format = datetime.strftime(DATE_TIME_FORMAT)
154
+ message = []
155
+ message << "#{ date_format } #{ ip_address }"
156
+ message << 'CEF:0|Contrast Security'
157
+ message << progname
158
+ message << AGENT_VERSION
159
+ message << EVENT_TYPE
160
+ message << msg[0]
161
+ message << severity
162
+ message << extract_metadata(msg[1], msg[2])
163
+ message.join('|') + "\n"
164
+ end
165
+ end
166
+
167
+ # This method will extract the metadata information from context and other places
168
+ #
169
+ # initial structure of the data:
170
+ # <metadata> := <message-source>" "<source-ip>" "<source-port>" "<request-url>" "<request-method>" \
171
+ # "<application>" "<outcome>
172
+ # it could come from: blockEntry, lei, bbi(bot blocker), vp(virtual patch) or pri(rule)
173
+ # initially here we will use case to add it
174
+ def extract_metadata rule_id = nil, outcome = nil
175
+ message = []
176
+ sender_info = context&.activity&.http_request&.sender
177
+ rule_id ? message << "pri=#{ rule_id } " : 'asd'
178
+ request_method = if context.request.rack_request.env['REQUEST_METHOD'].length.positive?
179
+ context.request.rack_request.env['REQUEST_METHOD']
180
+ else
181
+ DEFAULT_METADATA
182
+ end
183
+ app_name = ::Contrast::APP_CONTEXT.app_name
184
+ attach_request_and_sender_info message, sender_info
185
+ message << "request=#{ context.request.url } "
186
+ message << "requestMethod=#{ request_method } "
187
+ message << "app=#{ app_name } "
188
+ message << "outcome=#{ outcome } "
189
+ end
190
+
191
+ def attach_request_and_sender_info message, sender_info
192
+ # here, instead of the ip, we need to report the first non-private 'X-Forwarded-For' Header if available.
193
+ # if not we return '-'
194
+ needed_header = extract_sender_ip
195
+ # I'm not sure if we should report the sender ip from the ActivityDtm
196
+ src = if needed_header
197
+ needed_header
198
+ else
199
+ sender_info.ip.length > 1 ? sender_info.ip : DEFAULT_METADATA
200
+ end
201
+ message << "src=#{ src }"
202
+ message << "port=#{ sender_info.port }"
203
+ end
204
+
205
+ def extract_ip_address
206
+ res = Socket.getifaddrs.reject do |ifaddr|
207
+ !ifaddr.addr.ipv4? ||
208
+ (ifaddr.flags & Socket::IFF_MULTICAST).zero? ||
209
+ ifaddr.name != 'en0' # rubocop:disable Security/Module/Name
210
+ end
211
+ return unless res.length.positive?
212
+
213
+ res[0].addr.ip_address
214
+ end
215
+
216
+ def extract_sender_ip
217
+ request_headers = context.activity.http_request.request_headers&.transform_keys(&:to_s)
218
+ request_headers['X-Forwarded-For']
219
+ end
220
+ end
221
+ end
222
+ end
@@ -51,14 +51,13 @@ module Contrast
51
51
  # deprecated and soon to be removed functionality. This method handles doing that by leveraging the standard
52
52
  # Kernel#warn approach
53
53
  def inform_deprecations
54
- # Ruby 2.5 is currently in security maintenance, meaning int is only receiving updates for security issues. It
55
- # will move to eol on 31 March 2021. As such, we can remove support for it in Q3. We'll begin the deprecation
56
- # warnings now so that customers have time to reach out if they'll be impacted.
57
- # TODO: RUBY-715 remove this part of the method, leaving it empty if there are no other deprecations, when we
58
- # drop 2.5 support.
59
- return unless RUBY_VERSION < '2.6.0'
54
+ # Ruby 2.6 will be dropped in april of 2022. We'll begin the deprecation warnings
55
+ # now so that customers have time to reach out if they'll be impacted.
56
+ # TODO: RUBY-1188 remove this part of the method, leaving it empty if there are no other deprecations, when we
57
+ # drop 2.6 support.
58
+ return unless RUBY_VERSION < '2.7.0'
60
59
 
61
- Kernel.warn('[Contrast Security] [DEPRECATION] Support for Ruby 2.5 will be removed in April 2021. '\
60
+ Kernel.warn('[Contrast Security] [DEPRECATION] Support for Ruby 2.6 will be removed in April 2022. '\
62
61
  'Please contact Customer Support prior if you require continued support.')
63
62
  end
64
63
 
@@ -59,15 +59,7 @@ module Contrast
59
59
  return @_connection_verified unless @_connection_verified.nil?
60
60
  return false if client.nil?
61
61
 
62
- # Before RUBY 2.7 there is no #ipaddr
63
- ipaddr = if RUBY_VERSION < '2.7.0'
64
- socket = TCPSocket.open(client.address, client.port)
65
- ipaddr = socket.peeraddr[3]
66
- socket.close
67
- ipaddr
68
- else
69
- client.ipaddr
70
- end
62
+ ipaddr = get_ipaddr(client)
71
63
  response = client.request(Net::HTTP::Get.new(client.address))
72
64
  verify_cert = client.address.to_s.include?('localhost') ||
73
65
  OpenSSL::SSL.verify_certificate_identity(client.peer_cert, client.address)
@@ -160,6 +152,17 @@ module Contrast
160
152
 
161
153
  @_proxy_enabled = Contrast::API.proxy_enabled? && !Contrast::API.proxy_url.nil?
162
154
  end
155
+
156
+ # Retrieve the IP address from the client.
157
+ #
158
+ # @param client [Net::HTTP]
159
+ # @return [String]
160
+ def get_ipaddr client
161
+ socket = TCPSocket.open(client.address, client.port)
162
+ ipaddr = socket.peeraddr[3]
163
+ socket.close
164
+ ipaddr
165
+ end
163
166
  end
164
167
  end
165
168
  end
@@ -63,10 +63,6 @@ module Contrast
63
63
  rescue StandardError => e
64
64
  # Anything else was our bad and we gotta catch that to allow for normal application flow
65
65
  logger.error('Unable to apply pre patch to method.', e)
66
- rescue Exception => e # rubocop:disable Lint/RescueException
67
- # This is something like NoMemoryError that we can't hope to handle. Nonetheless, shouldn't leak scope.
68
- exit_contrast_scope!
69
- raise e
70
66
  end
71
67
 
72
68
  # THIS IS CALLED FROM C. Do not change the signature lightly.
data/lib/contrast.rb CHANGED
@@ -21,10 +21,11 @@ class Object
21
21
  alias_method :cs__singleton_class, :singleton_class
22
22
  end
23
23
 
24
- if RUBY_VERSION >= '3.0.0'
24
+ if RUBY_VERSION >= '3.0.0' && RUBY_VERSION < '3.1.0'
25
25
  # This fixes Ruby 3.0 issues with Module#(some instance method) patching by preventing the prepending of
26
26
  # a JSON helper on protobuf load. String.instance_method(:+) is one of the most noticeable.
27
- # TODO: RUBY-1132 Remove this once Ruby 3 is fixed.
27
+ # This is fixed in Ruby 3.1.0
28
+ # TODO: RUBY-1132 Remove this once Ruby 3 support is dropped.
28
29
  # See bug here: https://bugs.ruby-lang.org/issues/17725
29
30
  class Class
30
31
  alias_method(:cs__orig_prepend, :prepend)
@@ -73,7 +74,7 @@ require 'contrast/utils/preflight_util'
73
74
  require 'contrast/utils/assess/sampling_util'
74
75
  require 'contrast/agent'
75
76
 
76
- if RUBY_VERSION >= '3.0.0'
77
+ if RUBY_VERSION >= '3.0.0' && RUBY_VERSION < '3.1.0'
77
78
  # Put prepend back as it was.
78
79
  Class.alias_method(:prepend, :cs__orig_prepend)
79
80
  Class.remove_method(:cs__orig_prepend)
@@ -634,6 +634,16 @@
634
634
  "source":"O",
635
635
  "target":"R",
636
636
  "action":"REMOVE"
637
+ }, {
638
+ "class_name":"MatchData",
639
+ "instance_method": true,
640
+ "method_visibility": "public",
641
+ "method_name":"match",
642
+ "source":"O",
643
+ "target":"R",
644
+ "action":"CUSTOM",
645
+ "patch_class": "Contrast::Agent::Assess::Policy::Propagator::MatchData",
646
+ "patch_method": "square_bracket_tagger"
637
647
  }, {
638
648
  "class_name":"MatchData",
639
649
  "instance_method": true,
data/ruby-agent.gemspec CHANGED
@@ -59,7 +59,7 @@ def self.add_linters spec
59
59
  spec.add_development_dependency 'debride', '1.8.2'
60
60
  spec.add_development_dependency 'fasterer', '0.9.0'
61
61
  spec.add_development_dependency 'flay', '2.12.1'
62
- spec.add_development_dependency 'steep', '0.44.1'
62
+ spec.add_development_dependency 'steep', '0.47.0'
63
63
  add_rubocop(spec)
64
64
  end
65
65
 
@@ -173,7 +173,7 @@ Gem::Specification.new do |spec|
173
173
  'Testing and Protection.'
174
174
  spec.homepage = 'https://www.contrastsecurity.com'
175
175
  spec.license = 'CONTRAST SECURITY (see license file)'
176
- spec.required_ruby_version = ['>= 2.6.0', '< 3.1.0']
176
+ spec.required_ruby_version = ['>= 2.6.0', '< 3.2.0']
177
177
 
178
178
  spec.bindir = 'exe'
179
179
  spec.executables = ['contrast_service']
@@ -1 +1 @@
1
- 2.27.3
1
+ 2.28.14
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrast-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - galen.palmer@contrastsecurity.com
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: exe
15
15
  cert_chain: []
16
- date: 2022-01-06 00:00:00.000000000 Z
16
+ date: 2022-03-03 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -147,14 +147,14 @@ dependencies:
147
147
  requirements:
148
148
  - - '='
149
149
  - !ruby/object:Gem::Version
150
- version: 0.44.1
150
+ version: 0.47.0
151
151
  type: :development
152
152
  prerelease: false
153
153
  version_requirements: !ruby/object:Gem::Requirement
154
154
  requirements:
155
155
  - - '='
156
156
  - !ruby/object:Gem::Version
157
- version: 0.44.1
157
+ version: 0.47.0
158
158
  - !ruby/object:Gem::Dependency
159
159
  name: rubocop
160
160
  requirement: !ruby/object:Gem::Requirement
@@ -617,19 +617,20 @@ executables:
617
617
  - contrast_service
618
618
  extensions:
619
619
  - ext/cs__common/extconf.rb
620
+ - ext/cs__os_information/extconf.rb
621
+ - ext/cs__assess_basic_object/extconf.rb
622
+ - ext/cs__assess_kernel/extconf.rb
623
+ - ext/cs__assess_hash/extconf.rb
624
+ - ext/cs__assess_yield_track/extconf.rb
620
625
  - ext/cs__assess_fiber_track/extconf.rb
621
- - ext/cs__assess_array/extconf.rb
622
- - ext/cs__assess_string/extconf.rb
623
626
  - ext/cs__assess_regexp/extconf.rb
624
- - ext/cs__assess_yield_track/extconf.rb
627
+ - ext/cs__assess_string/extconf.rb
628
+ - ext/cs__assess_array/extconf.rb
625
629
  - ext/cs__contrast_patch/extconf.rb
626
- - ext/cs__assess_kernel/extconf.rb
627
- - ext/cs__assess_hash/extconf.rb
630
+ - ext/cs__scope/extconf.rb
628
631
  - ext/cs__assess_string_interpolation26/extconf.rb
629
- - ext/cs__os_information/extconf.rb
630
- - ext/cs__assess_marshal_module/extconf.rb
631
- - ext/cs__assess_basic_object/extconf.rb
632
632
  - ext/cs__assess_module/extconf.rb
633
+ - ext/cs__assess_marshal_module/extconf.rb
633
634
  extra_rdoc_files: []
634
635
  files:
635
636
  - ".clang-format"
@@ -687,6 +688,9 @@ files:
687
688
  - ext/cs__os_information/cs__os_information.c
688
689
  - ext/cs__os_information/cs__os_information.h
689
690
  - ext/cs__os_information/extconf.rb
691
+ - ext/cs__scope/cs__scope.c
692
+ - ext/cs__scope/cs__scope.h
693
+ - ext/cs__scope/extconf.rb
690
694
  - ext/extconf_common.rb
691
695
  - funchook/LICENSE
692
696
  - funchook/Makefile.in
@@ -879,8 +883,19 @@ files:
879
883
  - lib/contrast/agent/assess/rule/provider/hardcoded_key.rb
880
884
  - lib/contrast/agent/assess/rule/provider/hardcoded_password.rb
881
885
  - lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb
882
- - lib/contrast/agent/assess/rule/response/autocomplete_rule.rb
886
+ - lib/contrast/agent/assess/rule/response/auto_complete_rule.rb
883
887
  - lib/contrast/agent/assess/rule/response/base_rule.rb
888
+ - lib/contrast/agent/assess/rule/response/body_rule.rb
889
+ - lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb
890
+ - lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb
891
+ - lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb
892
+ - lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb
893
+ - lib/contrast/agent/assess/rule/response/framework/rails_support.rb
894
+ - lib/contrast/agent/assess/rule/response/header_rule.rb
895
+ - lib/contrast/agent/assess/rule/response/hsts_header_rule.rb
896
+ - lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb
897
+ - lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb
898
+ - lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb
884
899
  - lib/contrast/agent/assess/tag.rb
885
900
  - lib/contrast/agent/assess/tracker.rb
886
901
  - lib/contrast/agent/at_exit_hook.rb
@@ -910,6 +925,7 @@ files:
910
925
  - lib/contrast/agent/patching/policy/policy.rb
911
926
  - lib/contrast/agent/patching/policy/policy_node.rb
912
927
  - lib/contrast/agent/patching/policy/trigger_node.rb
928
+ - lib/contrast/agent/protect/input_analyzer/input_analyzer.rb
913
929
  - lib/contrast/agent/protect/policy/applies_command_injection_rule.rb
914
930
  - lib/contrast/agent/protect/policy/applies_deserialization_rule.rb
915
931
  - lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb
@@ -934,12 +950,18 @@ files:
934
950
  - lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb
935
951
  - lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb
936
952
  - lib/contrast/agent/protect/rule/sqli/postgres_sql_scanner.rb
953
+ - lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb
954
+ - lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb
937
955
  - lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb
938
956
  - lib/contrast/agent/protect/rule/unsafe_file_upload.rb
939
957
  - lib/contrast/agent/protect/rule/xss.rb
940
958
  - lib/contrast/agent/protect/rule/xxe.rb
941
959
  - lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb
942
960
  - lib/contrast/agent/reaction_processor.rb
961
+ - lib/contrast/agent/reporting/input_analysis/input_analysis.rb
962
+ - lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb
963
+ - lib/contrast/agent/reporting/input_analysis/input_type.rb
964
+ - lib/contrast/agent/reporting/input_analysis/score_level.rb
943
965
  - lib/contrast/agent/reporting/report.rb
944
966
  - lib/contrast/agent/reporting/reporter.rb
945
967
  - lib/contrast/agent/reporting/reporting_events/application_inventory.rb
@@ -948,16 +970,19 @@ files:
948
970
  - lib/contrast/agent/reporting/reporting_events/discovered_route.rb
949
971
  - lib/contrast/agent/reporting/reporting_events/finding.rb
950
972
  - lib/contrast/agent/reporting/reporting_events/finding_event.rb
973
+ - lib/contrast/agent/reporting/reporting_events/finding_event_object.rb
974
+ - lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb
975
+ - lib/contrast/agent/reporting/reporting_events/finding_event_property.rb
976
+ - lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb
951
977
  - lib/contrast/agent/reporting/reporting_events/finding_event_source.rb
952
- - lib/contrast/agent/reporting/reporting_events/finding_object.rb
978
+ - lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb
979
+ - lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb
953
980
  - lib/contrast/agent/reporting/reporting_events/finding_request.rb
954
- - lib/contrast/agent/reporting/reporting_events/finding_signature.rb
955
- - lib/contrast/agent/reporting/reporting_events/finding_stack.rb
956
- - lib/contrast/agent/reporting/reporting_events/finding_taint_range.rb
957
981
  - lib/contrast/agent/reporting/reporting_events/library_discovery.rb
958
982
  - lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb
959
983
  - lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb
960
984
  - lib/contrast/agent/reporting/reporting_events/observed_route.rb
985
+ - lib/contrast/agent/reporting/reporting_events/poll.rb
961
986
  - lib/contrast/agent/reporting/reporting_events/preflight.rb
962
987
  - lib/contrast/agent/reporting/reporting_events/preflight_message.rb
963
988
  - lib/contrast/agent/reporting/reporting_events/reporting_event.rb
@@ -1020,10 +1045,12 @@ files:
1020
1045
  - lib/contrast/api/decorators/application_startup.rb
1021
1046
  - lib/contrast/api/decorators/application_update.rb
1022
1047
  - lib/contrast/api/decorators/architecture_component.rb
1048
+ - lib/contrast/api/decorators/bot_blocker.rb
1023
1049
  - lib/contrast/api/decorators/finding.rb
1024
1050
  - lib/contrast/api/decorators/http_request.rb
1025
1051
  - lib/contrast/api/decorators/input_analysis.rb
1026
1052
  - lib/contrast/api/decorators/instrumentation_mode.rb
1053
+ - lib/contrast/api/decorators/ip_denylist.rb
1027
1054
  - lib/contrast/api/decorators/library.rb
1028
1055
  - lib/contrast/api/decorators/library_usage_update.rb
1029
1056
  - lib/contrast/api/decorators/message.rb
@@ -1036,6 +1063,7 @@ files:
1036
1063
  - lib/contrast/api/decorators/trace_taint_range.rb
1037
1064
  - lib/contrast/api/decorators/trace_taint_range_tags.rb
1038
1065
  - lib/contrast/api/decorators/user_input.rb
1066
+ - lib/contrast/api/decorators/virtual_patch.rb
1039
1067
  - lib/contrast/api/dtm.pb.rb
1040
1068
  - lib/contrast/api/settings.pb.rb
1041
1069
  - lib/contrast/components/agent.rb
@@ -1091,7 +1119,6 @@ files:
1091
1119
  - lib/contrast/extension/delegator.rb
1092
1120
  - lib/contrast/extension/extension.rb
1093
1121
  - lib/contrast/extension/inventory.rb
1094
- - lib/contrast/extension/kernel.rb
1095
1122
  - lib/contrast/extension/module.rb
1096
1123
  - lib/contrast/extension/protect.rb
1097
1124
  - lib/contrast/extension/protect/psych.rb
@@ -1113,6 +1140,7 @@ files:
1113
1140
  - lib/contrast/framework/sinatra/support.rb
1114
1141
  - lib/contrast/funchook/funchook.rb
1115
1142
  - lib/contrast/logger/application.rb
1143
+ - lib/contrast/logger/cef_log.rb
1116
1144
  - lib/contrast/logger/format.rb
1117
1145
  - lib/contrast/logger/log.rb
1118
1146
  - lib/contrast/logger/request.rb
@@ -1193,7 +1221,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
1193
1221
  version: 2.6.0
1194
1222
  - - "<"
1195
1223
  - !ruby/object:Gem::Version
1196
- version: 3.1.0
1224
+ version: 3.2.0
1197
1225
  required_rubygems_version: !ruby/object:Gem::Requirement
1198
1226
  requirements:
1199
1227
  - - ">="