contrast-agent 6.7.0 → 6.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/.simplecov +0 -1
- data/Rakefile +0 -1
- data/ext/cs__assess_array/cs__assess_array.c +41 -10
- data/ext/cs__assess_array/cs__assess_array.h +4 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +2 -2
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -1
- data/lib/contrast/agent/excluder.rb +52 -34
- data/lib/contrast/agent/exclusion_matcher.rb +21 -9
- data/lib/contrast/agent/middleware.rb +4 -4
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -0
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +146 -127
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +20 -0
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
- data/lib/contrast/agent/protect/rule/base.rb +45 -53
- data/lib/contrast/agent/protect/rule/base_service.rb +48 -24
- data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +98 -0
- data/lib/contrast/agent/protect/rule/bot_blocker.rb +81 -0
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -1
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +8 -5
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +22 -22
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +69 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +68 -0
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +2 -58
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +3 -14
- data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +2 -2
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +0 -11
- data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +29 -34
- data/lib/contrast/agent/protect/rule/no_sqli.rb +25 -18
- data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_input_classification.rb +61 -0
- data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +114 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +38 -12
- data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +33 -15
- data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +0 -14
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -62
- data/lib/contrast/agent/protect/rule/sqli.rb +70 -0
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +39 -63
- data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +6 -33
- data/lib/contrast/agent/protect/rule/xss/reflected_xss_input_classification.rb +58 -0
- data/lib/contrast/agent/protect/rule/xss.rb +14 -20
- data/lib/contrast/agent/protect/rule/xxe.rb +4 -24
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +18 -39
- data/lib/contrast/agent/reporting/attack_result/response_type.rb +9 -9
- data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +10 -2
- data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +8 -2
- data/lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb +27 -0
- data/lib/contrast/agent/reporting/input_analysis/details/protect_rule_details.rb +15 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +1 -2
- data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +16 -2
- data/lib/contrast/agent/reporting/masker/masker.rb +2 -0
- data/lib/contrast/agent/reporting/reporter.rb +1 -14
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +15 -12
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +3 -3
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +1 -2
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +0 -2
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +4 -4
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +0 -5
- data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +1 -11
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_utilities/response.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +0 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -0
- data/lib/contrast/agent/reporting/settings/code_exclusion.rb +6 -1
- data/lib/contrast/agent/reporting/settings/exclusion_base.rb +18 -0
- data/lib/contrast/agent/reporting/settings/exclusions.rb +2 -1
- data/lib/contrast/agent/reporting/settings/input_exclusion.rb +9 -3
- data/lib/contrast/agent/reporting/settings/protect.rb +15 -15
- data/lib/contrast/agent/request.rb +2 -14
- data/lib/contrast/agent/request_context.rb +6 -9
- data/lib/contrast/agent/request_context_extend.rb +9 -148
- data/lib/contrast/agent/thread_watcher.rb +3 -18
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +0 -11
- data/lib/contrast/agent_lib/api/command_injection.rb +46 -0
- data/lib/contrast/agent_lib/api/init.rb +101 -0
- data/lib/contrast/agent_lib/api/input_tracing.rb +267 -0
- data/lib/contrast/agent_lib/api/method_tempering.rb +29 -0
- data/lib/contrast/agent_lib/api/panic.rb +87 -0
- data/lib/contrast/agent_lib/api/path_semantic_file_security_bypass.rb +40 -0
- data/lib/contrast/agent_lib/interface.rb +260 -0
- data/lib/contrast/agent_lib/interface_base.rb +118 -0
- data/lib/contrast/agent_lib/return_types/eval_result.rb +44 -0
- data/lib/contrast/agent_lib/test.rb +29 -0
- data/lib/contrast/api/communication/connection_status.rb +5 -5
- data/lib/contrast/components/agent.rb +0 -14
- data/lib/contrast/components/app_context.rb +0 -2
- data/lib/contrast/components/app_context_extend.rb +0 -25
- data/lib/contrast/components/config.rb +1 -18
- data/lib/contrast/components/protect.rb +4 -1
- data/lib/contrast/components/ruby_component.rb +1 -1
- data/lib/contrast/components/settings.rb +37 -89
- data/lib/contrast/config/protect_rule_configuration.rb +7 -7
- data/lib/contrast/config/protect_rules_configuration.rb +20 -58
- data/lib/contrast/configuration.rb +1 -10
- data/lib/contrast/extension/assess/array.rb +9 -0
- data/lib/contrast/extension/delegator.rb +2 -0
- data/lib/contrast/framework/manager.rb +3 -1
- data/lib/contrast/framework/rails/railtie.rb +0 -1
- data/lib/contrast/framework/rails/support.rb +0 -1
- data/lib/contrast/tasks/config.rb +1 -8
- data/lib/contrast/utils/duck_utils.rb +1 -0
- data/lib/contrast/utils/input_classification_base.rb +156 -0
- data/lib/contrast/utils/os.rb +0 -20
- data/lib/contrast/utils/response_utils.rb +0 -16
- data/lib/contrast/utils/stack_trace_utils.rb +3 -15
- data/lib/contrast/utils/string_utils.rb +10 -7
- data/lib/contrast.rb +2 -3
- data/resources/protect/policy.json +1 -2
- data/ruby-agent.gemspec +2 -5
- metadata +42 -112
- data/exe/contrast_service +0 -23
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +0 -64
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +0 -118
- data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +0 -45
- data/lib/contrast/agent/reaction_processor.rb +0 -47
- data/lib/contrast/agent/service_heartbeat.rb +0 -35
- data/lib/contrast/api/communication/messaging_queue.rb +0 -128
- data/lib/contrast/api/communication/response_processor.rb +0 -90
- data/lib/contrast/api/communication/service_lifecycle.rb +0 -77
- data/lib/contrast/api/communication/socket.rb +0 -44
- data/lib/contrast/api/communication/socket_client.rb +0 -130
- data/lib/contrast/api/communication/speedracer.rb +0 -138
- data/lib/contrast/api/communication/tcp_socket.rb +0 -32
- data/lib/contrast/api/communication/unix_socket.rb +0 -28
- data/lib/contrast/api/communication.rb +0 -20
- data/lib/contrast/api/decorators/address.rb +0 -59
- data/lib/contrast/api/decorators/agent_startup.rb +0 -56
- data/lib/contrast/api/decorators/application_settings.rb +0 -43
- data/lib/contrast/api/decorators/application_startup.rb +0 -56
- data/lib/contrast/api/decorators/bot_blocker.rb +0 -37
- data/lib/contrast/api/decorators/http_request.rb +0 -137
- data/lib/contrast/api/decorators/input_analysis.rb +0 -18
- data/lib/contrast/api/decorators/instrumentation_mode.rb +0 -35
- data/lib/contrast/api/decorators/ip_denylist.rb +0 -37
- data/lib/contrast/api/decorators/message.rb +0 -67
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -52
- data/lib/contrast/api/decorators/response_type.rb +0 -17
- data/lib/contrast/api/decorators/server_features.rb +0 -25
- data/lib/contrast/api/decorators/user_input.rb +0 -51
- data/lib/contrast/api/decorators/virtual_patch.rb +0 -34
- data/lib/contrast/api/decorators.rb +0 -22
- data/lib/contrast/api/dtm.pb.rb +0 -363
- data/lib/contrast/api/settings.pb.rb +0 -500
- data/lib/contrast/api.rb +0 -16
- data/lib/contrast/components/contrast_service.rb +0 -88
- data/lib/contrast/components/service.rb +0 -55
- data/lib/contrast/tasks/service.rb +0 -84
- data/lib/contrast/utils/input_classification.rb +0 -73
- data/lib/protobuf/code_generator.rb +0 -129
- data/lib/protobuf/decoder.rb +0 -28
- data/lib/protobuf/deprecation.rb +0 -117
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +0 -79
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +0 -360
- data/lib/protobuf/descriptors.rb +0 -3
- data/lib/protobuf/encoder.rb +0 -11
- data/lib/protobuf/enum.rb +0 -365
- data/lib/protobuf/exceptions.rb +0 -9
- data/lib/protobuf/field/base_field.rb +0 -380
- data/lib/protobuf/field/base_field_object_definitions.rb +0 -504
- data/lib/protobuf/field/bool_field.rb +0 -64
- data/lib/protobuf/field/bytes_field.rb +0 -67
- data/lib/protobuf/field/double_field.rb +0 -25
- data/lib/protobuf/field/enum_field.rb +0 -56
- data/lib/protobuf/field/field_array.rb +0 -102
- data/lib/protobuf/field/field_hash.rb +0 -122
- data/lib/protobuf/field/fixed32_field.rb +0 -25
- data/lib/protobuf/field/fixed64_field.rb +0 -28
- data/lib/protobuf/field/float_field.rb +0 -43
- data/lib/protobuf/field/int32_field.rb +0 -21
- data/lib/protobuf/field/int64_field.rb +0 -34
- data/lib/protobuf/field/integer_field.rb +0 -23
- data/lib/protobuf/field/message_field.rb +0 -51
- data/lib/protobuf/field/sfixed32_field.rb +0 -27
- data/lib/protobuf/field/sfixed64_field.rb +0 -28
- data/lib/protobuf/field/signed_integer_field.rb +0 -29
- data/lib/protobuf/field/sint32_field.rb +0 -21
- data/lib/protobuf/field/sint64_field.rb +0 -21
- data/lib/protobuf/field/string_field.rb +0 -51
- data/lib/protobuf/field/uint32_field.rb +0 -21
- data/lib/protobuf/field/uint64_field.rb +0 -21
- data/lib/protobuf/field/varint_field.rb +0 -77
- data/lib/protobuf/field.rb +0 -74
- data/lib/protobuf/generators/base.rb +0 -85
- data/lib/protobuf/generators/enum_generator.rb +0 -39
- data/lib/protobuf/generators/extension_generator.rb +0 -27
- data/lib/protobuf/generators/field_generator.rb +0 -193
- data/lib/protobuf/generators/file_generator.rb +0 -262
- data/lib/protobuf/generators/group_generator.rb +0 -122
- data/lib/protobuf/generators/message_generator.rb +0 -104
- data/lib/protobuf/generators/option_generator.rb +0 -17
- data/lib/protobuf/generators/printable.rb +0 -160
- data/lib/protobuf/generators/service_generator.rb +0 -50
- data/lib/protobuf/lifecycle.rb +0 -33
- data/lib/protobuf/logging.rb +0 -39
- data/lib/protobuf/message/fields.rb +0 -233
- data/lib/protobuf/message/serialization.rb +0 -85
- data/lib/protobuf/message.rb +0 -241
- data/lib/protobuf/optionable.rb +0 -72
- data/lib/protobuf/tasks/compile.rake +0 -80
- data/lib/protobuf/tasks.rb +0 -1
- data/lib/protobuf/varint.rb +0 -20
- data/lib/protobuf/varint_pure.rb +0 -31
- data/lib/protobuf/version.rb +0 -3
- data/lib/protobuf/wire_type.rb +0 -10
- data/lib/protobuf.rb +0 -91
- data/proto/dynamic_discovery.proto +0 -46
- data/proto/google/protobuf/compiler/plugin.proto +0 -183
- data/proto/google/protobuf/descriptor.proto +0 -911
- data/proto/rpc.proto +0 -71
- data/service_executables/.gitkeep +0 -0
- data/service_executables/VERSION +0 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
@@ -6,6 +6,7 @@ require 'contrast/utils/timer'
|
|
6
6
|
require 'contrast/agent/reporting/attack_result/user_input'
|
7
7
|
require 'contrast/agent/reporting/input_analysis/input_type'
|
8
8
|
require 'contrast/agent/reporting/details/protect_rule_details'
|
9
|
+
require 'contrast/agent/reporting/reporting_events/application_defend_attack_sample_stack'
|
9
10
|
|
10
11
|
module Contrast
|
11
12
|
module Agent
|
@@ -19,15 +20,11 @@ module Contrast
|
|
19
20
|
#
|
20
21
|
# @return [Contrast::Agent::Reporting::Details::ProtectRuleDetails, nil]
|
21
22
|
attr_accessor :details
|
22
|
-
# @return [Contrast::Agent::Reporting::Details::IpDenylistDetails, nil]
|
23
|
-
attr_accessor :ip_denylist
|
24
|
-
# @return [Contrast::Agent::Reporting::Details::VirtualPatchDetails, nil]
|
25
|
-
attr_accessor :virtual_patch
|
26
23
|
|
27
24
|
class << self
|
28
25
|
# @param context [Contrast::Agent::RequestContext]
|
29
|
-
# @param ia_result [Contrast::
|
30
|
-
# determined to be an attack
|
26
|
+
# @param ia_result [Contrast::Agent::Reporting::Settings::InputAnalysisResult] the analysis of the input that
|
27
|
+
# was determined to be an attack
|
31
28
|
# @return [Contrast::Agent::Reporting::RaspRuleSample]
|
32
29
|
def build context, ia_result
|
33
30
|
sample = new
|
@@ -39,43 +36,19 @@ module Contrast
|
|
39
36
|
sample
|
40
37
|
end
|
41
38
|
|
42
|
-
# @param ia_result [Contrast::
|
43
|
-
# determined to be an attack
|
39
|
+
# @param ia_result [Contrast::Agent::Reporting::Settings::InputAnalysisResult] the analysis of the input that
|
40
|
+
# was determined to be an attack
|
44
41
|
def build_user_input_from_ia ia_result
|
45
|
-
# TODO: RUBY-99999 remove once only using Agent IA
|
46
|
-
result = if ia_result.cs__is_a?(Contrast::Api::Settings::InputAnalysisResult)
|
47
|
-
transform_ia_result(ia_result)
|
48
|
-
else
|
49
|
-
# Use Agent ia_result
|
50
|
-
ia_result
|
51
|
-
end
|
52
42
|
user_input = Contrast::Agent::Reporting::UserInput.new
|
53
|
-
return user_input unless
|
43
|
+
return user_input unless ia_result
|
54
44
|
|
55
|
-
user_input.input_type =
|
56
|
-
user_input.matcher_ids =
|
57
|
-
user_input.path =
|
58
|
-
user_input.key =
|
59
|
-
user_input.value =
|
45
|
+
user_input.input_type = ia_result.input_type
|
46
|
+
user_input.matcher_ids = ia_result.ids
|
47
|
+
user_input.path = ia_result.path
|
48
|
+
user_input.key = ia_result.key if ia_result.key
|
49
|
+
user_input.value = ia_result.value if ia_result.value
|
60
50
|
user_input
|
61
51
|
end
|
62
|
-
|
63
|
-
# @param [Contrast::Api::Settings::InputAnalysisResult]
|
64
|
-
# @return [Contrast::Agent::Reporting::InputAnalysisResult]
|
65
|
-
def transform_ia_result dtm_ia_result
|
66
|
-
ia_result = Contrast::Agent::Reporting::InputAnalysisResult.new
|
67
|
-
ia_result.input_type = Contrast::Agent::Reporting::InputType.to_a.find do |value|
|
68
|
-
value == dtm_ia_result.input_type.name # rubocop:disable Security/Module/Name
|
69
|
-
end
|
70
|
-
ia_result.score_level = dtm_ia_result.score_level.name # rubocop:disable Security/Module/Name
|
71
|
-
ia_result.value = dtm_ia_result.value
|
72
|
-
ia_result.key = dtm_ia_result.key
|
73
|
-
ia_result.path = dtm_ia_result.path
|
74
|
-
ia_result.rule_id = dtm_ia_result.rule_id
|
75
|
-
ia_result.attack_count = dtm_ia_result.attack_count
|
76
|
-
ia_result.ids = dtm_ia_result.ids
|
77
|
-
ia_result
|
78
|
-
end
|
79
52
|
end
|
80
53
|
|
81
54
|
def time_stamp
|
@@ -94,11 +67,17 @@ module Contrast
|
|
94
67
|
@_user_input = input if input.is_a?(Contrast::Agent::Reporting::UserInput)
|
95
68
|
end
|
96
69
|
|
70
|
+
# @return [Array<Contrast::Agent::Reporting::ApplicationDefendAttackSampleStack>,Array]
|
71
|
+
def stack
|
72
|
+
@_stack ||= []
|
73
|
+
end
|
74
|
+
|
97
75
|
def to_controlled_hash
|
98
76
|
{
|
99
77
|
timeStamp: Time.at(time_stamp).iso8601,
|
100
78
|
userInput: user_input.to_controlled_hash,
|
101
|
-
details: details&.to_controlled_hash
|
79
|
+
details: details&.to_controlled_hash,
|
80
|
+
stack: stack.map(&:to_controlled_hash)
|
102
81
|
}
|
103
82
|
end
|
104
83
|
end
|
@@ -9,18 +9,18 @@ module Contrast
|
|
9
9
|
# This module will hold the response types used to generate
|
10
10
|
# attack result.
|
11
11
|
module ResponseType
|
12
|
-
BLOCKED
|
13
|
-
MONITORED
|
14
|
-
PROBED
|
15
|
-
|
16
|
-
SUSPICIOUS
|
17
|
-
AGGREGATED
|
18
|
-
EXPLOITED
|
19
|
-
NO_ACTION
|
12
|
+
BLOCKED = :BLOCKED.cs__freeze
|
13
|
+
MONITORED = :MONITORED.cs__freeze
|
14
|
+
PROBED = :PROBED.cs__freeze
|
15
|
+
BLOCKED_AT_PERIMETER = :BLOCKED_AT_PERIMETER.cs__freeze
|
16
|
+
SUSPICIOUS = :SUSPICIOUS.cs__freeze
|
17
|
+
AGGREGATED = :AGGREGATED.cs__freeze
|
18
|
+
EXPLOITED = :EXPLOITED.cs__freeze
|
19
|
+
NO_ACTION = :NO_ACTION.cs__freeze
|
20
20
|
|
21
21
|
class << self
|
22
22
|
def to_a
|
23
|
-
[NO_ACTION, BLOCKED, MONITORED, PROBED,
|
23
|
+
[NO_ACTION, BLOCKED, MONITORED, PROBED, BLOCKED_AT_PERIMETER, EXPLOITED, SUSPICIOUS, AGGREGATED]
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -10,9 +10,17 @@ module Contrast
|
|
10
10
|
# Bot blocker IA result details info.
|
11
11
|
class IpDenylistDetails < ProtectRuleDetails
|
12
12
|
# @return [String]
|
13
|
-
|
13
|
+
attr_reader :ip
|
14
14
|
# @return [String]
|
15
|
-
|
15
|
+
attr_reader :uuid
|
16
|
+
|
17
|
+
# @param ip [String] the IP address that was blocked
|
18
|
+
# @param uuid [String] the UUID to identify the block rule in TeamServer
|
19
|
+
def initialize ip, uuid
|
20
|
+
@ip = ip
|
21
|
+
@uuid = uuid
|
22
|
+
super()
|
23
|
+
end
|
16
24
|
|
17
25
|
def to_controlled_hash
|
18
26
|
{
|
@@ -7,10 +7,16 @@ module Contrast
|
|
7
7
|
module Agent
|
8
8
|
module Reporting
|
9
9
|
module Details
|
10
|
-
#
|
10
|
+
# Virtual Patch IA result details info.
|
11
11
|
class VirtualPatchDetails < ProtectRuleDetails
|
12
12
|
# @return [String]
|
13
|
-
|
13
|
+
attr_reader :uuid
|
14
|
+
|
15
|
+
# @param uuid [String] the UUID to identify the block rule in TeamServer
|
16
|
+
def initialize uuid
|
17
|
+
@uuid = uuid
|
18
|
+
super()
|
19
|
+
end
|
14
20
|
|
15
21
|
def to_controlled_hash
|
16
22
|
{
|
@@ -0,0 +1,27 @@
|
|
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/agent/reporting/input_analysis/details/protect_rule_details'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
module Reporting
|
9
|
+
# Bot blocker IA result details info.
|
10
|
+
class BotBlockerDetails < ProtectRuleDetails
|
11
|
+
# @return [String]
|
12
|
+
attr_accessor :bot
|
13
|
+
# User agent header value
|
14
|
+
#
|
15
|
+
# @return [String]
|
16
|
+
attr_accessor :user_agent
|
17
|
+
|
18
|
+
def to_controlled_hash
|
19
|
+
{
|
20
|
+
bot: bot,
|
21
|
+
userAgent: user_agent
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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
|
+
module Contrast
|
5
|
+
module Agent
|
6
|
+
module Reporting
|
7
|
+
# This class is holding additional info which is rule specific and this is
|
8
|
+
# the base class for type check made easy.
|
9
|
+
class ProtectRuleDetails
|
10
|
+
# Extend per each rule.
|
11
|
+
def to_controlled_hash; end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -7,8 +7,7 @@ require 'contrast/agent/reporting/input_analysis/input_analysis_result'
|
|
7
7
|
module Contrast
|
8
8
|
module Agent
|
9
9
|
module Reporting
|
10
|
-
# This class will do ia analysis for our protect rules
|
11
|
-
# using the service.
|
10
|
+
# This class will do ia analysis for our protect rules
|
12
11
|
class InputAnalysis
|
13
12
|
# result from input analysis
|
14
13
|
#
|
@@ -4,12 +4,12 @@
|
|
4
4
|
require 'contrast/utils/object_share'
|
5
5
|
require 'contrast/agent/reporting/input_analysis/input_type'
|
6
6
|
require 'contrast/agent/reporting/input_analysis/score_level'
|
7
|
+
require 'contrast/agent/reporting/input_analysis/details/protect_rule_details'
|
7
8
|
|
8
9
|
module Contrast
|
9
10
|
module Agent
|
10
11
|
module Reporting
|
11
|
-
# This class will do ia analysis for our protect rules
|
12
|
-
# using the service.
|
12
|
+
# This class will do ia analysis for our protect rules
|
13
13
|
class InputAnalysisResult
|
14
14
|
INPUT_TYPE = Contrast::Agent::Reporting::InputType
|
15
15
|
SCORE_LEVEL = Contrast::Agent::Reporting::ScoreLevel
|
@@ -109,6 +109,20 @@ module Contrast
|
|
109
109
|
def score_level= score_level
|
110
110
|
@_score_level = score_level if SCORE_LEVEL.to_a.include?(score_level)
|
111
111
|
end
|
112
|
+
|
113
|
+
# Additional per rule details containing more specific info.
|
114
|
+
#
|
115
|
+
# @param protect_rule_details [Contrast::Agent::Reporting::ProtectRuleDetails]
|
116
|
+
def details= protect_rule_details
|
117
|
+
@_details = protect_rule_details if protect_rule_details.is_a?(Contrast::Agent::Reporting::ProtectRuleDetails)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Additional per rule details containing more specific info.
|
121
|
+
#
|
122
|
+
# @return [Contrast::Agent::Reporting::ProtectRuleDetails, nil]
|
123
|
+
def details
|
124
|
+
@_details
|
125
|
+
end
|
112
126
|
end
|
113
127
|
end
|
114
128
|
end
|
@@ -35,6 +35,8 @@ module Contrast
|
|
35
35
|
return unless activity
|
36
36
|
|
37
37
|
logger.debug('Masker: masking sensitive data', activity: activity.__id__, request: activity.request&.__id__)
|
38
|
+
return if activity.request.nil?
|
39
|
+
|
38
40
|
mask_body(activity)
|
39
41
|
mask_query_string(activity)
|
40
42
|
mask_request_params(activity)
|
@@ -18,7 +18,7 @@ module Contrast
|
|
18
18
|
#
|
19
19
|
# @return[Boolean] true if bypass is enabled, or false if bypass disabled
|
20
20
|
def enabled?
|
21
|
-
@_enabled = Contrast::
|
21
|
+
@_enabled = ::Contrast::AGENT.enabled? if @_enabled.nil?
|
22
22
|
@_enabled
|
23
23
|
end
|
24
24
|
end
|
@@ -39,7 +39,6 @@ module Contrast
|
|
39
39
|
logger.debug('Starting background Reporter thread.')
|
40
40
|
loop do
|
41
41
|
next unless connected?
|
42
|
-
next unless app_create_complete?
|
43
42
|
|
44
43
|
process_event(queue.pop)
|
45
44
|
rescue StandardError => e
|
@@ -120,18 +119,6 @@ module Contrast
|
|
120
119
|
false
|
121
120
|
end
|
122
121
|
|
123
|
-
# Unless we're in bypass mode, we need to make sure the service has started and built the application on
|
124
|
-
# TeamServer since we're doing a split style here.
|
125
|
-
#
|
126
|
-
# @return [Boolean]
|
127
|
-
def app_create_complete?
|
128
|
-
return true if Contrast::APP_CONTEXT.session_id
|
129
|
-
|
130
|
-
logger.debug('Service startup incomplete; Application may not be created; sleeping')
|
131
|
-
sleep(5)
|
132
|
-
false
|
133
|
-
end
|
134
|
-
|
135
122
|
# @param event [Contrast::Agent::Reporting::ReportingEvent]
|
136
123
|
def process_event event
|
137
124
|
client.send_event(event, connection)
|
@@ -71,18 +71,21 @@ module Contrast
|
|
71
71
|
def attack_results_for rule_id, response_type = nil
|
72
72
|
results = []
|
73
73
|
defend.attackers.each do |attacker|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
74
|
+
next unless attacker.protection_rules[rule_id]
|
75
|
+
|
76
|
+
result = case response_type
|
77
|
+
when BLOCKED, BLOCKED_AT_PERIMETER
|
78
|
+
attacker.protection_rules[rule_id].blocked
|
79
|
+
when EXPLOITED
|
80
|
+
attacker.protection_rules[rule_id].exploited
|
81
|
+
when PROBED
|
82
|
+
attacker.protection_rules[rule_id].ineffective
|
83
|
+
when SUSPICIOUS
|
84
|
+
attacker.protection_rules[rule_id].suspicious
|
85
|
+
else
|
86
|
+
attacker.protection_rules[rule_id]
|
87
|
+
end
|
88
|
+
results << result if result
|
86
89
|
end
|
87
90
|
results
|
88
91
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'contrast/api/dtm.pb'
|
5
|
-
require 'contrast/api/decorators/response_type'
|
6
4
|
require 'contrast/components/logger'
|
7
5
|
require 'contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity'
|
8
6
|
|
@@ -45,7 +43,9 @@ module Contrast
|
|
45
43
|
attack_sample_activity.attach_data(attack_result)
|
46
44
|
@response_type = attack_result.response
|
47
45
|
case response_type
|
48
|
-
when ::Contrast::Agent::Reporting::ResponseType::BLOCKED
|
46
|
+
when ::Contrast::Agent::Reporting::ResponseType::BLOCKED,
|
47
|
+
::Contrast::Agent::Reporting::ResponseType::BLOCKED_AT_PERIMETER
|
48
|
+
|
49
49
|
@blocked = attack_sample_activity
|
50
50
|
when ::Contrast::Agent::Reporting::ResponseType::MONITORED
|
51
51
|
@exploited = attack_sample_activity
|
@@ -5,7 +5,6 @@ require 'contrast/agent/protect/rule/cmd_injection'
|
|
5
5
|
require 'contrast/agent/protect/rule/deserialization'
|
6
6
|
require 'contrast/agent/protect/rule/http_method_tampering'
|
7
7
|
require 'contrast/agent/protect/rule/no_sqli'
|
8
|
-
require 'contrast/api/dtm.pb'
|
9
8
|
require 'contrast/agent/reporting/attack_result/user_input'
|
10
9
|
require 'contrast/agent/reporting/attack_result/response_type'
|
11
10
|
require 'contrast/components/logger'
|
@@ -60,7 +59,7 @@ module Contrast
|
|
60
59
|
}
|
61
60
|
end
|
62
61
|
|
63
|
-
# @param response_type [Contrast::
|
62
|
+
# @param response_type [Contrast::Agent::Reporting::ResponseType]
|
64
63
|
# @return [Boolean] check if response type is blocked
|
65
64
|
def blocked? response_type
|
66
65
|
@blocked = response_type == Contrast::Agent::Reporting::ResponseType::BLOCKED
|
@@ -6,9 +6,7 @@ require 'contrast/agent/reporting/reporting_events/application_reporting_event'
|
|
6
6
|
require 'contrast/agent/reporting/reporting_events/library_discovery'
|
7
7
|
require 'contrast/agent/reporting/reporting_events/reporting_event'
|
8
8
|
require 'contrast/agent/reporting/reporting_events/route_discovery'
|
9
|
-
require 'contrast/api/dtm.pb'
|
10
9
|
require 'contrast/components/logger'
|
11
|
-
require 'json'
|
12
10
|
|
13
11
|
module Contrast
|
14
12
|
module Agent
|
@@ -162,7 +162,7 @@ module Contrast
|
|
162
162
|
# Rules which are event based must have an event to be sent to TeamServer. They include the Trigger, Regexp,
|
163
163
|
# and Data flow type Rules, meaning all those which are not Properties based. Eventually, we may have
|
164
164
|
# validation for each of those types; however, that's a refactor for after we've translated all rules from the
|
165
|
-
#
|
165
|
+
# TeamServer and have had time to build proper child structure.
|
166
166
|
#
|
167
167
|
# @return [Boolean]
|
168
168
|
def event_based?
|
@@ -171,7 +171,7 @@ module Contrast
|
|
171
171
|
|
172
172
|
# Rules which are property based must have a property to be sent to TeamServer. Eventually, each rule may own
|
173
173
|
# its own validation, as the properties each needs are different; however, that's a refactor for after we've
|
174
|
-
# translated all rules from
|
174
|
+
# translated all rules from TeamServer and have had time to build proper child structure.
|
175
175
|
#
|
176
176
|
# @return [Boolean]
|
177
177
|
def property_based?
|
@@ -180,7 +180,7 @@ module Contrast
|
|
180
180
|
|
181
181
|
# Rules which are config based must have a configuration to be sent to TeamServer. Eventually, each rule may own
|
182
182
|
# its own validation, as the properties each needs are different; however, that's a refactor for after we've
|
183
|
-
# translated all rules from
|
183
|
+
# translated all rules from TeamServer and have had time to build proper child structure.
|
184
184
|
#
|
185
185
|
# @return [Boolean]
|
186
186
|
def config_based?
|
@@ -189,7 +189,7 @@ module Contrast
|
|
189
189
|
|
190
190
|
# Rules which are hardcode based send properties to TeamServer. Eventually, each rule may own its own
|
191
191
|
# validation, as the properties each needs are different; however, that's a refactor for after we've
|
192
|
-
# translated all rules from
|
192
|
+
# translated all rules from TeamServer and have had time to build proper child structure.
|
193
193
|
#
|
194
194
|
# @return [Boolean]
|
195
195
|
def hardcoded?
|
@@ -39,9 +39,6 @@ module Contrast
|
|
39
39
|
attr_accessor :body_binary
|
40
40
|
# @return [Hash]
|
41
41
|
attr_reader :cookies
|
42
|
-
# REMOVE_DTM_REQUEST
|
43
|
-
# @return [Contrast::Api::Dtm::HttpRequest]
|
44
|
-
attr_reader :dtm
|
45
42
|
|
46
43
|
class << self
|
47
44
|
# @param request [Contrast::Agent::Request]
|
@@ -60,8 +57,6 @@ module Contrast
|
|
60
57
|
#
|
61
58
|
# @param request [Contrast::Agent::Request]
|
62
59
|
def attach_data request
|
63
|
-
# REMOVE_DTM_REQUEST
|
64
|
-
@dtm = request.dtm
|
65
60
|
@body = request.body
|
66
61
|
@headers = {}
|
67
62
|
extract_headers(request)
|
@@ -6,7 +6,7 @@ require 'contrast/agent/reporting/reporting_events/application_reporting_event'
|
|
6
6
|
module Contrast
|
7
7
|
module Agent
|
8
8
|
module Reporting
|
9
|
-
# This is the new Poll class for the Heartbeat
|
9
|
+
# This is the new Poll class for the Heartbeat to TeamServer.
|
10
10
|
class Poll < Contrast::Agent::Reporting::ApplicationReportingEvent
|
11
11
|
def initialize
|
12
12
|
@event_type = :heartbeat
|
@@ -17,16 +17,6 @@ module Contrast
|
|
17
17
|
def file_name
|
18
18
|
'applications-heartbeat'
|
19
19
|
end
|
20
|
-
|
21
|
-
# This is commented out as I am not aware if we're supposed to send some information and/or parse it to hash
|
22
|
-
# In https://github.com/Contrast-Security-Inc/contrast-service/blob/next/reporting/tsreporter.go
|
23
|
-
#
|
24
|
-
# Convert the instance variables on the class, and other information, into the identifiers required for
|
25
|
-
# TeamServer to process the JSON form of this message.
|
26
|
-
#
|
27
|
-
# @return [Hash]
|
28
|
-
# @raise [ArgumentError]
|
29
|
-
# def to_controlled_hash; end
|
30
20
|
end
|
31
21
|
end
|
32
22
|
end
|
@@ -19,8 +19,8 @@ module Contrast
|
|
19
19
|
generate_paths if enabled?
|
20
20
|
end
|
21
21
|
|
22
|
-
# This method will be handling the auditing of the requests and responses we send to
|
23
|
-
# feature is enabled, we'll log to file the request and/or response
|
22
|
+
# This method will be handling the auditing of the requests and responses we send to TeamServer. If the audit
|
23
|
+
# feature is enabled, we'll log to file the request and/or response JSON objects.
|
24
24
|
#
|
25
25
|
# @param event [Contrast::Agent::Reporting::ReportingEvent] One of the DTMs valid for the
|
26
26
|
# event field of Contrast::Agent::Reporting::ReportingEvent
|
@@ -19,7 +19,7 @@ module Contrast
|
|
19
19
|
|
20
20
|
# All of the feature server_features
|
21
21
|
#
|
22
|
-
# @return [Contrast::Agent::Reporting::Settings::
|
22
|
+
# @return [Contrast::Agent::Reporting::Settings::ServerFeatures, nil]
|
23
23
|
attr_accessor :server_features
|
24
24
|
|
25
25
|
# Success boolean message value
|
@@ -1,12 +1,9 @@
|
|
1
1
|
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'contrast/api/communication/response_processor'
|
5
|
-
require 'contrast/api/decorators/application_settings'
|
6
4
|
require 'contrast/agent/reporting/reporting_utilities/response'
|
7
5
|
require 'contrast/agent/reporting/reporting_utilities/response_handler_utils'
|
8
6
|
require 'contrast/agent/reporting/reporting_utilities/response_handler_mode'
|
9
|
-
require 'contrast/api/decorators/server_features'
|
10
7
|
require 'contrast/components/logger'
|
11
8
|
require 'json'
|
12
9
|
|
@@ -12,9 +12,14 @@ module Contrast
|
|
12
12
|
ATTRIBUTES = BASE_ATTRIBUTES.dup << :denylist
|
13
13
|
ATTRIBUTES.cs__freeze
|
14
14
|
|
15
|
-
# @return
|
15
|
+
# @return [Array<String>]
|
16
16
|
attr_accessor :denylist
|
17
17
|
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
@denylist = []
|
21
|
+
end
|
22
|
+
|
18
23
|
def to_controlled_hash
|
19
24
|
hash = super
|
20
25
|
hash[:denylist] = denylist
|
@@ -18,6 +18,24 @@ module Contrast
|
|
18
18
|
# @return protect_rules [Array<String>]
|
19
19
|
attr_accessor :protect_rules
|
20
20
|
|
21
|
+
def initialize
|
22
|
+
@modes = []
|
23
|
+
@assess_rules = []
|
24
|
+
@protect_rules = []
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Boolean] does this exclusion apply to Assess or not
|
28
|
+
def assess
|
29
|
+
@_assess = modes&.include?('assess') if @_assess.nil?
|
30
|
+
@_assess
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Boolean] does this exclusion apply to Protect or not
|
34
|
+
def protect
|
35
|
+
@_protect = modes&.include?('defend') if @_protect.nil?
|
36
|
+
@_protect
|
37
|
+
end
|
38
|
+
|
21
39
|
def to_controlled_hash
|
22
40
|
{
|
23
41
|
name: name, # rubocop:disable Security/Module/Name
|
@@ -26,6 +26,7 @@ module Contrast
|
|
26
26
|
# @param new_code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
|
27
27
|
# name [String] The name of the exclusion as defined by the user in TS.
|
28
28
|
# modes [String] If this exclusion applies to assess or protect. [assess, defend]
|
29
|
+
# protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
|
29
30
|
# assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
|
30
31
|
# denylist [String] The call, if in the stack, should result in the agent not taking action.
|
31
32
|
# }
|
@@ -39,7 +40,7 @@ module Contrast
|
|
39
40
|
|
40
41
|
# Cases where rules should be excluded if violated from a given input.
|
41
42
|
#
|
42
|
-
# @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::
|
43
|
+
# @return input_exclusions [Array<Contrast::Agent::Reporting::Settings::InputExclusion>]
|
43
44
|
# Array of InputExclusions
|
44
45
|
def input_exclusions
|
45
46
|
@_input_exclusions ||= []
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'contrast/agent/reporting/settings/
|
4
|
+
require 'contrast/agent/reporting/settings/url_exclusion'
|
5
5
|
require 'contrast/utils/object_share'
|
6
6
|
|
7
7
|
module Contrast
|
@@ -9,11 +9,17 @@ module Contrast
|
|
9
9
|
module Reporting
|
10
10
|
module Settings
|
11
11
|
# InputExclusions class
|
12
|
-
class InputExclusion <
|
13
|
-
ATTRIBUTES =
|
12
|
+
class InputExclusion < UrlExclusion
|
13
|
+
ATTRIBUTES = UrlExclusion::ATTRIBUTES.dup << :type
|
14
14
|
ATTRIBUTES.cs__freeze
|
15
15
|
VALID_INPUT_TYPES = %w[COOKIE PARAMETER HEADER BODY QUERYSTRING].cs__freeze
|
16
16
|
|
17
|
+
# @return [String] the name of the input to match
|
18
|
+
attr_accessor :input_name
|
19
|
+
|
20
|
+
# @return [String] the type of the input to match
|
21
|
+
attr_accessor :input_type
|
22
|
+
|
17
23
|
# @return type [String] The type of the input
|
18
24
|
def type
|
19
25
|
@_type ||= Contrast::Utils::ObjectShare::EMPTY_STRING
|