contrast-agent 5.3.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 +1 -2
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +26 -12
- data/ext/cs__assess_module/cs__assess_module.c +1 -1
- data/ext/cs__assess_string/cs__assess_string.c +13 -1
- data/ext/cs__common/cs__common.c +12 -11
- data/ext/cs__contrast_patch/cs__contrast_patch.c +54 -43
- data/ext/cs__os_information/cs__os_information.c +13 -10
- data/ext/cs__scope/cs__scope.c +146 -97
- 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/propagator/buffer.rb +118 -0
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +19 -4
- 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 +3 -1
- data/lib/contrast/agent/assess/property/tagged.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/auto_complete_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +3 -3
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +1 -1
- data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +1 -1
- 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 +3 -1
- data/lib/contrast/agent/patching/policy/patcher.rb +3 -3
- 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 +61 -8
- 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 +37 -5
- data/lib/contrast/agent/protect/rule/base_service.rb +3 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +13 -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/http_method_tampering/http_method_tampering_input_classification.rb +96 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +8 -0
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +231 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +27 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +18 -54
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +1 -4
- 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/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/masker/masker.rb +246 -0
- data/lib/contrast/agent/reporting/masker/masker_utils.rb +58 -0
- data/lib/contrast/agent/reporting/report.rb +2 -0
- data/lib/contrast/agent/reporting/reporter.rb +23 -11
- 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 +1 -1
- 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/preflight_message.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +8 -6
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +16 -5
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +27 -26
- 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 +68 -6
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_mode.rb +63 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +122 -96
- 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 +1 -1
- data/lib/contrast/agent/request_context_extend.rb +1 -1
- data/lib/contrast/agent/request_handler.rb +4 -0
- 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/response_type.rb +30 -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/protect.rb +2 -2
- data/lib/contrast/components/sampling.rb +7 -11
- data/lib/contrast/components/settings.rb +106 -8
- data/lib/contrast/config/agent_configuration.rb +13 -30
- data/lib/contrast/config/api_configuration.rb +4 -67
- data/lib/contrast/config/api_proxy_configuration.rb +2 -45
- data/lib/contrast/config/application_configuration.rb +9 -84
- data/lib/contrast/config/assess_configuration.rb +10 -69
- data/lib/contrast/config/assess_rules_configuration.rb +9 -38
- data/lib/contrast/config/base_configuration.rb +17 -50
- data/lib/contrast/config/certification_configuration.rb +6 -63
- data/lib/contrast/config/exception_configuration.rb +5 -52
- data/lib/contrast/config/heap_dump_configuration.rb +6 -64
- data/lib/contrast/config/inventory_configuration.rb +2 -49
- data/lib/contrast/config/logger_configuration.rb +0 -36
- data/lib/contrast/config/protect_configuration.rb +17 -7
- data/lib/contrast/config/protect_rule_configuration.rb +12 -30
- data/lib/contrast/config/protect_rules_configuration.rb +21 -26
- data/lib/contrast/config/request_audit_configuration.rb +6 -48
- data/lib/contrast/config/root_configuration.rb +52 -12
- data/lib/contrast/config/ruby_configuration.rb +0 -36
- data/lib/contrast/config/sampling_configuration.rb +1 -57
- data/lib/contrast/config/server_configuration.rb +0 -36
- data/lib/contrast/config/service_configuration.rb +5 -44
- data/lib/contrast/configuration.rb +2 -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 +1 -1
- 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/input_classification.rb +73 -0
- data/lib/contrast/utils/log_utils.rb +1 -1
- data/lib/contrast/utils/middleware_utils.rb +9 -8
- data/lib/contrast/utils/net_http_base.rb +1 -1
- 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 -5
- 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/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 +73 -28
@@ -0,0 +1,36 @@
|
|
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_message'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Agent
|
9
|
+
# This class will hold the basic information for a Parent Telemetry Exception Event
|
10
|
+
class TelemetryExceptionEvent < Contrast::Agent::TelemetryExceptionBase
|
11
|
+
# Array of Telemetry Exclusions
|
12
|
+
# @return [Array<Contrast::Agent::TelemetryExceptionMessage>]
|
13
|
+
attr_reader :exclusions
|
14
|
+
|
15
|
+
# Initialization of the Parent Event requires us to require the exception
|
16
|
+
# to be created
|
17
|
+
#
|
18
|
+
# @param message [Contrast::Agent::TelemetryExceptionMessage]
|
19
|
+
def initialize message
|
20
|
+
super()
|
21
|
+
validate_class message, Contrast::Agent::TelemetryExceptionMessage, 'exception_message'
|
22
|
+
@exclusions = Array.new(1, message)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param message [Contrast::Agent::TelemetryExceptionMessage]
|
26
|
+
def push message
|
27
|
+
validate_class message, Contrast::Agent::TelemetryExceptionMessage, 'exception_message'
|
28
|
+
@exclusions << message
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_controlled_hash
|
32
|
+
exclusions.map(&:to_controlled_hash)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,97 @@
|
|
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_message_exception'
|
6
|
+
|
7
|
+
module Contrast
|
8
|
+
module Agent
|
9
|
+
# This class will hold the all the information for the specific exceptions
|
10
|
+
# and will be passed in the the event to be sent to TS
|
11
|
+
class TelemetryExceptionMessage < Contrast::Agent::TelemetryExceptionBase
|
12
|
+
VALIDATIONS = {
|
13
|
+
instance: { required: true, range: 12..64 },
|
14
|
+
tags: { required: true, range: 1..512 },
|
15
|
+
logger: { required: false, range: 1..128 },
|
16
|
+
message: { required: false, range: 1..512 },
|
17
|
+
exceptions: { required: true, range: 1..512, class: Contrast::Agent::TelemetryExceptionMessageException }
|
18
|
+
}.cs__freeze
|
19
|
+
|
20
|
+
# Timestamp of creation in ISO8601 format
|
21
|
+
# @return [Integer]
|
22
|
+
attr_reader :timestamp
|
23
|
+
|
24
|
+
# An Instance ID as defined in Unique Identification // Application ID
|
25
|
+
# @return [String]
|
26
|
+
attr_reader :instance
|
27
|
+
|
28
|
+
# Tags are key-value string pairs that annotate either metrics
|
29
|
+
# or errors to help provide context, filtering, grouping, and deduplication.
|
30
|
+
# @return [Hash{String => String}]
|
31
|
+
attr_reader :tags
|
32
|
+
|
33
|
+
# @return [Integer] A number of the occurrences of the exception
|
34
|
+
attr_accessor :occurrences
|
35
|
+
|
36
|
+
# Array of exceptions, but in our case the Array will only include one exception
|
37
|
+
# @return [Array<Contrast::Agent::TelemetryExceptionMessageException>]
|
38
|
+
attr_reader :exceptions
|
39
|
+
|
40
|
+
# @return [String,nil] A string denoting the origin of this error.
|
41
|
+
attr_reader :logger
|
42
|
+
|
43
|
+
# @return [String | nil] A string message to provide additional context to the errors.
|
44
|
+
attr_reader :message
|
45
|
+
|
46
|
+
def initialize instance, tags, exceptions
|
47
|
+
super()
|
48
|
+
@tags = tags
|
49
|
+
@timestamp = Time.now.iso8601
|
50
|
+
@instance = instance
|
51
|
+
@occurrences = 1
|
52
|
+
@exceptions = exceptions
|
53
|
+
validate VALIDATIONS
|
54
|
+
end
|
55
|
+
|
56
|
+
# Optional parameters will be set separately from the required
|
57
|
+
#
|
58
|
+
# @param logger[String]
|
59
|
+
def logger= logger
|
60
|
+
validate_field VALIDATIONS[:logger], 'logger'
|
61
|
+
@logger = logger
|
62
|
+
end
|
63
|
+
|
64
|
+
# Optional parameters will be set separately from the required
|
65
|
+
#
|
66
|
+
# @param message[String]
|
67
|
+
def message= message
|
68
|
+
validate_field VALIDATIONS[:message], 'message'
|
69
|
+
@message = message
|
70
|
+
end
|
71
|
+
|
72
|
+
# Optional parameters will be set separately from the required
|
73
|
+
# This method is different and is regarding the way we proceed
|
74
|
+
# with incrementing occurrences
|
75
|
+
# If we keep track of them in different places and we store that value
|
76
|
+
# in separated variable - we may directly re-assign occurrences=
|
77
|
+
# But if we are not doing that - we may on same message generated
|
78
|
+
# to increment occurrences from here
|
79
|
+
def increment_occurrences
|
80
|
+
@occurrences += 1
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_controlled_hash
|
84
|
+
super()
|
85
|
+
{
|
86
|
+
timestamp: timestamp,
|
87
|
+
instance: instance,
|
88
|
+
occurrences: occurrences,
|
89
|
+
tags: tags,
|
90
|
+
exceptions: exceptions.map(&:to_controlled_hash),
|
91
|
+
logger: logger,
|
92
|
+
message: message
|
93
|
+
}.compact
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -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,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)
|
@@ -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?
|
@@ -41,7 +41,7 @@ module Contrast
|
|
41
41
|
def report_any_command_execution?
|
42
42
|
if @_report_any_command_execution.nil?
|
43
43
|
ctrl = rule_config[Contrast::Agent::Protect::Rule::CmdInjection::NAME]
|
44
|
-
@_report_any_command_execution = true?(ctrl.disable_system_commands)
|
44
|
+
@_report_any_command_execution = ctrl && true?(ctrl.disable_system_commands)
|
45
45
|
end
|
46
46
|
@_report_any_command_execution
|
47
47
|
end
|
@@ -50,7 +50,7 @@ module Contrast
|
|
50
50
|
if @_report_custom_code_sysfile_access.nil?
|
51
51
|
name_changed = Contrast::Agent::Protect::Rule::PathTraversal::NAME.tr('-', '_')
|
52
52
|
ctrl = rule_config[name_changed]
|
53
|
-
@_report_custom_code_sysfile_access = true?(ctrl.detect_custom_code_accessing_system_files)
|
53
|
+
@_report_custom_code_sysfile_access = ctrl && true?(ctrl.detect_custom_code_accessing_system_files)
|
54
54
|
end
|
55
55
|
@_report_custom_code_sysfile_access
|
56
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
|
|