contrast-agent 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/cs__assess_kernel/cs__assess_kernel.c +7 -4
- data/ext/cs__assess_module/cs__assess_module.c +7 -7
- data/ext/cs__common/cs__common.c +4 -0
- data/ext/cs__common/cs__common.h +1 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +52 -27
- data/ext/cs__contrast_patch/cs__contrast_patch.h +2 -0
- data/ext/cs__scope/cs__scope.c +747 -0
- data/ext/cs__scope/cs__scope.h +88 -0
- data/ext/cs__scope/extconf.rb +5 -0
- data/lib/contrast/agent/assess/contrast_event.rb +20 -13
- data/lib/contrast/agent/assess/contrast_object.rb +4 -1
- data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -5
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +2 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -1
- data/lib/contrast/agent/assess/rule/response/{autocomplete_rule.rb → auto_complete_rule.rb} +4 -3
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +12 -79
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +109 -0
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +157 -0
- data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +26 -0
- data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +14 -15
- data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +5 -25
- data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +29 -0
- data/lib/contrast/agent/assess/rule/response/header_rule.rb +70 -0
- data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +12 -36
- data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +2 -1
- data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +26 -0
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +36 -0
- data/lib/contrast/agent/middleware.rb +1 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +1 -3
- data/lib/contrast/agent/patching/policy/patch.rb +2 -6
- data/lib/contrast/agent/patching/policy/patcher.rb +1 -1
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +94 -0
- data/lib/contrast/agent/protect/rule/base.rb +28 -1
- data/lib/contrast/agent/protect/rule/base_service.rb +10 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +2 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +6 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +5 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +1 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +124 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +121 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +33 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +4 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +44 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +115 -0
- data/lib/contrast/agent/reporting/input_analysis/input_type.rb +44 -0
- data/lib/contrast/agent/reporting/input_analysis/score_level.rb +21 -0
- data/lib/contrast/agent/reporting/report.rb +1 -0
- data/lib/contrast/agent/reporting/reporter.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +69 -36
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +88 -59
- data/lib/contrast/agent/reporting/reporting_events/{finding_object.rb → finding_event_object.rb} +24 -20
- data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +39 -0
- data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +40 -0
- data/lib/contrast/agent/reporting/reporting_events/{finding_signature.rb → finding_event_signature.rb} +29 -24
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +12 -8
- data/lib/contrast/agent/reporting/reporting_events/{finding_stack.rb → finding_event_stack.rb} +23 -19
- data/lib/contrast/agent/reporting/reporting_events/{finding_taint_range.rb → finding_event_taint_range.rb} +17 -15
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +26 -53
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +29 -0
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +5 -4
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +28 -20
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +13 -1
- data/lib/contrast/agent/request_context.rb +6 -1
- data/lib/contrast/agent/request_context_extend.rb +85 -21
- data/lib/contrast/agent/scope.rb +102 -107
- data/lib/contrast/agent/service_heartbeat.rb +45 -2
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/bot_blocker.rb +37 -0
- data/lib/contrast/api/decorators/ip_denylist.rb +37 -0
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +29 -0
- data/lib/contrast/api/decorators/user_input.rb +11 -1
- data/lib/contrast/api/decorators/virtual_patch.rb +34 -0
- data/lib/contrast/components/logger.rb +5 -0
- data/lib/contrast/components/protect.rb +4 -2
- data/lib/contrast/components/scope.rb +98 -91
- data/lib/contrast/config/agent_configuration.rb +58 -12
- data/lib/contrast/config/api_configuration.rb +100 -12
- data/lib/contrast/config/api_proxy_configuration.rb +55 -3
- data/lib/contrast/config/application_configuration.rb +114 -15
- data/lib/contrast/config/assess_configuration.rb +106 -12
- data/lib/contrast/config/assess_rules_configuration.rb +44 -3
- data/lib/contrast/config/base_configuration.rb +1 -0
- data/lib/contrast/config/certification_configuration.rb +74 -3
- data/lib/contrast/config/exception_configuration.rb +61 -3
- data/lib/contrast/config/heap_dump_configuration.rb +101 -17
- data/lib/contrast/config/inventory_configuration.rb +64 -3
- data/lib/contrast/config/logger_configuration.rb +46 -3
- data/lib/contrast/config/protect_rule_configuration.rb +36 -9
- data/lib/contrast/config/protect_rules_configuration.rb +120 -17
- data/lib/contrast/config/request_audit_configuration.rb +68 -3
- data/lib/contrast/config/ruby_configuration.rb +96 -22
- data/lib/contrast/config/sampling_configuration.rb +76 -10
- data/lib/contrast/config/server_configuration.rb +56 -11
- data/lib/contrast/configuration.rb +6 -3
- data/lib/contrast/logger/cef_log.rb +151 -0
- data/lib/contrast/utils/hash_digest.rb +14 -6
- data/lib/contrast/utils/log_utils.rb +114 -0
- data/lib/contrast/utils/middleware_utils.rb +6 -7
- data/lib/contrast/utils/net_http_base.rb +12 -9
- data/lib/contrast/utils/patching/policy/patch_utils.rb +0 -4
- data/lib/contrast.rb +4 -3
- data/ruby-agent.gemspec +1 -1
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +41 -21
- data/lib/contrast/agent/assess/rule/response/cachecontrol_rule.rb +0 -184
- data/lib/contrast/agent/assess/rule/response/clickjacking_rule.rb +0 -66
- data/lib/contrast/agent/assess/rule/response/x_content_type_rule.rb +0 -52
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_rule.rb +0 -53
- 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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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.
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
#
|
|
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)
|
data/ruby-agent.gemspec
CHANGED
|
@@ -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.
|
|
176
|
+
spec.required_ruby_version = ['>= 2.6.0', '< 3.2.0']
|
|
177
177
|
|
|
178
178
|
spec.bindir = 'exe'
|
|
179
179
|
spec.executables = ['contrast_service']
|
data/service_executables/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.28.6
|
|
Binary file
|
|
Binary file
|
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.
|
|
4
|
+
version: 5.2.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-
|
|
16
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
19
19
|
name: bundler
|
|
@@ -617,19 +617,20 @@ executables:
|
|
|
617
617
|
- contrast_service
|
|
618
618
|
extensions:
|
|
619
619
|
- ext/cs__common/extconf.rb
|
|
620
|
-
- ext/
|
|
621
|
-
- ext/
|
|
620
|
+
- ext/cs__os_information/extconf.rb
|
|
621
|
+
- ext/cs__assess_basic_object/extconf.rb
|
|
622
|
+
- ext/cs__assess_kernel/extconf.rb
|
|
622
623
|
- ext/cs__assess_hash/extconf.rb
|
|
623
|
-
- ext/
|
|
624
|
+
- ext/cs__assess_yield_track/extconf.rb
|
|
624
625
|
- ext/cs__assess_fiber_track/extconf.rb
|
|
625
|
-
- ext/cs__assess_string_interpolation26/extconf.rb
|
|
626
|
-
- ext/cs__assess_basic_object/extconf.rb
|
|
627
|
-
- ext/cs__assess_array/extconf.rb
|
|
628
626
|
- ext/cs__assess_regexp/extconf.rb
|
|
629
|
-
- ext/cs__assess_kernel/extconf.rb
|
|
630
|
-
- ext/cs__os_information/extconf.rb
|
|
631
627
|
- ext/cs__assess_string/extconf.rb
|
|
628
|
+
- ext/cs__assess_array/extconf.rb
|
|
629
|
+
- ext/cs__contrast_patch/extconf.rb
|
|
630
|
+
- ext/cs__scope/extconf.rb
|
|
631
|
+
- ext/cs__assess_string_interpolation26/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,16 +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/
|
|
886
|
+
- lib/contrast/agent/assess/rule/response/auto_complete_rule.rb
|
|
883
887
|
- lib/contrast/agent/assess/rule/response/base_rule.rb
|
|
884
|
-
- lib/contrast/agent/assess/rule/response/
|
|
885
|
-
- lib/contrast/agent/assess/rule/response/
|
|
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
|
|
886
891
|
- lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb
|
|
887
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
|
|
888
895
|
- lib/contrast/agent/assess/rule/response/hsts_header_rule.rb
|
|
889
896
|
- lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb
|
|
890
|
-
- lib/contrast/agent/assess/rule/response/
|
|
891
|
-
- lib/contrast/agent/assess/rule/response/
|
|
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
|
|
892
899
|
- lib/contrast/agent/assess/tag.rb
|
|
893
900
|
- lib/contrast/agent/assess/tracker.rb
|
|
894
901
|
- lib/contrast/agent/at_exit_hook.rb
|
|
@@ -918,6 +925,7 @@ files:
|
|
|
918
925
|
- lib/contrast/agent/patching/policy/policy.rb
|
|
919
926
|
- lib/contrast/agent/patching/policy/policy_node.rb
|
|
920
927
|
- lib/contrast/agent/patching/policy/trigger_node.rb
|
|
928
|
+
- lib/contrast/agent/protect/input_analyzer/input_analyzer.rb
|
|
921
929
|
- lib/contrast/agent/protect/policy/applies_command_injection_rule.rb
|
|
922
930
|
- lib/contrast/agent/protect/policy/applies_deserialization_rule.rb
|
|
923
931
|
- lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb
|
|
@@ -942,12 +950,18 @@ files:
|
|
|
942
950
|
- lib/contrast/agent/protect/rule/sqli/default_sql_scanner.rb
|
|
943
951
|
- lib/contrast/agent/protect/rule/sqli/mysql_sql_scanner.rb
|
|
944
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
|
|
945
955
|
- lib/contrast/agent/protect/rule/sqli/sqlite_sql_scanner.rb
|
|
946
956
|
- lib/contrast/agent/protect/rule/unsafe_file_upload.rb
|
|
947
957
|
- lib/contrast/agent/protect/rule/xss.rb
|
|
948
958
|
- lib/contrast/agent/protect/rule/xxe.rb
|
|
949
959
|
- lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb
|
|
950
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
|
|
951
965
|
- lib/contrast/agent/reporting/report.rb
|
|
952
966
|
- lib/contrast/agent/reporting/reporter.rb
|
|
953
967
|
- lib/contrast/agent/reporting/reporting_events/application_inventory.rb
|
|
@@ -956,16 +970,19 @@ files:
|
|
|
956
970
|
- lib/contrast/agent/reporting/reporting_events/discovered_route.rb
|
|
957
971
|
- lib/contrast/agent/reporting/reporting_events/finding.rb
|
|
958
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
|
|
959
977
|
- lib/contrast/agent/reporting/reporting_events/finding_event_source.rb
|
|
960
|
-
- lib/contrast/agent/reporting/reporting_events/
|
|
978
|
+
- lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb
|
|
979
|
+
- lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb
|
|
961
980
|
- lib/contrast/agent/reporting/reporting_events/finding_request.rb
|
|
962
|
-
- lib/contrast/agent/reporting/reporting_events/finding_signature.rb
|
|
963
|
-
- lib/contrast/agent/reporting/reporting_events/finding_stack.rb
|
|
964
|
-
- lib/contrast/agent/reporting/reporting_events/finding_taint_range.rb
|
|
965
981
|
- lib/contrast/agent/reporting/reporting_events/library_discovery.rb
|
|
966
982
|
- lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb
|
|
967
983
|
- lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb
|
|
968
984
|
- lib/contrast/agent/reporting/reporting_events/observed_route.rb
|
|
985
|
+
- lib/contrast/agent/reporting/reporting_events/poll.rb
|
|
969
986
|
- lib/contrast/agent/reporting/reporting_events/preflight.rb
|
|
970
987
|
- lib/contrast/agent/reporting/reporting_events/preflight_message.rb
|
|
971
988
|
- lib/contrast/agent/reporting/reporting_events/reporting_event.rb
|
|
@@ -1028,10 +1045,12 @@ files:
|
|
|
1028
1045
|
- lib/contrast/api/decorators/application_startup.rb
|
|
1029
1046
|
- lib/contrast/api/decorators/application_update.rb
|
|
1030
1047
|
- lib/contrast/api/decorators/architecture_component.rb
|
|
1048
|
+
- lib/contrast/api/decorators/bot_blocker.rb
|
|
1031
1049
|
- lib/contrast/api/decorators/finding.rb
|
|
1032
1050
|
- lib/contrast/api/decorators/http_request.rb
|
|
1033
1051
|
- lib/contrast/api/decorators/input_analysis.rb
|
|
1034
1052
|
- lib/contrast/api/decorators/instrumentation_mode.rb
|
|
1053
|
+
- lib/contrast/api/decorators/ip_denylist.rb
|
|
1035
1054
|
- lib/contrast/api/decorators/library.rb
|
|
1036
1055
|
- lib/contrast/api/decorators/library_usage_update.rb
|
|
1037
1056
|
- lib/contrast/api/decorators/message.rb
|
|
@@ -1044,6 +1063,7 @@ files:
|
|
|
1044
1063
|
- lib/contrast/api/decorators/trace_taint_range.rb
|
|
1045
1064
|
- lib/contrast/api/decorators/trace_taint_range_tags.rb
|
|
1046
1065
|
- lib/contrast/api/decorators/user_input.rb
|
|
1066
|
+
- lib/contrast/api/decorators/virtual_patch.rb
|
|
1047
1067
|
- lib/contrast/api/dtm.pb.rb
|
|
1048
1068
|
- lib/contrast/api/settings.pb.rb
|
|
1049
1069
|
- lib/contrast/components/agent.rb
|
|
@@ -1099,7 +1119,6 @@ files:
|
|
|
1099
1119
|
- lib/contrast/extension/delegator.rb
|
|
1100
1120
|
- lib/contrast/extension/extension.rb
|
|
1101
1121
|
- lib/contrast/extension/inventory.rb
|
|
1102
|
-
- lib/contrast/extension/kernel.rb
|
|
1103
1122
|
- lib/contrast/extension/module.rb
|
|
1104
1123
|
- lib/contrast/extension/protect.rb
|
|
1105
1124
|
- lib/contrast/extension/protect/psych.rb
|
|
@@ -1121,6 +1140,7 @@ files:
|
|
|
1121
1140
|
- lib/contrast/framework/sinatra/support.rb
|
|
1122
1141
|
- lib/contrast/funchook/funchook.rb
|
|
1123
1142
|
- lib/contrast/logger/application.rb
|
|
1143
|
+
- lib/contrast/logger/cef_log.rb
|
|
1124
1144
|
- lib/contrast/logger/format.rb
|
|
1125
1145
|
- lib/contrast/logger/log.rb
|
|
1126
1146
|
- lib/contrast/logger/request.rb
|
|
@@ -1201,7 +1221,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
1201
1221
|
version: 2.6.0
|
|
1202
1222
|
- - "<"
|
|
1203
1223
|
- !ruby/object:Gem::Version
|
|
1204
|
-
version: 3.
|
|
1224
|
+
version: 3.2.0
|
|
1205
1225
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1206
1226
|
requirements:
|
|
1207
1227
|
- - ">="
|