contrast-agent 3.11.0 → 3.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.flayignore +1 -0
- data/ext/cs__assess_active_record_named/cs__active_record_named.c +7 -2
- data/ext/cs__assess_active_record_named/cs__active_record_named.h +1 -0
- data/ext/cs__assess_array/cs__assess_array.c +2 -1
- data/ext/cs__assess_array/cs__assess_array.h +1 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +3 -7
- data/ext/cs__assess_basic_object/cs__assess_basic_object.h +2 -1
- data/ext/cs__assess_kernel/cs__assess_kernel.c +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +5 -7
- data/ext/cs__assess_module/cs__assess_module.h +3 -0
- data/ext/cs__common/cs__common.c +1 -1
- data/ext/cs__protect_kernel/cs__protect_kernel.c +4 -2
- data/ext/cs__protect_kernel/cs__protect_kernel.h +1 -0
- data/funchook/autom4te.cache/output.0 +13 -1
- data/funchook/autom4te.cache/requests +49 -48
- data/funchook/autom4te.cache/traces.0 +3 -0
- data/funchook/config.log +217 -378
- data/funchook/config.status +24 -23
- data/funchook/configure +13 -1
- data/funchook/src/Makefile +7 -7
- data/funchook/src/config.h +2 -2
- data/funchook/src/decoder.o +0 -0
- data/funchook/src/distorm.o +0 -0
- data/funchook/src/funchook.o +0 -0
- data/funchook/src/funchook_io.o +0 -0
- data/funchook/src/funchook_syscall.o +0 -0
- data/funchook/src/funchook_unix.o +0 -0
- data/funchook/src/funchook_x86.o +0 -0
- data/funchook/src/instructions.o +0 -0
- data/funchook/src/insts.o +0 -0
- data/funchook/src/libfunchook.so +0 -0
- data/funchook/src/mnemonics.o +0 -0
- data/funchook/src/operands.o +0 -0
- data/funchook/src/os_func.o +0 -0
- data/funchook/src/os_func_unix.o +0 -0
- data/funchook/src/prefix.o +0 -0
- data/funchook/src/printf_base.o +0 -0
- data/funchook/src/textdefs.o +0 -0
- data/funchook/src/wstring.o +0 -0
- data/funchook/test/Makefile +2 -2
- data/funchook/test/funchook_test +0 -0
- data/funchook/test/libfunchook_test.so +0 -0
- data/funchook/test/test_main.o +0 -0
- data/funchook/test/x86_64_test.o +0 -0
- data/lib/contrast.rb +0 -1
- data/lib/contrast/agent.rb +19 -22
- data/lib/contrast/agent/assess.rb +0 -9
- data/lib/contrast/agent/assess/policy/patcher.rb +1 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +1 -1
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagation_method.rb +3 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -3
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +90 -0
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +57 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +3 -7
- data/lib/contrast/agent/assess/policy/trigger_node.rb +4 -1
- data/lib/contrast/agent/assess/rule/base.rb +0 -15
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +22 -5
- data/lib/contrast/agent/assess/rule/redos.rb +0 -1
- data/lib/contrast/agent/at_exit_hook.rb +2 -2
- data/lib/contrast/agent/class_reopener.rb +9 -4
- data/lib/contrast/agent/exclusion_matcher.rb +0 -1
- data/lib/contrast/agent/inventory/policy/datastores.rb +54 -0
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/middleware.rb +38 -34
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +11 -2
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +51 -56
- data/lib/contrast/agent/patching/policy/patch.rb +2 -1
- data/lib/contrast/agent/patching/policy/patcher.rb +10 -12
- data/lib/contrast/agent/patching/policy/policy_node.rb +1 -1
- data/lib/contrast/agent/patching/policy/trigger_node.rb +1 -1
- data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +63 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +52 -0
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +68 -0
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +117 -0
- data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +54 -0
- data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +129 -0
- data/lib/contrast/agent/protect/policy/policy.rb +6 -6
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +51 -0
- data/lib/contrast/agent/protect/rule.rb +0 -5
- data/lib/contrast/agent/protect/rule/base.rb +6 -5
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +3 -3
- data/lib/contrast/agent/protect/rule/path_traversal.rb +2 -7
- data/lib/contrast/agent/protect/rule/sqli.rb +4 -4
- data/lib/contrast/agent/railtie.rb +1 -0
- data/lib/contrast/agent/request.rb +2 -6
- data/lib/contrast/agent/request_context.rb +5 -6
- data/lib/contrast/agent/request_handler.rb +2 -2
- data/lib/contrast/agent/response.rb +0 -69
- data/lib/contrast/agent/service_heartbeat.rb +2 -2
- data/lib/contrast/agent/socket_client.rb +8 -8
- data/lib/contrast/agent/static_analysis.rb +2 -3
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/application_settings.rb +1 -1
- data/lib/contrast/api/speedracer.rb +1 -1
- data/lib/contrast/components/agent.rb +17 -12
- data/lib/contrast/components/app_context.rb +33 -1
- data/lib/contrast/components/assess.rb +25 -15
- data/lib/contrast/components/contrast_service.rb +23 -67
- data/lib/contrast/components/interface.rb +4 -12
- data/lib/contrast/components/inventory.rb +5 -1
- data/lib/contrast/components/logger.rb +2 -2
- data/lib/contrast/components/protect.rb +40 -4
- data/lib/contrast/components/scope.rb +2 -52
- data/lib/contrast/components/settings.rb +24 -18
- data/lib/contrast/config/protect_rules_configuration.rb +0 -1
- data/lib/contrast/{extensions/ruby_core → extension}/assess.rb +12 -14
- data/lib/contrast/extension/assess/array.rb +77 -0
- data/lib/contrast/{extensions/ruby_core → extension}/assess/assess_extension.rb +2 -2
- data/lib/contrast/{extensions/ruby_core → extension}/assess/erb.rb +0 -0
- data/lib/contrast/extension/assess/eval_trigger.rb +78 -0
- data/lib/contrast/{extensions/ruby_core → extension}/assess/exec_trigger.rb +1 -1
- data/lib/contrast/{extensions/ruby_core → extension}/assess/fiber.rb +6 -5
- data/lib/contrast/{extensions/ruby_core → extension}/assess/hash.rb +2 -2
- data/lib/contrast/extension/assess/kernel.rb +110 -0
- data/lib/contrast/{extensions/ruby_core → extension}/assess/regexp.rb +4 -4
- data/lib/contrast/{extensions/ruby_core → extension}/assess/string.rb +5 -5
- data/lib/contrast/{extensions/ruby_core → extension}/delegator.rb +0 -0
- data/lib/contrast/{extensions/ruby_core → extension}/inventory.rb +2 -2
- data/lib/contrast/extension/kernel.rb +54 -0
- data/lib/contrast/{extensions/ruby_core → extension}/module.rb +0 -0
- data/lib/contrast/{extensions/ruby_core → extension}/protect.rb +2 -2
- data/lib/contrast/extension/protect/kernel.rb +44 -0
- data/lib/contrast/{extensions/ruby_core → extension}/protect/psych.rb +1 -1
- data/lib/contrast/{extensions/ruby_core → extension}/thread.rb +0 -0
- data/lib/contrast/framework/base_support.rb +22 -0
- data/lib/contrast/framework/manager.rb +33 -8
- data/lib/contrast/framework/rack/patch/session_cookie.rb +126 -0
- data/lib/contrast/framework/rack/patch/support.rb +24 -0
- data/lib/contrast/framework/rack/support.rb +22 -0
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +43 -0
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +103 -0
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +31 -0
- data/lib/contrast/framework/rails/patch/support.rb +67 -0
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +34 -0
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +39 -0
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +73 -0
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +33 -0
- data/lib/contrast/framework/rails/support.rb +115 -0
- data/lib/contrast/framework/sinatra/application_helper.rb +51 -0
- data/lib/contrast/framework/sinatra/patch/base.rb +83 -0
- data/lib/contrast/framework/sinatra/patch/support.rb +27 -0
- data/lib/contrast/framework/sinatra/support.rb +109 -0
- data/lib/contrast/logger/application.rb +80 -0
- data/lib/contrast/{agent/logger.rb → logger/log.rb} +23 -54
- data/lib/contrast/logger/time.rb +50 -0
- data/lib/contrast/tasks/config.rb +54 -0
- data/lib/contrast/tasks/service.rb +1 -5
- data/lib/contrast/utils/class_util.rb +1 -1
- data/lib/contrast/utils/gemfile_reader.rb +2 -2
- data/lib/contrast/utils/hash_digest.rb +2 -7
- data/lib/contrast/utils/invalid_configuration_util.rb +3 -3
- data/lib/contrast/utils/job_servers_running.rb +4 -2
- data/lib/contrast/utils/object_share.rb +0 -1
- data/lib/contrast/utils/service_response_util.rb +14 -12
- data/lib/contrast/utils/service_sender_util.rb +78 -21
- data/resources/assess/policy.json +9 -50
- data/resources/inventory/policy.json +2 -2
- data/resources/protect/policy.json +6 -6
- data/ruby-agent.gemspec +5 -1
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +69 -83
- data/funchook/src/libfunchook.dylib +0 -0
- data/funchook/test/libfunchook_test.so.dSYM/Contents/Info.plist +0 -20
- data/funchook/test/libfunchook_test.so.dSYM/Contents/Resources/DWARF/libfunchook_test.so +0 -0
- data/lib/contrast/agent/assess/rule/csrf.rb +0 -66
- data/lib/contrast/agent/assess/rule/csrf/csrf_action.rb +0 -28
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +0 -53
- data/lib/contrast/agent/assess/rule/csrf/csrf_watcher.rb +0 -136
- data/lib/contrast/agent/assess/rule/response_scanning_rule.rb +0 -47
- data/lib/contrast/agent/assess/rule/response_watcher.rb +0 -36
- data/lib/contrast/agent/assess/rule/watcher.rb +0 -36
- data/lib/contrast/agent/feature_state.rb +0 -346
- data/lib/contrast/agent/protect/rule/csrf.rb +0 -119
- data/lib/contrast/agent/protect/rule/csrf/csrf_evaluator.rb +0 -100
- data/lib/contrast/agent/protect/rule/csrf/csrf_token_injector.rb +0 -85
- data/lib/contrast/agent/settings_state.rb +0 -88
- data/lib/contrast/api/decorators/exclusion.rb +0 -20
- data/lib/contrast/extensions/framework/rack/cookie.rb +0 -24
- data/lib/contrast/extensions/framework/rack/request.rb +0 -24
- data/lib/contrast/extensions/framework/rack/response.rb +0 -23
- data/lib/contrast/extensions/framework/rails/action_controller_inheritance.rb +0 -39
- data/lib/contrast/extensions/framework/rails/action_controller_railties_helper_inherited.rb +0 -20
- data/lib/contrast/extensions/framework/rails/active_record.rb +0 -26
- data/lib/contrast/extensions/framework/rails/active_record_named.rb +0 -58
- data/lib/contrast/extensions/framework/rails/active_record_time_zone_inherited.rb +0 -21
- data/lib/contrast/extensions/framework/rails/buffer.rb +0 -28
- data/lib/contrast/extensions/framework/rails/configuration.rb +0 -27
- data/lib/contrast/extensions/framework/sinatra/base.rb +0 -59
- data/lib/contrast/extensions/ruby_core/assess/array.rb +0 -59
- data/lib/contrast/extensions/ruby_core/assess/basic_object.rb +0 -15
- data/lib/contrast/extensions/ruby_core/assess/kernel.rb +0 -96
- data/lib/contrast/extensions/ruby_core/assess/module.rb +0 -14
- data/lib/contrast/extensions/ruby_core/assess/tilt_template_trigger.rb +0 -78
- data/lib/contrast/extensions/ruby_core/assess/xpath_library_trigger.rb +0 -40
- data/lib/contrast/extensions/ruby_core/eval_trigger.rb +0 -51
- data/lib/contrast/extensions/ruby_core/inventory/datastores.rb +0 -37
- data/lib/contrast/extensions/ruby_core/protect/applies_command_injection_rule.rb +0 -61
- data/lib/contrast/extensions/ruby_core/protect/applies_deserialization_rule.rb +0 -50
- data/lib/contrast/extensions/ruby_core/protect/applies_no_sqli_rule.rb +0 -66
- data/lib/contrast/extensions/ruby_core/protect/applies_path_traversal_rule.rb +0 -115
- data/lib/contrast/extensions/ruby_core/protect/applies_sqli_rule.rb +0 -53
- data/lib/contrast/extensions/ruby_core/protect/applies_xxe_rule.rb +0 -127
- data/lib/contrast/extensions/ruby_core/protect/kernel.rb +0 -30
- data/lib/contrast/extensions/ruby_core/protect/rule_applicator.rb +0 -50
- data/lib/contrast/framework/rails_support.rb +0 -104
- data/lib/contrast/framework/sinatra_application_helper.rb +0 -49
- data/lib/contrast/framework/sinatra_support.rb +0 -104
- data/lib/contrast/utils/data_store_util.rb +0 -23
- data/lib/contrast/utils/rack_assess_session_cookie.rb +0 -104
- data/lib/contrast/utils/rails_assess_configuration.rb +0 -95
- data/lib/contrast/utils/random_util.rb +0 -22
- data/resources/csrf/inject.js +0 -44
@@ -13,7 +13,7 @@ module Contrast
|
|
13
13
|
# Protect rule.
|
14
14
|
class PathTraversal < Contrast::Agent::Protect::Rule::BaseService
|
15
15
|
include Contrast::Components::Interface
|
16
|
-
access_component :agent
|
16
|
+
access_component :agent, :analysis
|
17
17
|
|
18
18
|
NAME = 'path-traversal'
|
19
19
|
SYSTEM_PATHS = %w[
|
@@ -69,11 +69,6 @@ module Contrast
|
|
69
69
|
private
|
70
70
|
|
71
71
|
# Build a subclass of the RaspRuleSample if the sample matches
|
72
|
-
# TODO: SPEED-? delete me when implemented in Speedracer.
|
73
|
-
# this implementation duplicates logic that is moving to Speedracer
|
74
|
-
# the reason it is still here is Speedracer doesn't yet have a method to correlate
|
75
|
-
# and (update) attack results that are generated because the evaluation results
|
76
|
-
# from REP, it can only forward the attack results are generated by the agent.
|
77
72
|
def build_rep_sample context, path
|
78
73
|
sample = build_base_sample(context, nil)
|
79
74
|
sample.path_traversal_semantic = Contrast::Api::Dtm::PathTraversalSemanticAnalysisDetails.new
|
@@ -103,7 +98,7 @@ module Contrast
|
|
103
98
|
end
|
104
99
|
|
105
100
|
def custom_code_access_sysfile_enabled?
|
106
|
-
|
101
|
+
PROTECT.report_custom_code_sysfile_access?
|
107
102
|
end
|
108
103
|
|
109
104
|
def custom_code_accessing_system_file? input
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
cs__scoped_require 'contrast/agent/protect/rule/base_service'
|
5
|
-
cs__scoped_require 'contrast/
|
5
|
+
cs__scoped_require 'contrast/agent/protect/policy/applies_sqli_rule'
|
6
6
|
|
7
7
|
module Contrast
|
8
8
|
module Agent
|
@@ -84,11 +84,11 @@ module Contrast
|
|
84
84
|
|
85
85
|
def select_scanner database
|
86
86
|
@sql_scanners ||= {
|
87
|
-
Contrast::
|
87
|
+
Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_MYSQL =>
|
88
88
|
Contrast::Agent::Protect::Rule::Sqli::MysqlSqlScanner.new,
|
89
|
-
Contrast::
|
89
|
+
Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_PG =>
|
90
90
|
Contrast::Agent::Protect::Rule::Sqli::PostgresSqlScanner.new,
|
91
|
-
Contrast::
|
91
|
+
Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_SQLITE =>
|
92
92
|
Contrast::Agent::Protect::Rule::Sqli::SqliteSqlScanner.new
|
93
93
|
}.cs__freeze
|
94
94
|
|
@@ -17,7 +17,7 @@ module Contrast
|
|
17
17
|
# order to avoid repeatedly creating Strings & thrashing GC.
|
18
18
|
class Request
|
19
19
|
include Contrast::Components::Interface
|
20
|
-
access_component :logging, :scope
|
20
|
+
access_component :agent, :logging, :scope
|
21
21
|
|
22
22
|
extend Forwardable
|
23
23
|
|
@@ -159,10 +159,6 @@ module Contrast
|
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
162
|
-
def header_value key
|
163
|
-
normalized_request_headers[Contrast::Utils::StringUtils.normalized_key(key)]
|
164
|
-
end
|
165
|
-
|
166
162
|
# Return a flattened hash of params with realized paths for keys, in
|
167
163
|
# addition to a separate, valueless, entry for each nest key.
|
168
164
|
# See RUBY-621 for more details.
|
@@ -335,7 +331,7 @@ module Contrast
|
|
335
331
|
end
|
336
332
|
|
337
333
|
def omit_body?
|
338
|
-
return true if
|
334
|
+
return true if AGENT.omit_body?
|
339
335
|
return false if document_type == :XML
|
340
336
|
return false if document_type == :JSON
|
341
337
|
|
@@ -14,7 +14,7 @@ module Contrast
|
|
14
14
|
# in a standardized and normalized format which the Agent understands.
|
15
15
|
class RequestContext
|
16
16
|
include Contrast::Components::Interface
|
17
|
-
access_component :
|
17
|
+
access_component :agent, :analysis, :logging, :settings, :scope
|
18
18
|
|
19
19
|
EMPTY_INPUT_ANALYSIS_PB = Contrast::Api::Settings::InputAnalysis.new
|
20
20
|
|
@@ -90,10 +90,8 @@ module Contrast
|
|
90
90
|
# For TS routes
|
91
91
|
@observed_route.signature = route.route
|
92
92
|
@observed_route.verb = route.verb
|
93
|
-
@observed_route.session_id =
|
94
|
-
|
95
|
-
# TODO: SPEED-273: deprecate when SR handles this. ContrastUI API currently does not allow empty url, so we have to provide a default
|
96
|
-
@observed_route.url = route.url.empty? ? Contrast::Utils::ObjectShare::SLASH : route.url
|
93
|
+
@observed_route.session_id = SETTINGS.session_id
|
94
|
+
@observed_route.url = route.url if route.url
|
97
95
|
end
|
98
96
|
|
99
97
|
# Collect the results for the given rule with the given action
|
@@ -111,10 +109,11 @@ module Contrast
|
|
111
109
|
end
|
112
110
|
|
113
111
|
def service_extract_request
|
112
|
+
return false unless AGENT.enabled?
|
114
113
|
return false unless PROTECT.enabled?
|
115
114
|
return false if @do_not_track
|
116
115
|
|
117
|
-
service_response =
|
116
|
+
service_response = Contrast::Utils::ServiceSenderUtil.send_event_immediately(@activity.http_request)
|
118
117
|
return false unless service_response
|
119
118
|
|
120
119
|
handle_protect_state(service_response)
|
@@ -8,7 +8,7 @@ module Contrast
|
|
8
8
|
# prefilter and postfilter).
|
9
9
|
class RequestHandler
|
10
10
|
include Contrast::Components::Interface
|
11
|
-
access_component :agent, :
|
11
|
+
access_component :agent, :logging, :scope
|
12
12
|
|
13
13
|
attr_reader :ruleset, :context
|
14
14
|
|
@@ -20,7 +20,7 @@ module Contrast
|
|
20
20
|
def send_activity_messages
|
21
21
|
Contrast::Utils::GemfileReader.instance.generate_library_usage(context.activity)
|
22
22
|
[context.server_activity, context.activity, context.observed_route].each do |message|
|
23
|
-
|
23
|
+
Contrast::Utils::ServiceSenderUtil.push_to_ready_queue(message)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -97,26 +97,6 @@ module Contrast
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
def header key
|
101
|
-
return unless rack_response
|
102
|
-
|
103
|
-
if @is_array
|
104
|
-
normalized_headers[Contrast::Utils::StringUtils.normalized_key(key)]
|
105
|
-
else
|
106
|
-
rack_response.get_header(key)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def set_header key, value
|
111
|
-
return unless rack_response
|
112
|
-
|
113
|
-
if @is_array
|
114
|
-
Rack::Utils.set_cookie_header!(rack_response[1], key, value)
|
115
|
-
elsif rack_response.is_a?(Rack::Response)
|
116
|
-
rack_response.set_header(key, value)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
100
|
# The response body can change during the request lifecycle
|
121
101
|
# We should not extract it out as a variable here, or we'll miss those
|
122
102
|
# changes.
|
@@ -127,59 +107,10 @@ module Contrast
|
|
127
107
|
extract_body(body_content)
|
128
108
|
end
|
129
109
|
|
130
|
-
def update_body body_string
|
131
|
-
return unless rack_response
|
132
|
-
|
133
|
-
successfully_updated_body = true
|
134
|
-
if @is_array
|
135
|
-
if rack_response[2].is_a?(Rack::BodyProxy)
|
136
|
-
successfully_updated_body = update_rack_body_proxy(body_string, true)
|
137
|
-
else
|
138
|
-
rack_response[2] = [body_string]
|
139
|
-
end
|
140
|
-
elsif rack_response.body.is_a?(Rack::BodyProxy)
|
141
|
-
successfully_updated_body = update_rack_body_proxy(body_string)
|
142
|
-
else
|
143
|
-
rack_response.body = body_string
|
144
|
-
end
|
145
|
-
update_content_length(body_string.bytesize) if successfully_updated_body
|
146
|
-
end
|
147
|
-
|
148
|
-
# Set the length header for this response. This value should be set ot the
|
149
|
-
# bytesize, NOT THE LENGTH, of the response body. Otherwise, we may get
|
150
|
-
# got by the Lint thing.
|
151
|
-
CONTENT_LENGTH_HEADER = 'Content-Length'.cs__freeze
|
152
|
-
def update_content_length length
|
153
|
-
headers[CONTENT_LENGTH_HEADER] = length.to_s
|
154
|
-
end
|
155
|
-
|
156
110
|
private
|
157
111
|
|
158
112
|
HTTP_PREFIX = /^[Hh][Tt][Tt][Pp][_-]/i.cs__freeze
|
159
113
|
|
160
|
-
def update_rack_body_proxy body_string, is_array = false
|
161
|
-
top_body_proxy = is_array ? rack_response[2] : rack_response
|
162
|
-
parent_body_proxy = top_body_proxy
|
163
|
-
until (next_body = parent_body_proxy.instance_variable_get(:@body)).cs__class != Rack::BodyProxy
|
164
|
-
parent_body_proxy = next_body
|
165
|
-
end
|
166
|
-
|
167
|
-
if next_body.cs__class.to_s == 'ActionDispatch::Response::RackBody'
|
168
|
-
modified_response = next_body.instance_variable_defined?(:@response) ? next_body.instance_variable_get(:@response) : nil
|
169
|
-
if modified_response
|
170
|
-
modified_response.body = body_string
|
171
|
-
next_body.instance_variable_set(:@response, modified_response)
|
172
|
-
end
|
173
|
-
elsif next_body.is_a?(Array) && next_body[0].cs__class.to_s == 'ActionView::OutputBuffer'
|
174
|
-
new_body = ActionView::OutputBuffer.new(body_string)
|
175
|
-
next_body[0] = new_body
|
176
|
-
else
|
177
|
-
logger.warn('Detected unsupported Rack::BodyProxy internal response class', module: next_body.cs__class)
|
178
|
-
return false
|
179
|
-
end
|
180
|
-
true
|
181
|
-
end
|
182
|
-
|
183
114
|
# Given some holder of the content of the response's body, extract that
|
184
115
|
# content and return it as a String
|
185
116
|
#
|
@@ -9,7 +9,7 @@ module Contrast
|
|
9
9
|
# ensure that it maintains this Agent's ApplicationContext.
|
10
10
|
class ServiceHeartbeat
|
11
11
|
include Contrast::Components::Interface
|
12
|
-
access_component :
|
12
|
+
access_component :logging
|
13
13
|
|
14
14
|
# Spec recommends 30 seconds, we're going with 15.
|
15
15
|
REFRESH_INTERVAL_SEC = 15
|
@@ -19,7 +19,7 @@ module Contrast
|
|
19
19
|
logger.info('Starting heartbeat thread.')
|
20
20
|
loop do
|
21
21
|
begin
|
22
|
-
|
22
|
+
Contrast::Utils::ServiceSenderUtil.push_to_ready_queue(poll_message)
|
23
23
|
end
|
24
24
|
sleep REFRESH_INTERVAL_SEC
|
25
25
|
end
|
@@ -27,14 +27,6 @@ module Contrast
|
|
27
27
|
@ensure_running = Mutex.new
|
28
28
|
end
|
29
29
|
|
30
|
-
def init_connection
|
31
|
-
if CONTRAST_SERVICE.use_tcp?
|
32
|
-
Contrast::Api::TcpSocket.new(CONTRAST_SERVICE.host, CONTRAST_SERVICE.port)
|
33
|
-
else
|
34
|
-
Contrast::Api::UnixSocket.new(CONTRAST_SERVICE.socket_path)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
30
|
def service_unavailable?
|
39
31
|
speedracer.nil?
|
40
32
|
end
|
@@ -76,6 +68,14 @@ module Contrast
|
|
76
68
|
|
77
69
|
private
|
78
70
|
|
71
|
+
def init_connection
|
72
|
+
if CONTRAST_SERVICE.use_tcp?
|
73
|
+
Contrast::Api::TcpSocket.new(CONTRAST_SERVICE.host, CONTRAST_SERVICE.port)
|
74
|
+
else
|
75
|
+
Contrast::Api::UnixSocket.new(CONTRAST_SERVICE.socket_path)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
79
|
def restart?
|
80
80
|
status.was_connected? && status.failed?
|
81
81
|
end
|
@@ -11,7 +11,7 @@ module Contrast
|
|
11
11
|
class StaticAnalysis
|
12
12
|
include Singleton
|
13
13
|
include Contrast::Components::Interface
|
14
|
-
access_component :logging, :analysis, :
|
14
|
+
access_component :logging, :analysis, :scope
|
15
15
|
class << self
|
16
16
|
# After the first request is complete, we do a one-time manual catchup to review and
|
17
17
|
# report the already-loaded gems.
|
@@ -33,8 +33,7 @@ module Contrast
|
|
33
33
|
app_update_msg = Contrast::Api::Dtm::ApplicationUpdate.build
|
34
34
|
|
35
35
|
Contrast::Utils::InventoryUtil.append_db_config(app_update_msg)
|
36
|
-
|
37
|
-
CONTRAST_SERVICE.queue_message app_update_msg
|
36
|
+
Contrast::Utils::ServiceSenderUtil.push_to_ready_queue(app_update_msg)
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
@@ -26,7 +26,7 @@ module Contrast
|
|
26
26
|
modes_by_id: translated_protection_mode_by_id,
|
27
27
|
exclusion_matchers: translated_exclusions,
|
28
28
|
disabled_assess_rules: disabled_assess_rules,
|
29
|
-
session_id: session_id
|
29
|
+
session_id: Contrast::Utils::StringUtils.force_utf8(session_id)
|
30
30
|
}
|
31
31
|
end
|
32
32
|
end
|
@@ -78,7 +78,7 @@ module Contrast
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def determine_startup_options
|
81
|
-
return { out: :out, err: :err } if
|
81
|
+
return { out: :out, err: :err } if CONTRAST_SERVICE.logger_path == 'STDOUT'
|
82
82
|
|
83
83
|
{ out: File::NULL, err: File::NULL }
|
84
84
|
end
|
@@ -32,18 +32,12 @@ module Contrast
|
|
32
32
|
@enabled = false
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
35
|
+
def ruleset
|
36
|
+
@_ruleset ||= Contrast::Agent::RuleSet.new(retrieve_ruleset&.values)
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
# Instead of asking specifically for assess or protect rules, we can ask agent to retrieve
|
43
|
-
# the correct ruleset based on enabled modes. Since these can change on a per request basis,
|
44
|
-
# we shouldn't memoize these.
|
45
|
-
def ruleset
|
46
|
-
Contrast::Agent::RuleSet.new(retrieve_ruleset&.values)
|
39
|
+
def reset_ruleset
|
40
|
+
@_ruleset = nil
|
47
41
|
end
|
48
42
|
|
49
43
|
def patch_interpolation?
|
@@ -64,8 +58,17 @@ module Contrast
|
|
64
58
|
@_interpolation_enabled
|
65
59
|
end
|
66
60
|
|
67
|
-
def
|
68
|
-
|
61
|
+
def omit_body?
|
62
|
+
@_omit_body = true?(CONFIG.root.agent.omit_body) if @_omit_body.nil?
|
63
|
+
@_omit_body
|
64
|
+
end
|
65
|
+
|
66
|
+
def exception_control
|
67
|
+
@_exception_control ||= {
|
68
|
+
enable: true?(CONFIG.root.agent.ruby.exceptions.capture),
|
69
|
+
status: CONFIG.root.agent.ruby.exceptions.override_status || 403,
|
70
|
+
message: CONFIG.root.agent.ruby.exceptions.override_message || Contrast::Utils::ObjectShare::OVERRIDE_MESSAGE
|
71
|
+
}
|
69
72
|
end
|
70
73
|
|
71
74
|
def skip_instrumentation? loaded_module_name
|
@@ -93,6 +96,8 @@ module Contrast
|
|
93
96
|
end
|
94
97
|
|
95
98
|
def retrieve_ruleset
|
99
|
+
return {} unless enabled?
|
100
|
+
|
96
101
|
if ASSESS.enabled? && PROTECT.enabled?
|
97
102
|
ASSESS.rules.merge(PROTECT.rules)
|
98
103
|
elsif ASSESS.enabled?
|
@@ -16,13 +16,23 @@ module Contrast
|
|
16
16
|
include Contrast::Components::ComponentBase
|
17
17
|
include Contrast::Components::Interface
|
18
18
|
|
19
|
-
access_component :config
|
19
|
+
access_component :agent, :config
|
20
20
|
|
21
21
|
DEFAULT_APP_NAME = 'rails'
|
22
22
|
DEFAULT_APP_PATH = '/'
|
23
23
|
DEFAULT_SERVER_NAME = 'localhost'
|
24
24
|
DEFAULT_SERVER_PATH = '/'
|
25
25
|
|
26
|
+
def ready?
|
27
|
+
@_ready ||= AGENT.enabled? &&
|
28
|
+
Contrast::Utils::ServiceSenderUtil.connection_established? &&
|
29
|
+
Contrast::Utils::ServiceResponseUtil.update_received?
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
original_pid
|
34
|
+
end
|
35
|
+
|
26
36
|
def server_type
|
27
37
|
@_server_type ||= begin
|
28
38
|
tmp = CONFIG.root.server.type
|
@@ -118,6 +128,28 @@ module Contrast
|
|
118
128
|
def instrument_middleware_stack?
|
119
129
|
!Contrast::Utils::JobServersRunning.job_servers_running?
|
120
130
|
end
|
131
|
+
|
132
|
+
def disabled_agent_rake_tasks
|
133
|
+
CONFIG.root.agent.ruby.disabled_agent_rake_tasks
|
134
|
+
end
|
135
|
+
|
136
|
+
# Determines if the Process we're currently in matches that of the
|
137
|
+
# Process in which the App Context instance was created.
|
138
|
+
# If it doesn't, that indicates the running context is in a new
|
139
|
+
# Process.
|
140
|
+
# @return [Boolean] if we're in the original Process in which the
|
141
|
+
# App Context instance was initialized.
|
142
|
+
def in_new_process?
|
143
|
+
current_pid = Process.pid
|
144
|
+
original_pid = pid
|
145
|
+
current_pid != original_pid
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def original_pid
|
151
|
+
@_original_pid ||= Process.pid
|
152
|
+
end
|
121
153
|
end
|
122
154
|
|
123
155
|
COMPONENT_INTERFACE = Interface.new
|
@@ -12,12 +12,14 @@ module Contrast
|
|
12
12
|
include Contrast::Components::ComponentBase
|
13
13
|
include Contrast::Components::Interface
|
14
14
|
|
15
|
-
access_component :settings
|
15
|
+
access_component :config, :settings
|
16
16
|
|
17
17
|
def enabled?
|
18
|
-
|
18
|
+
# config overrides if forcibly set
|
19
|
+
return false if forcibly_disabled?
|
20
|
+
return true if forcibly_enabled?
|
19
21
|
|
20
|
-
|
22
|
+
SETTINGS.assess_enabled?
|
21
23
|
end
|
22
24
|
|
23
25
|
def tainted_columns
|
@@ -25,39 +27,47 @@ module Contrast
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def forcibly_disabled?
|
28
|
-
|
30
|
+
@_forcibly_disabled = false?(CONFIG.root.assess.enable) if @_forcibly_disabled.nil?
|
31
|
+
@_forcibly_disabled
|
29
32
|
end
|
30
33
|
|
31
34
|
def rule_disabled? name
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def disabled_rules
|
36
|
-
state.assess_disabled_rules
|
35
|
+
disabled_rules.include?(name)
|
37
36
|
end
|
38
37
|
|
39
38
|
def scan_response?
|
40
|
-
|
39
|
+
@_scan_response = !false?(CONFIG.root.assess.enable_scan_response) if @_scan_response.nil?
|
40
|
+
@_scan_response
|
41
41
|
end
|
42
42
|
|
43
43
|
def track_frozen_sources?
|
44
|
-
|
44
|
+
@_track_frozen_sources = !false?(CONFIG.root.agent.ruby.track_frozen_sources) if @_track_frozen_sources.nil?
|
45
|
+
@_track_frozen_sources
|
45
46
|
end
|
46
47
|
|
47
48
|
def require_scan?
|
48
|
-
|
49
|
+
@_require_scan = !false?(CONFIG.root.agent.ruby.require_scan) if @_require_scan.nil?
|
50
|
+
@_require_scan
|
49
51
|
end
|
50
52
|
|
51
53
|
def tags
|
52
|
-
|
54
|
+
CONFIG.root.assess&.tags
|
53
55
|
end
|
54
56
|
|
55
57
|
def rules
|
56
58
|
SETTINGS.assess_rules
|
57
59
|
end
|
58
60
|
|
59
|
-
|
60
|
-
|
61
|
+
private
|
62
|
+
|
63
|
+
def forcibly_enabled?
|
64
|
+
@_forcibly_enabled = true?(CONFIG.root.assess.enable) if @_forcibly_enabled.nil?
|
65
|
+
@_forcibly_enabled
|
66
|
+
end
|
67
|
+
|
68
|
+
def disabled_rules
|
69
|
+
# TODO: RUBY-903
|
70
|
+
CONFIG.root.assess&.rules&.disabled_rules || SETTINGS.disabled_assess_rules || []
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|