contrast-agent 5.1.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/cs__assess_array/cs__assess_array.c +7 -0
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +19 -5
- data/ext/cs__assess_fiber_track/cs__assess_fiber_track.c +1 -1
- data/ext/cs__assess_hash/cs__assess_hash.c +3 -4
- data/ext/cs__assess_kernel/cs__assess_kernel.c +7 -5
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +26 -12
- data/ext/cs__assess_module/cs__assess_module.c +7 -7
- data/ext/cs__assess_string/cs__assess_string.c +13 -1
- data/ext/cs__common/cs__common.c +16 -11
- data/ext/cs__common/cs__common.h +1 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +100 -64
- data/ext/cs__contrast_patch/cs__contrast_patch.h +2 -0
- data/ext/cs__os_information/cs__os_information.c +13 -10
- data/ext/cs__scope/cs__scope.c +796 -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/finalizers/hash.rb +2 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +50 -27
- data/lib/contrast/agent/assess/policy/policy_node_utils.rb +51 -0
- data/lib/contrast/agent/assess/policy/preshift.rb +8 -2
- data/lib/contrast/agent/assess/policy/propagation_method.rb +47 -13
- data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -5
- data/lib/contrast/agent/assess/policy/propagator/buffer.rb +118 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +19 -4
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +2 -0
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +18 -2
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +17 -3
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/substitution_utils.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator.rb +1 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +7 -7
- data/lib/contrast/agent/assess/policy/trigger_method.rb +6 -1
- data/lib/contrast/agent/assess/property/tagged.rb +1 -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 +35 -0
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +0 -7
- data/lib/contrast/agent/deadzone/policy/policy.rb +0 -6
- data/lib/contrast/agent/exclusion_matcher.rb +3 -3
- data/lib/contrast/agent/middleware.rb +4 -1
- 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 +4 -4
- data/lib/contrast/agent/patching/policy/policy_node.rb +15 -2
- data/lib/contrast/agent/protect/exploitable_collection.rb +38 -0
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +147 -0
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +2 -1
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +2 -2
- data/lib/contrast/agent/protect/rule/base.rb +61 -2
- data/lib/contrast/agent/protect/rule/base_service.rb +12 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +15 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +83 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +64 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +6 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +96 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +13 -1
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +231 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +28 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +88 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +118 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +33 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +82 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +45 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +42 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +4 -0
- data/lib/contrast/agent/reporting/attack_result/attack_result.rb +63 -0
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +52 -0
- data/lib/contrast/agent/reporting/attack_result/response_type.rb +29 -0
- data/lib/contrast/agent/reporting/attack_result/user_input.rb +87 -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/masker/masker.rb +246 -0
- data/lib/contrast/agent/reporting/masker/masker_utils.rb +58 -0
- data/lib/contrast/agent/reporting/report.rb +3 -0
- data/lib/contrast/agent/reporting/reporter.rb +31 -12
- data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +30 -0
- data/lib/contrast/agent/reporting/reporting_events/application_inventory.rb +7 -3
- data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +40 -0
- data/lib/contrast/agent/reporting/reporting_events/application_startup_instrumentation.rb +27 -0
- 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/library_usage_observation.rb +5 -5
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +9 -9
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +29 -0
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +6 -4
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +8 -6
- 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 +17 -5
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +54 -45
- data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +97 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +69 -7
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +63 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +123 -85
- data/lib/contrast/agent/reporting/settings/application_settings.rb +9 -0
- data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +5 -33
- data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +1 -1
- data/lib/contrast/agent/reporting/settings/sampling.rb +36 -0
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking.rb +110 -0
- data/lib/contrast/agent/reporting/settings/sensitive_data_masking_rule.rb +58 -0
- data/lib/contrast/agent/request_context.rb +7 -2
- data/lib/contrast/agent/request_context_extend.rb +85 -21
- data/lib/contrast/agent/request_handler.rb +4 -0
- data/lib/contrast/agent/scope.rb +102 -107
- data/lib/contrast/agent/service_heartbeat.rb +45 -2
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +51 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +36 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +97 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +65 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +47 -0
- data/lib/contrast/agent/{metric_telemetry_event.rb → telemetry/events/metric_telemetry_event.rb} +1 -1
- data/lib/contrast/agent/{startup_metrics_telemetry_event.rb → telemetry/events/startup_metrics_telemetry_event.rb} +3 -3
- data/lib/contrast/agent/{telemetry_event.rb → telemetry/events/telemetry_event.rb} +1 -1
- data/lib/contrast/agent/{telemetry.rb → telemetry/telemetry.rb} +32 -19
- data/lib/contrast/agent/thread_watcher.rb +1 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +3 -0
- data/lib/contrast/api/communication/speedracer.rb +1 -1
- data/lib/contrast/api/decorators/address.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/response_type.rb +30 -0
- data/lib/contrast/api/decorators/user_input.rb +11 -1
- data/lib/contrast/api/decorators/virtual_patch.rb +34 -0
- data/lib/contrast/api/decorators.rb +1 -0
- data/lib/contrast/components/app_context.rb +0 -4
- data/lib/contrast/components/assess.rb +14 -0
- data/lib/contrast/components/logger.rb +5 -0
- data/lib/contrast/components/protect.rb +6 -4
- data/lib/contrast/components/sampling.rb +7 -11
- data/lib/contrast/components/scope.rb +98 -91
- data/lib/contrast/components/settings.rb +106 -8
- data/lib/contrast/config/agent_configuration.rb +41 -12
- data/lib/contrast/config/api_configuration.rb +37 -12
- data/lib/contrast/config/api_proxy_configuration.rb +12 -3
- data/lib/contrast/config/application_configuration.rb +38 -14
- data/lib/contrast/config/assess_configuration.rb +47 -12
- data/lib/contrast/config/assess_rules_configuration.rb +15 -3
- data/lib/contrast/config/base_configuration.rb +18 -50
- data/lib/contrast/config/certification_configuration.rb +17 -3
- data/lib/contrast/config/exception_configuration.rb +14 -3
- data/lib/contrast/config/heap_dump_configuration.rb +43 -17
- data/lib/contrast/config/inventory_configuration.rb +17 -3
- data/lib/contrast/config/logger_configuration.rb +10 -3
- data/lib/contrast/config/protect_configuration.rb +17 -7
- data/lib/contrast/config/protect_rule_configuration.rb +17 -8
- data/lib/contrast/config/protect_rules_configuration.rb +115 -17
- data/lib/contrast/config/request_audit_configuration.rb +26 -3
- data/lib/contrast/config/root_configuration.rb +52 -12
- data/lib/contrast/config/ruby_configuration.rb +60 -22
- data/lib/contrast/config/sampling_configuration.rb +19 -9
- data/lib/contrast/config/server_configuration.rb +19 -10
- data/lib/contrast/config/service_configuration.rb +27 -11
- data/lib/contrast/configuration.rb +5 -3
- data/lib/contrast/extension/assess/string.rb +20 -1
- data/lib/contrast/extension/module.rb +0 -1
- data/lib/contrast/framework/manager.rb +2 -2
- data/lib/contrast/logger/application.rb +1 -1
- data/lib/contrast/logger/cef_log.rb +151 -0
- data/lib/contrast/tasks/config.rb +90 -3
- data/lib/contrast/utils/assess/object_store.rb +36 -0
- data/lib/contrast/utils/assess/propagation_method_utils.rb +6 -0
- data/lib/contrast/utils/class_util.rb +3 -12
- data/lib/contrast/utils/hash_digest.rb +14 -6
- data/lib/contrast/utils/input_classification.rb +73 -0
- data/lib/contrast/utils/log_utils.rb +114 -0
- data/lib/contrast/utils/middleware_utils.rb +9 -9
- data/lib/contrast/utils/net_http_base.rb +13 -10
- data/lib/contrast/utils/object_share.rb +2 -1
- data/lib/contrast/utils/os.rb +0 -5
- data/lib/contrast/utils/patching/policy/patch_utils.rb +4 -9
- data/lib/contrast/utils/response_utils.rb +18 -33
- data/lib/contrast/utils/telemetry.rb +1 -1
- data/lib/contrast/utils/telemetry_client.rb +1 -1
- data/lib/contrast/utils/telemetry_identifier.rb +1 -1
- data/lib/contrast.rb +4 -3
- data/resources/assess/policy.json +98 -0
- data/resources/deadzone/policy.json +0 -86
- data/ruby-agent.gemspec +9 -8
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +103 -38
- 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,65 @@
|
|
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_relative 'telemetry_exception_base'
|
5
|
+
require_relative 'telemetry_exception_stack_frame'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Agent
|
9
|
+
# This class will hold the all the information for the specific exception
|
10
|
+
# and will be passed in the Exception message itself
|
11
|
+
class TelemetryExceptionMessageException < Contrast::Agent::TelemetryExceptionBase
|
12
|
+
VALIDATIONS = {
|
13
|
+
type: { required: true, range: 1..256 },
|
14
|
+
module_name: { required: false, range: 1..256 },
|
15
|
+
value: { required: false, range: 1..256 },
|
16
|
+
stack_frames: { required: true, range: 1..128, class: Contrast::Agent::TelemetryExceptionStackFrame }
|
17
|
+
}.cs__freeze
|
18
|
+
|
19
|
+
# @return [String] The type of the exception itself
|
20
|
+
attr_reader :type
|
21
|
+
|
22
|
+
# @return [Array<Contrast::Agent::TelemetryExceptionStackFrame>] stack frames for the message exception
|
23
|
+
attr_reader :stack_frames
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
attr_reader :module_name
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :value
|
30
|
+
|
31
|
+
def initialize type, stack_frame
|
32
|
+
super()
|
33
|
+
@type = type
|
34
|
+
@stack_frames = Array.new(1, stack_frame)
|
35
|
+
validate VALIDATIONS
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param stack_frame [Contrast::Agent::TelemetryExceptionStackFrame]
|
39
|
+
def push stack_frame
|
40
|
+
validate_class stack_frame, Contrast::Agent::TelemetryExceptionStackFrame, 'stack_frame'
|
41
|
+
@stack_frames << stack_frame
|
42
|
+
end
|
43
|
+
|
44
|
+
def module_name= module_name
|
45
|
+
validate_field VALIDATIONS[:module_name], 'module_name'
|
46
|
+
@module_name = module_name
|
47
|
+
end
|
48
|
+
|
49
|
+
def value= value
|
50
|
+
validate_field VALIDATIONS[:value], 'value'
|
51
|
+
@value = value
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_controlled_hash
|
55
|
+
super
|
56
|
+
{
|
57
|
+
type: type,
|
58
|
+
stack_frames: stack_frames.map(&:to_controlled_hash),
|
59
|
+
module_name: module_name,
|
60
|
+
value: value
|
61
|
+
}.compact
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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_relative 'telemetry_exception_base'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
# This class will hold the all the information for the specific exception
|
9
|
+
# and will be passed in the Exception message itself
|
10
|
+
class TelemetryExceptionStackFrame < Contrast::Agent::TelemetryExceptionBase
|
11
|
+
VALIDATIONS = {
|
12
|
+
function: { required: true, range: 1..256 },
|
13
|
+
type: { required: true, range: 1..256 },
|
14
|
+
module_name: { required: false, range: 1..256 }
|
15
|
+
}.cs__freeze
|
16
|
+
|
17
|
+
# @return [String] The type of the exception itself
|
18
|
+
attr_reader :type
|
19
|
+
|
20
|
+
# @return [String] the function of the stack trace
|
21
|
+
attr_reader :function
|
22
|
+
|
23
|
+
# @return [Boolean] Is it in contrast
|
24
|
+
attr_accessor :in_contrast
|
25
|
+
|
26
|
+
def initialize function, type
|
27
|
+
super()
|
28
|
+
@function = function
|
29
|
+
@type = type
|
30
|
+
@in_contrast = false
|
31
|
+
validate VALIDATIONS
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :module_name
|
35
|
+
|
36
|
+
def module_name= module_name
|
37
|
+
validate_field VALIDATIONS[:module_name], 'module_name'
|
38
|
+
@module_name = module_name
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_controlled_hash
|
42
|
+
super
|
43
|
+
{ function: function, type: type, inContrast: in_contrast, module_name: module_name }.compact
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'contrast/utils/metrics_hash'
|
5
|
-
require 'contrast/agent/metric_telemetry_event'
|
5
|
+
require 'contrast/agent/telemetry/events/metric_telemetry_event'
|
6
6
|
require 'contrast/agent/version'
|
7
7
|
require 'contrast/utils/os'
|
8
8
|
|
@@ -69,9 +69,9 @@ module Contrast
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def add_config_keys config, nested_key
|
72
|
-
config.
|
72
|
+
config.to_hash.reject! { |_k, v| REJECTED_VALUES.include?(v) }
|
73
73
|
|
74
|
-
config.
|
74
|
+
config.to_hash.each do |k, v|
|
75
75
|
unless v.cs__class <= Contrast::Config::BaseConfiguration
|
76
76
|
@settings << "#{ nested_key }.#{ k }"
|
77
77
|
next
|
@@ -27,13 +27,13 @@ module Contrast
|
|
27
27
|
mac = Contrast::Utils::Telemetry::Identifier.mac
|
28
28
|
app_name = Contrast::Utils::Telemetry::Identifier.app_name
|
29
29
|
id = mac + app_name if mac && app_name
|
30
|
-
Digest::SHA2.new(256).hexdigest(id ||
|
30
|
+
Digest::SHA2.new(256).hexdigest(id || "_#{ SecureRandom.uuid }")
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def instance_id
|
35
35
|
@_instance_id ||= Digest::SHA2.new(256).hexdigest(Contrast::Utils::Telemetry::Identifier.mac ||
|
36
|
-
|
36
|
+
"_#{ SecureRandom.uuid }")
|
37
37
|
end
|
38
38
|
|
39
39
|
def enabled?
|
@@ -44,17 +44,15 @@ module Contrast
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def telemetry_enabled?
|
47
|
-
opt_out_telemetry = return_value(:telemetry_opt_outs)
|
48
|
-
return false if opt_out_telemetry.
|
49
|
-
return false if opt_out_telemetry.to_s.casecmp('1').zero?
|
47
|
+
opt_out_telemetry = return_value(:telemetry_opt_outs).to_s
|
48
|
+
return false if opt_out_telemetry.casecmp?('true') || opt_out_telemetry == '1'
|
50
49
|
|
51
50
|
# In case of connection error, do not create the background thread or queue,
|
52
51
|
# as if the opt-out env var was set
|
53
52
|
@_client = Contrast::Utils::TelemetryClient.new
|
54
53
|
ip_opt_out_telemetry = @_client.initialize_connection(URL)
|
55
54
|
if ip_opt_out_telemetry.nil?
|
56
|
-
logger.warn(
|
57
|
-
logger.warn('THE SERVICE IS GOING TO BE TERMINATED!!')
|
55
|
+
logger.warn("Connection was not established properly!!! \n Telemetry reporting will be disabled!")
|
58
56
|
return false
|
59
57
|
end
|
60
58
|
|
@@ -87,17 +85,27 @@ module Contrast
|
|
87
85
|
# general metrics every 3 hours, starting from implementation startup.
|
88
86
|
@_thread = Contrast::Agent::Thread.new do
|
89
87
|
logger.debug('Starting background telemetry thread.')
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
88
|
+
loop do
|
89
|
+
next unless client && connection
|
90
|
+
|
91
|
+
until queue.empty?
|
92
|
+
event = queue.pop
|
93
|
+
begin
|
94
|
+
logger.debug('This is the current processed event', event)
|
95
|
+
sleep_time = request_with_response event
|
96
|
+
if sleep_time
|
97
|
+
sleep(sleep_time)
|
98
|
+
logger.debug('Retrying to process event', event)
|
99
|
+
retry_sleep_time = request_with_response event
|
100
|
+
sleep(retry_sleep_time) unless retry_sleep_time.nil?
|
101
|
+
end
|
102
|
+
rescue StandardError => e
|
103
|
+
logger.error('Could not send message to service from telemetry queue.', e)
|
104
|
+
stop!
|
105
|
+
end
|
106
|
+
end
|
107
|
+
sleep(SUGGESTED_TIMEOUT)
|
99
108
|
end
|
100
|
-
sleep(SUGGESTED_TIMEOUT)
|
101
109
|
end
|
102
110
|
end
|
103
111
|
|
@@ -110,7 +118,6 @@ module Contrast
|
|
110
118
|
return unless cs__class.enabled?
|
111
119
|
|
112
120
|
logger.debug('Enqueued event for sending', event_type: event.cs__class)
|
113
|
-
|
114
121
|
queue << event if event
|
115
122
|
end
|
116
123
|
|
@@ -123,8 +130,14 @@ module Contrast
|
|
123
130
|
def stop!
|
124
131
|
return unless running?
|
125
132
|
|
126
|
-
|
133
|
+
@_enabled = false
|
127
134
|
delete_queue!
|
135
|
+
super
|
136
|
+
end
|
137
|
+
|
138
|
+
def request_with_response event
|
139
|
+
res = client.send_request event, connection
|
140
|
+
client.handle_response res
|
128
141
|
end
|
129
142
|
|
130
143
|
private
|
@@ -5,7 +5,7 @@ require 'contrast/components/logger'
|
|
5
5
|
require 'contrast/agent/service_heartbeat'
|
6
6
|
require 'contrast/api/communication/messaging_queue'
|
7
7
|
require 'contrast/agent/reporting/report'
|
8
|
-
require 'contrast/agent/telemetry'
|
8
|
+
require 'contrast/agent/telemetry/telemetry'
|
9
9
|
|
10
10
|
module Contrast
|
11
11
|
module Agent
|
data/lib/contrast/agent.rb
CHANGED
@@ -32,6 +32,8 @@ require 'contrast/utils/invalid_configuration_util'
|
|
32
32
|
# Collect findings
|
33
33
|
require 'contrast/utils/findings'
|
34
34
|
|
35
|
+
# Collect Exploites and Attacks
|
36
|
+
require 'contrast/agent/protect/exploitable_collection'
|
35
37
|
# scoping
|
36
38
|
require 'contrast/agent/scope'
|
37
39
|
|
@@ -52,6 +54,7 @@ module Contrast
|
|
52
54
|
# build a map for tracking the context of the current request
|
53
55
|
REQUEST_TRACKER = Contrast::Utils::ThreadTracker.new
|
54
56
|
FINDINGS = Contrast::Utils::Findings.new
|
57
|
+
EXPLOITS = Contrast::Agent::Protect::ExploitableCollection.new
|
55
58
|
|
56
59
|
# @return [Contrast::Framework::Manager]
|
57
60
|
def self.framework_manager
|
@@ -28,7 +28,7 @@ module Contrast
|
|
28
28
|
@_build_receiver ||= begin
|
29
29
|
address = new
|
30
30
|
address.host = 'localhost'
|
31
|
-
address.ip = '127.0.0.1'
|
31
|
+
address.ip = '127.0.0.1' # rubocop:disable Style/IpAddresses
|
32
32
|
begin
|
33
33
|
Timeout.timeout(1) do
|
34
34
|
address.host = Contrast::Utils::StringUtils.force_utf8(Socket.gethostname)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'contrast/utils/string_utils'
|
6
|
+
require 'contrast/components/base'
|
7
|
+
|
8
|
+
module Contrast
|
9
|
+
module Api
|
10
|
+
module Decorators
|
11
|
+
# Used to decorate the {Contrast::Api::Dtm::BotBlockerDetails} protobuf
|
12
|
+
# model so it can own the request which its data is for.
|
13
|
+
module BotBlockerDetails
|
14
|
+
def self.included klass
|
15
|
+
klass.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Used to add class methods to the AgentStartup class on inclusion of the decorator
|
19
|
+
module ClassMethods
|
20
|
+
def build
|
21
|
+
new
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param result [Contrast::Api::Dtm::BotBlockerDetails]
|
25
|
+
def to_controlled_hash result
|
26
|
+
{
|
27
|
+
bot: result.bot,
|
28
|
+
user_agent: result.user_agent
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Contrast::Api::Dtm::BotBlockerDetails.include(Contrast::Api::Decorators::BotBlockerDetails)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'contrast/utils/string_utils'
|
6
|
+
require 'contrast/components/base'
|
7
|
+
|
8
|
+
module Contrast
|
9
|
+
module Api
|
10
|
+
module Decorators
|
11
|
+
# Used to decorate the {Contrast::Api::Dtm::IpDenylistDetails} protobuf
|
12
|
+
# model so it can own the request which its data is for.
|
13
|
+
module IpDenylistDetails
|
14
|
+
def self.included klass
|
15
|
+
klass.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Used to add class methods to the AgentStartup class on inclusion of the decorator
|
19
|
+
module ClassMethods
|
20
|
+
def build
|
21
|
+
new
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param result [Contrast::Api::Dtm::IpDenylistDetails]
|
25
|
+
def to_controlled_hash result
|
26
|
+
{
|
27
|
+
ip: result.ip,
|
28
|
+
uuid: result.uuid
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Contrast::Api::Dtm::IpDenylistDetails.include(Contrast::Api::Decorators::IpDenylistDetails)
|
@@ -20,6 +20,35 @@ module Contrast
|
|
20
20
|
sample.user_input.document_type = Contrast::Utils::StringUtils.force_utf8(context.request.document_type)
|
21
21
|
sample
|
22
22
|
end
|
23
|
+
|
24
|
+
# @param result [Contrast::Api::Dtm::RaspRuleSample]
|
25
|
+
def to_controlled_hash result
|
26
|
+
{
|
27
|
+
timestamp: Time.at(result.timestamp_ms).iso8601,
|
28
|
+
user_input: result.user_input,
|
29
|
+
brute_force: result.brute_force,
|
30
|
+
bot_blocker: result.bot_blocker,
|
31
|
+
cmdi: result.cmdi,
|
32
|
+
csrf: result.csrf,
|
33
|
+
cve: result.cve,
|
34
|
+
untrusted_deserialization: result.untrusted_deserialization,
|
35
|
+
el_injection: result.el_injection,
|
36
|
+
mark_of_the_beast: result.mark_of_the_beast,
|
37
|
+
padding_oracle: result.padding_oracle,
|
38
|
+
path_traversal: result.path_traversal,
|
39
|
+
re_dos: result.re_dos,
|
40
|
+
sqli: result.sqli,
|
41
|
+
ssrf: result.ssrf,
|
42
|
+
virtual_patch: result.virtual_patch,
|
43
|
+
xss: result.xss,
|
44
|
+
xxe: result.xxe,
|
45
|
+
no_sqli: result.no_sqli,
|
46
|
+
method_tampering: result.method_tampering,
|
47
|
+
path_traversal_semantic: result.path_traversal_semantic,
|
48
|
+
ssjs: result.ssjs,
|
49
|
+
ip_denylist: result.ip_denylist
|
50
|
+
}
|
51
|
+
end
|
23
52
|
end
|
24
53
|
end
|
25
54
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'protobuf/message'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Api
|
9
|
+
module Decorators
|
10
|
+
# Used to decorate the {Contrast::Api::Dtm::AttackResult::ResponseType} protobuf
|
11
|
+
# model so it can add SUSPICIOUS.
|
12
|
+
module ResponseType
|
13
|
+
::Protobuf::Enum.define(:SUSPICIOUS, 6)
|
14
|
+
|
15
|
+
def self.included klass
|
16
|
+
klass.extend(ClassMethods)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Used to add class methods to the class on inclusion of the decorator
|
20
|
+
module ClassMethods
|
21
|
+
def build
|
22
|
+
new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Contrast::Api::Dtm::AttackResult::ResponseType.include(Contrast::Api::Decorators::ResponseType)
|
@@ -25,11 +25,21 @@ module Contrast
|
|
25
25
|
return UNKNOWN_USER_INPUT.dup unless ia_result
|
26
26
|
|
27
27
|
user_input = new
|
28
|
-
user_input.input_type = ia_result.input_type.to_i
|
29
28
|
user_input.matcher_ids = ia_result.ids
|
30
29
|
user_input.path = ia_result.path.to_s
|
31
30
|
user_input.key = ia_result.key.to_s
|
32
31
|
user_input.value = ia_result.value.to_s
|
32
|
+
if ia_result.input_type
|
33
|
+
#
|
34
|
+
# InputAnalysis have local Agent implementation, so we need ot take care of difference
|
35
|
+
# if we pass data from wrong place - we need to handle the TypeError in throws
|
36
|
+
begin
|
37
|
+
user_input.input_type = ia_result.input_type.to_i
|
38
|
+
rescue TypeError, NoMethodError => _e
|
39
|
+
user_input.input_type = ia_result.input_type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
33
43
|
user_input
|
34
44
|
end
|
35
45
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'contrast/api/dtm.pb'
|
5
|
+
require 'contrast/utils/string_utils'
|
6
|
+
require 'contrast/components/base'
|
7
|
+
|
8
|
+
module Contrast
|
9
|
+
module Api
|
10
|
+
module Decorators
|
11
|
+
# Used to decorate the {Contrast::Api::Dtm::VirtualPatchDetails} protobuf
|
12
|
+
# model so it can own the request which its data is for.
|
13
|
+
module VirtualPatchDetails
|
14
|
+
def self.included klass
|
15
|
+
klass.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Used to add class methods to the AgentStartup class on inclusion of the decorator
|
19
|
+
module ClassMethods
|
20
|
+
def build
|
21
|
+
new
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param result [Contrast::Api::Dtm::VirtualPatchDetails]
|
25
|
+
def to_controlled_hash result
|
26
|
+
{ uuid: result.uuid }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Contrast::Api::Dtm::VirtualPatchDetails.include(Contrast::Api::Decorators::VirtualPatchDetails)
|
@@ -110,6 +110,20 @@ module Contrast
|
|
110
110
|
[]
|
111
111
|
end
|
112
112
|
|
113
|
+
def track_original_object?
|
114
|
+
if @_track_original_object.nil?
|
115
|
+
@_track_original_object = !false?(::Contrast::CONFIG.root.assess.enable_original_object)
|
116
|
+
end
|
117
|
+
|
118
|
+
@_track_original_object
|
119
|
+
end
|
120
|
+
|
121
|
+
# The id for this process, based on the session metadata or id provided by the user, as indicated in
|
122
|
+
# application startup.
|
123
|
+
def session_id
|
124
|
+
::Contrast::SETTINGS.assess_state.session_id
|
125
|
+
end
|
126
|
+
|
113
127
|
private
|
114
128
|
|
115
129
|
def forcibly_enabled?
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'contrast/logger/log'
|
5
|
+
require 'contrast/logger/cef_log'
|
5
6
|
require 'contrast/components/base'
|
6
7
|
|
7
8
|
module Contrast
|
@@ -12,6 +13,10 @@ module Contrast
|
|
12
13
|
Contrast::Logger::Log.instance.logger
|
13
14
|
end
|
14
15
|
|
16
|
+
def cef_logger
|
17
|
+
@_cef_logger ||= Contrast::Logger::CEFLog.instance.tap(&:build_logger)
|
18
|
+
end
|
19
|
+
|
15
20
|
def add_trace_perf_logging_for sym, custom_message = nil
|
16
21
|
logger.add_trace_perf_logging(self, sym, custom_message)
|
17
22
|
end
|
@@ -28,7 +28,8 @@ module Contrast
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def rule_mode rule_id
|
31
|
-
|
31
|
+
str = rule_id.tr('-', '_')
|
32
|
+
::Contrast::CONFIG.root.protect.rules[str]&.applicable_mode ||
|
32
33
|
::Contrast::SETTINGS.application_state.modes_by_id[rule_id] ||
|
33
34
|
Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION
|
34
35
|
end
|
@@ -40,15 +41,16 @@ module Contrast
|
|
40
41
|
def report_any_command_execution?
|
41
42
|
if @_report_any_command_execution.nil?
|
42
43
|
ctrl = rule_config[Contrast::Agent::Protect::Rule::CmdInjection::NAME]
|
43
|
-
@_report_any_command_execution = true?(ctrl.disable_system_commands)
|
44
|
+
@_report_any_command_execution = ctrl && true?(ctrl.disable_system_commands)
|
44
45
|
end
|
45
46
|
@_report_any_command_execution
|
46
47
|
end
|
47
48
|
|
48
49
|
def report_custom_code_sysfile_access?
|
49
50
|
if @_report_custom_code_sysfile_access.nil?
|
50
|
-
|
51
|
-
|
51
|
+
name_changed = Contrast::Agent::Protect::Rule::PathTraversal::NAME.tr('-', '_')
|
52
|
+
ctrl = rule_config[name_changed]
|
53
|
+
@_report_custom_code_sysfile_access = ctrl && true?(ctrl.detect_custom_code_accessing_system_files)
|
52
54
|
end
|
53
55
|
@_report_custom_code_sysfile_access
|
54
56
|
end
|
@@ -48,7 +48,7 @@ module Contrast
|
|
48
48
|
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
49
49
|
# @return [Boolean] the resolution of the config_settings, settings, and default value
|
50
50
|
def enabled? config_settings, settings
|
51
|
-
true?([config_settings&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].
|
51
|
+
true?([config_settings&.enable, settings&.enabled, DEFAULT_SAMPLING_ENABLED].compact[0])
|
52
52
|
end
|
53
53
|
|
54
54
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
@@ -56,7 +56,7 @@ module Contrast
|
|
56
56
|
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
57
57
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
58
58
|
def baseline config_settings, settings
|
59
|
-
[config_settings&.baseline, settings&.baseline
|
59
|
+
[config_settings&.baseline, settings&.baseline].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_BASELINE
|
60
60
|
end
|
61
61
|
|
62
62
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
@@ -64,10 +64,8 @@ module Contrast
|
|
64
64
|
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
65
65
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
66
66
|
def request_frequency config_settings, settings
|
67
|
-
[
|
68
|
-
|
69
|
-
DEFAULT_SAMPLING_REQUEST_FREQUENCY
|
70
|
-
].map(&:to_i).find(&:positive?)
|
67
|
+
[config_settings&.request_frequency, settings&.request_frequency].map(&:to_i).find(&:positive?) ||
|
68
|
+
DEFAULT_SAMPLING_REQUEST_FREQUENCY
|
71
69
|
end
|
72
70
|
|
73
71
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
@@ -75,10 +73,8 @@ module Contrast
|
|
75
73
|
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
76
74
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
77
75
|
def response_frequency config_settings, settings
|
78
|
-
[
|
79
|
-
|
80
|
-
DEFAULT_SAMPLING_RESPONSE_FREQUENCY
|
81
|
-
].map(&:to_i).find(&:positive?)
|
76
|
+
[config_settings&.response_frequency, settings&.response_frequency].map(&:to_i).find(&:positive?) ||
|
77
|
+
DEFAULT_SAMPLING_RESPONSE_FREQUENCY
|
82
78
|
end
|
83
79
|
|
84
80
|
# @param config_settings [Contrast::Config::SamplingConfiguration] the Sampling configuration as provided by
|
@@ -86,7 +82,7 @@ module Contrast
|
|
86
82
|
# @param settings [Contrast::Api::Settings::Sampling] the Sampling settings as provided by TeamServer
|
87
83
|
# @return [Integer] the resolution of the config_settings, settings, and default value
|
88
84
|
def window config_settings, settings
|
89
|
-
[config_settings&.window_ms, settings&.window_ms
|
85
|
+
[config_settings&.window_ms, settings&.window_ms].map(&:to_i).find(&:positive?) || DEFAULT_SAMPLING_WINDOW_MS
|
90
86
|
end
|
91
87
|
end
|
92
88
|
|