contrast-agent 5.1.0 → 5.2.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_kernel/cs__assess_kernel.c +7 -4
- data/ext/cs__assess_module/cs__assess_module.c +7 -7
- data/ext/cs__common/cs__common.c +4 -0
- data/ext/cs__common/cs__common.h +1 -0
- data/ext/cs__contrast_patch/cs__contrast_patch.c +52 -27
- data/ext/cs__contrast_patch/cs__contrast_patch.h +2 -0
- data/ext/cs__scope/cs__scope.c +747 -0
- data/ext/cs__scope/cs__scope.h +88 -0
- data/ext/cs__scope/extconf.rb +5 -0
- data/lib/contrast/agent/assess/contrast_event.rb +20 -13
- data/lib/contrast/agent/assess/contrast_object.rb +4 -1
- data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -5
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +2 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -1
- data/lib/contrast/agent/assess/rule/response/{autocomplete_rule.rb → auto_complete_rule.rb} +4 -3
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +12 -79
- data/lib/contrast/agent/assess/rule/response/body_rule.rb +109 -0
- data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +157 -0
- data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +26 -0
- data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +14 -15
- data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +5 -25
- data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +29 -0
- data/lib/contrast/agent/assess/rule/response/header_rule.rb +70 -0
- data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +12 -36
- data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +2 -1
- data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +26 -0
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +36 -0
- data/lib/contrast/agent/middleware.rb +1 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +1 -3
- data/lib/contrast/agent/patching/policy/patch.rb +2 -6
- data/lib/contrast/agent/patching/policy/patcher.rb +1 -1
- data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +94 -0
- data/lib/contrast/agent/protect/rule/base.rb +28 -1
- data/lib/contrast/agent/protect/rule/base_service.rb +10 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +2 -0
- data/lib/contrast/agent/protect/rule/deserialization.rb +6 -0
- data/lib/contrast/agent/protect/rule/http_method_tampering.rb +5 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +1 -0
- data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +124 -0
- data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +121 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +33 -0
- data/lib/contrast/agent/protect/rule/xxe.rb +4 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +44 -0
- data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +115 -0
- data/lib/contrast/agent/reporting/input_analysis/input_type.rb +44 -0
- data/lib/contrast/agent/reporting/input_analysis/score_level.rb +21 -0
- data/lib/contrast/agent/reporting/report.rb +1 -0
- data/lib/contrast/agent/reporting/reporter.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +69 -36
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +88 -59
- data/lib/contrast/agent/reporting/reporting_events/{finding_object.rb → finding_event_object.rb} +24 -20
- data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +39 -0
- data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +40 -0
- data/lib/contrast/agent/reporting/reporting_events/{finding_signature.rb → finding_event_signature.rb} +29 -24
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +12 -8
- data/lib/contrast/agent/reporting/reporting_events/{finding_stack.rb → finding_event_stack.rb} +23 -19
- data/lib/contrast/agent/reporting/reporting_events/{finding_taint_range.rb → finding_event_taint_range.rb} +17 -15
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +26 -53
- data/lib/contrast/agent/reporting/reporting_events/poll.rb +29 -0
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +5 -4
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +0 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +28 -20
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +13 -1
- data/lib/contrast/agent/request_context.rb +6 -1
- data/lib/contrast/agent/request_context_extend.rb +85 -21
- data/lib/contrast/agent/scope.rb +102 -107
- data/lib/contrast/agent/service_heartbeat.rb +45 -2
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/bot_blocker.rb +37 -0
- data/lib/contrast/api/decorators/ip_denylist.rb +37 -0
- data/lib/contrast/api/decorators/rasp_rule_sample.rb +29 -0
- data/lib/contrast/api/decorators/user_input.rb +11 -1
- data/lib/contrast/api/decorators/virtual_patch.rb +34 -0
- data/lib/contrast/components/logger.rb +5 -0
- data/lib/contrast/components/protect.rb +4 -2
- data/lib/contrast/components/scope.rb +98 -91
- data/lib/contrast/config/agent_configuration.rb +58 -12
- data/lib/contrast/config/api_configuration.rb +100 -12
- data/lib/contrast/config/api_proxy_configuration.rb +55 -3
- data/lib/contrast/config/application_configuration.rb +114 -15
- data/lib/contrast/config/assess_configuration.rb +106 -12
- data/lib/contrast/config/assess_rules_configuration.rb +44 -3
- data/lib/contrast/config/base_configuration.rb +1 -0
- data/lib/contrast/config/certification_configuration.rb +74 -3
- data/lib/contrast/config/exception_configuration.rb +61 -3
- data/lib/contrast/config/heap_dump_configuration.rb +101 -17
- data/lib/contrast/config/inventory_configuration.rb +64 -3
- data/lib/contrast/config/logger_configuration.rb +46 -3
- data/lib/contrast/config/protect_rule_configuration.rb +36 -9
- data/lib/contrast/config/protect_rules_configuration.rb +120 -17
- data/lib/contrast/config/request_audit_configuration.rb +68 -3
- data/lib/contrast/config/ruby_configuration.rb +96 -22
- data/lib/contrast/config/sampling_configuration.rb +76 -10
- data/lib/contrast/config/server_configuration.rb +56 -11
- data/lib/contrast/configuration.rb +6 -3
- data/lib/contrast/logger/cef_log.rb +151 -0
- data/lib/contrast/utils/hash_digest.rb +14 -6
- data/lib/contrast/utils/log_utils.rb +114 -0
- data/lib/contrast/utils/middleware_utils.rb +6 -7
- data/lib/contrast/utils/net_http_base.rb +12 -9
- data/lib/contrast/utils/patching/policy/patch_utils.rb +0 -4
- data/lib/contrast.rb +4 -3
- data/ruby-agent.gemspec +1 -1
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +41 -21
- data/lib/contrast/agent/assess/rule/response/cachecontrol_rule.rb +0 -184
- data/lib/contrast/agent/assess/rule/response/clickjacking_rule.rb +0 -66
- data/lib/contrast/agent/assess/rule/response/x_content_type_rule.rb +0 -52
- data/lib/contrast/agent/assess/rule/response/x_xss_protection_rule.rb +0 -53
- data/lib/contrast/extension/kernel.rb +0 -54
@@ -16,28 +16,42 @@ module Contrast
|
|
16
16
|
# relay this information in the Finding/Trace messages. These findings are used by TeamServer to construct the
|
17
17
|
# vulnerability information for the assess feature. They represent those parts of the application, either through
|
18
18
|
# configuration, method invocation, or dataflow, which are determined to be insecure.
|
19
|
-
#
|
20
|
-
# @attr_accessor events [Array<Contrast::Agent::Assess::ContrastEvent>] if a dataflow based finding, the
|
21
|
-
# representation of those method calls which constitute a dangerous code path.
|
22
|
-
# @attr_accessor properties [Hash<String,String>] a set of values that TeamServer can use to provide more context
|
23
|
-
# to the user when rendering the finding. For some findings, a specific set of keys and values are required.
|
24
|
-
# @attr_accessor request [Contrast::Agent::Request, nil] the request, if any, in which this finding occurred
|
25
|
-
# @attr_accessor hash_code [String] the unique identifier of this finding.
|
26
|
-
# @attr_reader rule_id [String] the name of the rule violated; must match those in TeamServer.
|
27
19
|
class Finding < Contrast::Agent::Reporting::ReportingEvent
|
28
|
-
|
20
|
+
include Contrast::Components::Logger::InstanceMethods
|
21
|
+
|
22
|
+
# @return [Integer] the time, in ms, that this object was initialized
|
23
|
+
attr_reader :created
|
24
|
+
# @return [String] the ID of the rule associated with this finding
|
25
|
+
attr_reader :rule_id
|
26
|
+
# @return [Array<Contrast::Agent::Reporting::RouteDiscovery>] the routes associated with this finding, if the
|
27
|
+
# finding is request based.
|
28
|
+
attr_reader :routes
|
29
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEvent>] the events associated with this finding, if the
|
30
|
+
# finding is event (dataflow) based.
|
31
|
+
attr_reader :events
|
32
|
+
# @return [String] the evidence associated with this finding, if the finding is event based. deprecated in
|
33
|
+
# favor of properties
|
34
|
+
# attr_reader :evidence
|
35
|
+
# @return [Hash<String,String>] properties that prove the violation of the rule for this finding
|
36
|
+
attr_reader :properties
|
37
|
+
# @return [Contrast::Agent::Reporting::FindingRequest] the request associated with this finding, if the finding
|
38
|
+
# is request based
|
39
|
+
attr_reader :request
|
40
|
+
# @return [String] the uniquely identifying hash of this finding
|
29
41
|
attr_accessor :hash_code
|
30
42
|
|
43
|
+
CONFIGURATION_RULES = %w[rails-http-only-disabled secure-flag-missing session-timeout].cs__freeze
|
44
|
+
HARDCODED_RULES = %w[hardcoded-key hardcoded-password].cs__freeze
|
31
45
|
PROPERTIES_RULES = %w[
|
32
46
|
autocomplete-missing
|
33
47
|
cache-controls-missing
|
34
48
|
clickjacking-control-missing
|
35
|
-
xcontenttype-header-missing
|
36
|
-
hsts-header-missing
|
37
|
-
xxssprotection-header-disabled
|
38
49
|
csp-header-missing
|
39
50
|
csp-header-insecure
|
51
|
+
hsts-header-missing
|
40
52
|
parameter-pollution
|
53
|
+
xcontenttype-header-missing
|
54
|
+
xxssprotection-header-disabled
|
41
55
|
].cs__freeze
|
42
56
|
|
43
57
|
class << self
|
@@ -57,6 +71,7 @@ module Contrast
|
|
57
71
|
@routes = []
|
58
72
|
@rule_id = Contrast::Utils::StringUtils.truncate(rule_id)
|
59
73
|
@properties = {}
|
74
|
+
@created = Contrast::Utils::Timer.now_ms
|
60
75
|
super()
|
61
76
|
end
|
62
77
|
|
@@ -76,15 +91,16 @@ module Contrast
|
|
76
91
|
# @param request [Contrast::Agent::Request]
|
77
92
|
# @param args [Array<Object>] the Arguments with which the method was invoked
|
78
93
|
def attach_data trigger_node, source, object, ret, request, *args
|
94
|
+
event_messages = Contrast::Agent::Reporting::FindingEvent.from_source(source)
|
95
|
+
events.concat(event_messages) if event_messages&.any?
|
79
96
|
event_data = Contrast::Agent::Assess::Events::EventData.new(trigger_node, source, object, ret, args)
|
80
|
-
|
81
|
-
events.
|
82
|
-
if request
|
83
|
-
@request = Contrast::Agent::Reporting::FindingRequest.convert(request)
|
84
|
-
@routes << Contrast::Agent::Reporting::RouteDiscovery.convert(request&.route)
|
85
|
-
end
|
86
|
-
events << Contrast::Agent::Assess::ContrastEvent.new(event_data)
|
97
|
+
contrast_event = Contrast::Agent::Assess::ContrastEvent.new(event_data)
|
98
|
+
events << Contrast::Agent::Reporting::FindingEvent.convert(contrast_event)
|
87
99
|
attach_properties
|
100
|
+
return unless request
|
101
|
+
|
102
|
+
@request = Contrast::Agent::Reporting::FindingRequest.convert(request)
|
103
|
+
@routes << Contrast::Agent::Reporting::RouteDiscovery.convert(request.route)
|
88
104
|
end
|
89
105
|
|
90
106
|
# Attach the data from a Contrast::Api::Dtm::Finding required for property based findings generated during
|
@@ -92,7 +108,6 @@ module Contrast
|
|
92
108
|
#
|
93
109
|
# @param finding_dtm [Contrast::Api::Dtm::Finding]
|
94
110
|
def attach_property_data finding_dtm
|
95
|
-
@created = Contrast::Utils::Timer.now_ms
|
96
111
|
@hash_code = finding_dtm.hash_code
|
97
112
|
@rule_id = finding_dtm.rule_id
|
98
113
|
finding_dtm.properties.each_pair do |key, value|
|
@@ -101,7 +116,7 @@ module Contrast
|
|
101
116
|
finding_dtm.routes.each do |route|
|
102
117
|
@routes << Contrast::Agent::Reporting::RouteDiscovery.convert(route)
|
103
118
|
end
|
104
|
-
request = Contrast::Agent::REQUEST_TRACKER.current&.
|
119
|
+
request = Contrast::Agent::REQUEST_TRACKER.current&.request
|
105
120
|
@request = Contrast::Agent::Reporting::FindingRequest.convert(request) if request
|
106
121
|
end
|
107
122
|
|
@@ -113,20 +128,20 @@ module Contrast
|
|
113
128
|
def to_controlled_hash
|
114
129
|
validate
|
115
130
|
hsh = {
|
116
|
-
created:
|
117
|
-
hash: hash_code,
|
118
|
-
ruleId:
|
119
|
-
session_id: @agent_session_id_value,
|
131
|
+
created: created,
|
132
|
+
hash: hash_code.to_s,
|
133
|
+
ruleId: rule_id,
|
134
|
+
session_id: @agent_session_id_value.to_s,
|
120
135
|
version: 4
|
121
136
|
}
|
122
|
-
hsh[:events] = events if event_based?
|
123
|
-
hsh[:evidence] =
|
137
|
+
hsh[:events] = events.map(&:to_controlled_hash) if event_based?
|
138
|
+
# hsh[:evidence] = evidence unless event_based? || property_based?
|
124
139
|
hsh[:properties] = properties if property_based?
|
125
140
|
hsh[:tags] = Contrast::ASSESS.tags if Contrast::ASSESS.tags
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
141
|
+
return hsh unless request_based?
|
142
|
+
|
143
|
+
hsh[:request] = request.to_controlled_hash
|
144
|
+
hsh[:routes] = routes.map(&:to_controlled_hash)
|
130
145
|
hsh
|
131
146
|
end
|
132
147
|
|
@@ -135,14 +150,14 @@ module Contrast
|
|
135
150
|
raise(ArgumentError, "#{ self } did not have a proper rule. Unable to continue.") unless @rule_id
|
136
151
|
|
137
152
|
if event_based? && events.empty?
|
138
|
-
raise(ArgumentError, "#{ self } did not have proper events. Unable to continue.")
|
153
|
+
raise(ArgumentError, "#{ self } did not have proper events for #{ @rule_id }. Unable to continue.")
|
139
154
|
end
|
140
155
|
if property_based? && properties.empty?
|
141
|
-
raise(ArgumentError, "#{ self } did not have proper properties. Unable to continue.")
|
156
|
+
raise(ArgumentError, "#{ self } did not have proper properties for #{ @rule_id }. Unable to continue.")
|
142
157
|
end
|
143
158
|
return unless request_based? && request.nil?
|
144
159
|
|
145
|
-
raise(ArgumentError, "#{ self } did not have a proper request. Unable to continue.")
|
160
|
+
raise(ArgumentError, "#{ self } did not have a proper request for #{ @rule_id }. Unable to continue.")
|
146
161
|
end
|
147
162
|
|
148
163
|
private
|
@@ -169,7 +184,7 @@ module Contrast
|
|
169
184
|
#
|
170
185
|
# @return [Boolean]
|
171
186
|
def event_based?
|
172
|
-
!property_based?
|
187
|
+
!property_based? && !config_based?
|
173
188
|
end
|
174
189
|
|
175
190
|
# Rules which are property based must have a property to be sent to TeamServer. Eventually, each rule may own
|
@@ -181,13 +196,31 @@ module Contrast
|
|
181
196
|
PROPERTIES_RULES.include?(@rule_id)
|
182
197
|
end
|
183
198
|
|
199
|
+
# Rules which are config based must have a configuration to be sent to TeamServer. Eventually, each rule may own
|
200
|
+
# its own validation, as the properties each needs are different; however, that's a refactor for after we've
|
201
|
+
# translated all rules from the Service and have had time to build proper child structure.
|
202
|
+
#
|
203
|
+
# @return [Boolean]
|
204
|
+
def config_based?
|
205
|
+
CONFIGURATION_RULES.include?(@rule_id)
|
206
|
+
end
|
207
|
+
|
208
|
+
# Rules which are hardcode based send properties to TeamServer. Eventually, each rule may own its own
|
209
|
+
# validation, as the properties each needs are different; however, that's a refactor for after we've
|
210
|
+
# translated all rules from the Service and have had time to build proper child structure.
|
211
|
+
#
|
212
|
+
# @return [Boolean]
|
213
|
+
def hardcoded?
|
214
|
+
HARDCODED_RULES.include?(@rule_id)
|
215
|
+
end
|
216
|
+
|
184
217
|
# Rules which are request based must have a request to be sent to TeamServer. Most rules fit this category, so
|
185
218
|
# we'll default to true for now. Eventually, this will be split out for those rules, like Hardcoded, which do
|
186
219
|
# not need requests.
|
187
220
|
#
|
188
221
|
# @return [Boolean]
|
189
222
|
def request_based?
|
190
|
-
|
223
|
+
!config_based? && !hardcoded?
|
191
224
|
end
|
192
225
|
end
|
193
226
|
end
|
@@ -1,44 +1,63 @@
|
|
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/reporting_events/finding_event_object'
|
5
|
+
require 'contrast/agent/reporting/reporting_events/finding_event_parent_object'
|
6
|
+
require 'contrast/agent/reporting/reporting_events/finding_event_property'
|
7
|
+
require 'contrast/agent/reporting/reporting_events/finding_event_signature'
|
4
8
|
require 'contrast/agent/reporting/reporting_events/finding_event_source'
|
5
|
-
require 'contrast/agent/reporting/reporting_events/
|
6
|
-
require 'contrast/agent/reporting/reporting_events/
|
7
|
-
require 'contrast/agent/reporting/reporting_events/finding_taint_range'
|
9
|
+
require 'contrast/agent/reporting/reporting_events/finding_event_stack'
|
10
|
+
require 'contrast/agent/reporting/reporting_events/finding_event_taint_range'
|
8
11
|
|
9
12
|
module Contrast
|
10
13
|
module Agent
|
11
14
|
module Reporting
|
12
|
-
# This is the new
|
13
|
-
# relay this information in the Finding/Trace messages. These
|
14
|
-
# vulnerability information for the assess feature. They represent
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# @attr_reader action [String] what the event did; CREATION, A2O, A2P, A2A, A2R, O2A, O2O, O2P, O2R, P2A, P2O,
|
18
|
-
# P2P, P2R, TAG, TRIGGER.
|
19
|
-
# @attr_reader args [Array<Contrast::Agent::Reporting::FindingObject>] the arguments passed to the method.
|
20
|
-
# @attr_reader code [nil] unused.
|
21
|
-
# @attr_reader event_id [Integer] the id of this event.
|
22
|
-
# @attr_reader event_sources [Array<Contrast::Agent::Reporting::FindingEventSource>] the source of taint
|
23
|
-
# @attr_reader field_name [nil] unused.
|
24
|
-
# @attr_reader object [Contrast::Agent::Reporting::FindingEventSource] the object this method was invoked on.
|
25
|
-
# @attr_reader parent_object_ids [Array<Integer>]
|
26
|
-
# @attr_reader properties [Hash<String,String]
|
27
|
-
# @attr_reader ret [Contrast::Agent::Reporting::FindingObject] the return of the method.
|
28
|
-
# @attr_reader signature [Contrast::Agent::Reporting::FindingSignature] the signature of the method.
|
29
|
-
# @attr_reader source [String] the source of the taint from the method; ^(O|R|P\d+)$
|
30
|
-
# @attr_reader stack [Array<Contrast::Agent::Reporting::FindingStack>]
|
31
|
-
# @attr_reader tags [Array<String>] description of what's happened to the data
|
32
|
-
# @attr_reader taint_ranges [Array<Contrast::Agent::Reporting::FindingTaintRange>] the tags and spans of the
|
33
|
-
# source that are tracked
|
34
|
-
# @attr_reader target [String] the target of the taint from the method; ^(O|R|P\d+)$
|
35
|
-
# @attr_reader thread [String] the id of the thread on which the method was invoked
|
36
|
-
# @attr_reader time [Integer] the time, in ms, when the event was generated
|
37
|
-
# @attr_reader type [String] the type of event; METHOD, PROPAGATION, TAG
|
15
|
+
# This is the new FindingEvent class which will include all the needed information for the new reporting system
|
16
|
+
# to relay this information in the Finding/Trace messages. These FindingEvents are used by TeamServer to
|
17
|
+
# construct the vulnerability information for the assess feature. They represent the operation the application
|
18
|
+
# underwent that transformed data during the dataflow.
|
38
19
|
class FindingEvent
|
39
|
-
|
40
|
-
|
41
|
-
|
20
|
+
# @return [Symbol] what the event did; CREATION, A2O, A2P, A2A, A2R, O2A, O2O, O2P, O2R, P2A, P2O, P2P, P2R,
|
21
|
+
# TAG, TRIGGER.
|
22
|
+
attr_reader :action
|
23
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEventObject>] the arguments passed to the method.
|
24
|
+
attr_reader :args
|
25
|
+
# @return [nil] unused.
|
26
|
+
attr_reader :code
|
27
|
+
# @return [Integer] the id of this event.
|
28
|
+
attr_reader :event_id
|
29
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEventSource>] the source of taint
|
30
|
+
attr_reader :event_sources
|
31
|
+
# @return [nil] unused.
|
32
|
+
attr_reader :field_name
|
33
|
+
# @return [Contrast::Agent::Reporting::FindingEventObject] the object this method was invoked on.
|
34
|
+
attr_reader :object
|
35
|
+
# @@return [Array<Contrast::Agent::Reporting::FindingEventParentObject>] the ids of all the events directly
|
36
|
+
# preceding this
|
37
|
+
attr_reader :parent_object_ids
|
38
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEventProperty>]
|
39
|
+
attr_reader :properties
|
40
|
+
# @return [Contrast::Agent::Reporting::FindingEventObject] the return of the method.
|
41
|
+
attr_reader :ret
|
42
|
+
# @return [Contrast::Agent::Reporting::FindingEventSignature] the signature of the method.
|
43
|
+
attr_reader :signature
|
44
|
+
# @return [String] the source of the taint from the method; ^(O|R|P\d+)$
|
45
|
+
attr_reader :source
|
46
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEventStack>]
|
47
|
+
attr_reader :stack
|
48
|
+
# @return [String] comma separated list of descriptions of what's happened to the data
|
49
|
+
attr_reader :tags
|
50
|
+
# @return [Array<Contrast::Agent::Reporting::FindingEventTaintRange>] the tags and spans of the source that are
|
51
|
+
# tracked
|
52
|
+
attr_reader :taint_ranges
|
53
|
+
# @return [String] the target of the taint from the method; ^(O|R|P\d+)$
|
54
|
+
attr_reader :target
|
55
|
+
# @return [String] the id of the thread on which the method was invoked
|
56
|
+
attr_reader :thread
|
57
|
+
# @return [Integer] the time, in ms, when the event was generated
|
58
|
+
attr_reader :time
|
59
|
+
# @return [String] the type of event; METHOD, PROPAGATION, TAG
|
60
|
+
attr_reader :type
|
42
61
|
|
43
62
|
class << self
|
44
63
|
# Find all the events leading up to the given source and return an array of FindingEvents
|
@@ -48,7 +67,7 @@ module Contrast
|
|
48
67
|
def from_source source
|
49
68
|
return unless source && (props = Contrast::Agent::Assess::Tracker.properties(source))
|
50
69
|
|
51
|
-
build_events([], props.event) if props
|
70
|
+
build_events([], props.event) if props.event
|
52
71
|
end
|
53
72
|
|
54
73
|
# @param event [Contrast::Agent::Assess::ContrastEvent]
|
@@ -71,7 +90,7 @@ module Contrast
|
|
71
90
|
return unless event
|
72
91
|
|
73
92
|
event.parent_events&.each do |parent_event|
|
74
|
-
build_events(
|
93
|
+
build_events(events, parent_event)
|
75
94
|
end
|
76
95
|
events << convert(event)
|
77
96
|
events
|
@@ -85,11 +104,11 @@ module Contrast
|
|
85
104
|
def attach_data event
|
86
105
|
@event_id = event.event_id
|
87
106
|
@time = event.time.to_i
|
88
|
-
@thread = event.thread
|
107
|
+
@thread = event.thread.to_s
|
89
108
|
display_params!(event)
|
90
109
|
dataflow!(event)
|
91
110
|
event_sources!(event)
|
92
|
-
@signature = Contrast::Agent::Reporting::
|
111
|
+
@signature = Contrast::Agent::Reporting::FindingEventSignature.convert(event)
|
93
112
|
stack!(event)
|
94
113
|
parent_ids!(event)
|
95
114
|
properties!(event)
|
@@ -100,25 +119,25 @@ module Contrast
|
|
100
119
|
#
|
101
120
|
# @return [Hash]
|
102
121
|
# @raise [ArgumentError]
|
103
|
-
def to_controlled_hash
|
122
|
+
def to_controlled_hash # rubocop:disable Metrics/AbcSize
|
104
123
|
validate
|
105
124
|
{
|
106
125
|
action: action,
|
107
|
-
args: args,
|
126
|
+
args: args.map(&:to_controlled_hash),
|
108
127
|
# code: code, # Unused by our agent
|
109
|
-
|
110
|
-
eventSources: event_sources,
|
128
|
+
objectId: event_id,
|
129
|
+
eventSources: event_sources.map(&:to_controlled_hash),
|
111
130
|
# fieldName: field_name, # Unused by our agent
|
112
|
-
object: object,
|
113
|
-
parentObjectIds: parent_object_ids,
|
114
|
-
properties: properties,
|
115
|
-
ret: ret,
|
116
|
-
signature: signature,
|
117
|
-
source: source,
|
118
|
-
stack: stack,
|
119
|
-
tags: tags,
|
120
|
-
taintRanges: taint_ranges,
|
121
|
-
target: target,
|
131
|
+
object: object.to_controlled_hash,
|
132
|
+
parentObjectIds: parent_object_ids.map(&:to_controlled_hash),
|
133
|
+
properties: properties.map(&:to_controlled_hash),
|
134
|
+
ret: ret&.to_controlled_hash,
|
135
|
+
signature: signature.to_controlled_hash,
|
136
|
+
source: source || '',
|
137
|
+
stack: stack.map(&:to_controlled_hash),
|
138
|
+
tags: tags.join(','),
|
139
|
+
taintRanges: taint_ranges.map(&:to_controlled_hash),
|
140
|
+
target: target || '',
|
122
141
|
thread: thread,
|
123
142
|
time: time,
|
124
143
|
type: type
|
@@ -139,7 +158,14 @@ module Contrast
|
|
139
158
|
# @param event [Contrast::Agent::Assess::ContrastEvent]
|
140
159
|
def display_params! event
|
141
160
|
@action = event.policy_node.build_action
|
142
|
-
@type = event.policy_node.node_type
|
161
|
+
@type = case event.policy_node.node_type
|
162
|
+
when :TYPE_TAG
|
163
|
+
'TAG'
|
164
|
+
when :TYPE_PROPAGATION
|
165
|
+
'PROPAGATION'
|
166
|
+
else # :TYPE_METHOD
|
167
|
+
'METHOD'
|
168
|
+
end
|
143
169
|
end
|
144
170
|
|
145
171
|
# Build the dataflow components of this FindingEvent.
|
@@ -148,9 +174,9 @@ module Contrast
|
|
148
174
|
def dataflow! event
|
149
175
|
taint_target = taint_target!(event)
|
150
176
|
truncate_obj = Contrast::Utils::ObjectShare::OBJECT_KEY != taint_target
|
151
|
-
@object = Contrast::Agent::Reporting::
|
177
|
+
@object = Contrast::Agent::Reporting::FindingEventObject.convert(event.object, truncate_obj)
|
152
178
|
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
153
|
-
@ret = Contrast::Agent::Reporting::
|
179
|
+
@ret = Contrast::Agent::Reporting::FindingEventObject.convert(event.ret, truncate_ret)
|
154
180
|
event_args!(event, taint_target)
|
155
181
|
taint_ranges!(event)
|
156
182
|
end
|
@@ -164,7 +190,7 @@ module Contrast
|
|
164
190
|
@args = []
|
165
191
|
idx = 0
|
166
192
|
while idx < event.args.length
|
167
|
-
@args << Contrast::Agent::Reporting::
|
193
|
+
@args << Contrast::Agent::Reporting::FindingEventObject.convert(event.args[idx], taint_target != idx)
|
168
194
|
idx += 1
|
169
195
|
end
|
170
196
|
end
|
@@ -176,7 +202,8 @@ module Contrast
|
|
176
202
|
@event_sources = []
|
177
203
|
return unless event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
|
178
204
|
|
179
|
-
|
205
|
+
source = Contrast::Agent::Reporting::FindingEventSource.convert(event)
|
206
|
+
event_sources << source if source
|
180
207
|
end
|
181
208
|
|
182
209
|
# Convert the parent id's of the given ContrastEvent to the reportable form for this FindingEvent.
|
@@ -185,7 +212,7 @@ module Contrast
|
|
185
212
|
def parent_ids! event
|
186
213
|
@parent_object_ids = []
|
187
214
|
event.parent_events&.each do |parent_event|
|
188
|
-
parent_object_ids << parent_event.event_id.to_i
|
215
|
+
parent_object_ids << Contrast::Agent::Reporting::FindingEventParentObject.new(parent_event.event_id.to_i)
|
189
216
|
end
|
190
217
|
end
|
191
218
|
|
@@ -194,7 +221,7 @@ module Contrast
|
|
194
221
|
#
|
195
222
|
# @param _event [Contrast::Agent::Assess::ContrastEvent]
|
196
223
|
def properties! _event
|
197
|
-
@properties =
|
224
|
+
@properties = []
|
198
225
|
end
|
199
226
|
|
200
227
|
# Convert the stack of the given ContrastEvent to the reportable form for this FindingEvent.
|
@@ -203,7 +230,7 @@ module Contrast
|
|
203
230
|
def stack! event
|
204
231
|
@stack = []
|
205
232
|
event.stack_trace.each do |stack_event|
|
206
|
-
if (report = Contrast::Agent::Reporting::
|
233
|
+
if (report = Contrast::Agent::Reporting::FindingEventStack.convert(stack_event))
|
207
234
|
stack << report
|
208
235
|
end
|
209
236
|
end
|
@@ -217,7 +244,9 @@ module Contrast
|
|
217
244
|
@taint_ranges = []
|
218
245
|
event&.tags&.each_pair do |tag_key, tag_ranges|
|
219
246
|
tags << tag_key
|
220
|
-
tag_ranges.each
|
247
|
+
tag_ranges.each do |range|
|
248
|
+
taint_ranges << Contrast::Agent::Reporting::FindingEventTaintRange.convert(range)
|
249
|
+
end
|
221
250
|
end
|
222
251
|
end
|
223
252
|
|
data/lib/contrast/agent/reporting/reporting_events/{finding_object.rb → finding_event_object.rb}
RENAMED
@@ -2,20 +2,22 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'base64'
|
5
|
+
require 'contrast/agent/assess/contrast_object'
|
5
6
|
|
6
7
|
module Contrast
|
7
8
|
module Agent
|
8
9
|
module Reporting
|
9
|
-
# This is the new
|
10
|
-
# to relay this information in the Finding/Trace messages. These
|
11
|
-
# construct the vulnerability information for the assess feature. They represent those parts of the
|
12
|
-
# were acted on in a Dataflow Finding.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
# This is the new FindingEventObject class which will include all the needed information for the new reporting
|
11
|
+
# system to relay this information in the Finding/Trace messages. These FindingEventObjects are used by
|
12
|
+
# TeamServer to construct the vulnerability information for the assess feature. They represent those parts of the
|
13
|
+
# objects that were acted on in a Dataflow Finding.
|
14
|
+
class FindingEventObject
|
15
|
+
# @return [Integer] the id of the Object this represents.
|
16
|
+
attr_reader :hash
|
17
|
+
# @return [Boolean] if the Object is tracked or not
|
18
|
+
attr_reader :tracked
|
19
|
+
# @return [String] the base64 of the human readable representation of the Object this represents.
|
20
|
+
attr_reader :value
|
19
21
|
|
20
22
|
# We'll truncate any object that isn't important to the taint ranges of this event, so that we don't murder
|
21
23
|
# TeamServer by, for instance, hypothetically sending the entire rendered HTML page >_> <_< >_>
|
@@ -25,8 +27,8 @@ module Contrast
|
|
25
27
|
|
26
28
|
class << self
|
27
29
|
# @param object [Contrast::Agent::Assess::ContrastObject] the object to translate
|
28
|
-
# @param truncate [Boolean] if the value of this
|
29
|
-
# @return [Contrast::Agent::Reporting::
|
30
|
+
# @param truncate [Boolean] if the value of this FindingEventObject should be truncated or not
|
31
|
+
# @return [Contrast::Agent::Reporting::FindingEventObject]
|
30
32
|
def convert object, truncate
|
31
33
|
report = new
|
32
34
|
report.attach_data(object, truncate)
|
@@ -35,13 +37,13 @@ module Contrast
|
|
35
37
|
end
|
36
38
|
|
37
39
|
# Parse the data from a Contrast::Agent::Assess::ContrastObject to attach what is required for reporting to
|
38
|
-
# TeamServer to this Contrast::Agent::Reporting::
|
40
|
+
# TeamServer to this Contrast::Agent::Reporting::FindingEventObject
|
39
41
|
#
|
40
|
-
# @param object [Contrast::Agent::Assess::ContrastObject]
|
42
|
+
# @param object [Contrast::Agent::Assess::ContrastObject, nil]
|
41
43
|
def attach_data object, truncate
|
42
|
-
@hash = object.__id__
|
43
|
-
@tracked = object
|
44
|
-
@value = reportable_value(object
|
44
|
+
@hash = object&.object.__id__
|
45
|
+
@tracked = !!object&.tracked?
|
46
|
+
@value = reportable_value(object&.object, truncate)
|
45
47
|
end
|
46
48
|
|
47
49
|
# Convert the instance variables on the class, and other information, into the identifiers required for
|
@@ -59,9 +61,9 @@ module Contrast
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def validate
|
62
|
-
raise(ArgumentError, "#{ self } did not have a proper hash. Unable to continue.") unless hash
|
64
|
+
raise(ArgumentError, "#{ self } did not have a proper hash. Unable to continue.") unless hash
|
63
65
|
raise(ArgumentError, "#{ self } did not have a proper tracked. Unable to continue.") if tracked.nil?
|
64
|
-
return
|
66
|
+
return if value
|
65
67
|
|
66
68
|
raise(ArgumentError, "#{ self } did not have a proper value. Unable to continue.")
|
67
69
|
end
|
@@ -71,10 +73,12 @@ module Contrast
|
|
71
73
|
# Parse, truncate, and translate the given value to be reported to TeamServer. The field is expected to be
|
72
74
|
# base64 encoded.
|
73
75
|
#
|
74
|
-
# @param value [String] the contrast_string of the object this represents.
|
76
|
+
# @param value [String, nil] the contrast_string of the object this represents.
|
75
77
|
# @param truncate [Boolean] if the string should be truncated or not.
|
76
78
|
# @return [String]
|
77
79
|
def reportable_value value, truncate
|
80
|
+
return Contrast::Utils::ObjectShare::NIL_STRING unless value
|
81
|
+
|
78
82
|
if truncate && value.length > TRUNCATION_LENGTH
|
79
83
|
tmp = []
|
80
84
|
tmp << value[0, UNTRUNCATED_PORTION_LENGTH]
|
@@ -0,0 +1,39 @@
|
|
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 'base64'
|
5
|
+
|
6
|
+
module Contrast
|
7
|
+
module Agent
|
8
|
+
module Reporting
|
9
|
+
# This is the new FindingEventParentObject class which will include all the needed information for the new
|
10
|
+
# reporting system to relay this information in the Finding/Trace messages. These FindingEventParentObject are
|
11
|
+
# used by TeamServer to relate this event to those that came previously. They represent the events that directly
|
12
|
+
# preceding the FindingEvent generated.
|
13
|
+
class FindingEventParentObject
|
14
|
+
# @return [Integer] the Id of the parent event
|
15
|
+
attr_reader :id
|
16
|
+
|
17
|
+
def initialize id
|
18
|
+
@id = id
|
19
|
+
end
|
20
|
+
|
21
|
+
# Convert the instance variables on the class, and other information, into the identifiers required for
|
22
|
+
# TeamServer to process the JSON form of this message.
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
# @raise [ArgumentError]
|
26
|
+
def to_controlled_hash
|
27
|
+
validate
|
28
|
+
{
|
29
|
+
id: id
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate
|
34
|
+
raise(ArgumentError, "#{ self } did not have a proper id. Unable to continue.") unless id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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 is the new FindingEventProperty class which will include all the needed information for the new reporting
|
8
|
+
# system to relay this information in the Finding/Trace messages. Events have properties on them which are held
|
9
|
+
# as an array of key-value pairs.
|
10
|
+
class FindingEventProperty
|
11
|
+
# @return [String] the key of the property
|
12
|
+
attr_reader :key
|
13
|
+
# @return [String] the value of the source
|
14
|
+
attr_reader :value
|
15
|
+
|
16
|
+
def initialize key, value
|
17
|
+
@key = key
|
18
|
+
@value = value
|
19
|
+
end
|
20
|
+
|
21
|
+
# Convert the instance variables on the class, and other information, into the identifiers required for
|
22
|
+
# TeamServer to process the JSON form of this message.
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
# @raise [ArgumentError]
|
26
|
+
def to_controlled_hash
|
27
|
+
validate
|
28
|
+
{
|
29
|
+
key: key,
|
30
|
+
value: value
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate
|
35
|
+
raise(ArgumentError, "#{ self } did not have a proper key. Unable to continue.") unless key && !key.empty?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|