contrast-agent 7.6.0 → 7.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +2 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +35 -7
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +7 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +1 -6
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +4 -6
- data/lib/contrast/agent/request/request.rb +1 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/utils/hash_digest.rb +0 -14
- data/lib/contrast/utils/hash_digest_extend.rb +16 -5
- data/lib/contrast/utils/json.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8363c48e9a12500ea45f3d40389d6bf29d7931e01599a577dfb4026c9cedc260
|
4
|
+
data.tar.gz: 1c21202db2612d8715f1658fa9818442e16a5a51f613143a3c3c6b69c0a0fabf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f5fe5203e78e7ea7c6e996c32367c340704f3d1544890b64ed856d3554ef53f3006cc948fab0f3d36108e1577d19196249c10ee8f0fcee95c8677115b7a4a64
|
7
|
+
data.tar.gz: 7a1d876e9c49940daf97589adaaf5d2550fdbd51bd2216f44a28bf4f97ab9431a5b5db200035089a76bfbe66bf8849aed58f382ee99e7e681e555b8da5097af5
|
@@ -73,7 +73,8 @@ module Contrast
|
|
73
73
|
finding.routes << context.discovered_route if context&.discovered_route
|
74
74
|
build_evidence(evidence, finding)
|
75
75
|
finding.request = Contrast::Agent::Reporting::FindingRequest.convert(context.request) if context&.request
|
76
|
-
|
76
|
+
# Hash must be built last so that finding has full context.
|
77
|
+
hash = Contrast::Utils::HashDigest.generate_response_hash(finding, context&.request)
|
77
78
|
finding.hash_code = Contrast::Utils::StringUtils.force_utf8(hash)
|
78
79
|
finding
|
79
80
|
end
|
@@ -69,21 +69,46 @@ module Contrast
|
|
69
69
|
# @param event [Contrast::Agent::Reporting::ReportingEvent] The event to send to TeamServer. Really a
|
70
70
|
# child of the ReportingEvent rather than a literal one.
|
71
71
|
# @param connection [Net::HTTP] open connection
|
72
|
-
# @return response [Net::HTTPResponse, nil] response from TS if no response
|
73
72
|
def send_event event, connection
|
74
73
|
return unless connection
|
75
74
|
return unless event.valid?
|
76
75
|
|
77
76
|
logger.debug('[Reporter] Preparing to send reporting event', event_class: event.cs__class)
|
78
77
|
request = build_request(event)
|
79
|
-
|
78
|
+
begin
|
79
|
+
response = connection.request(request)
|
80
|
+
rescue StandardError => e
|
81
|
+
handle_response_error(event, connection, e)
|
82
|
+
return
|
83
|
+
end
|
80
84
|
audit.audit_event(event, response) if ::Contrast::API.request_audit_enable
|
81
|
-
|
82
|
-
process_preflight_response(event, response, connection)
|
83
|
-
report_configuration(response, event)
|
85
|
+
process_event_response(event, response, connection)
|
84
86
|
response
|
85
87
|
rescue StandardError => e
|
86
|
-
|
88
|
+
logger.error('[Reporter] Error while processing event sent to TeamServer',
|
89
|
+
error: e,
|
90
|
+
event_type: event&.cs__class)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Only two types of events require processing when returned from TeamServer; preflight and settings.
|
94
|
+
# For Settings, we want to update internally and then report the resulting configuration.
|
95
|
+
# For preflight, we want to process the response and send findings if requested.
|
96
|
+
#
|
97
|
+
# @param event [Contrast::Agent::Reporting::ReportingEvent] The event sent to TeamServer
|
98
|
+
# @param response [Net::HTTPResponse] the response from TeamServer
|
99
|
+
# @param connection [Net::HTTP] open connection
|
100
|
+
def process_event_response event, response, connection
|
101
|
+
case event
|
102
|
+
when Contrast::Agent::Reporting::Preflight
|
103
|
+
process_preflight_response(event, response, connection)
|
104
|
+
when Contrast::Agent::Reporting::AgentStartup,
|
105
|
+
Contrast::Agent::Reporting::ApplicationStartup,
|
106
|
+
Contrast::Agent::Reporting::ApplicationSettings,
|
107
|
+
Contrast::Agent::Reporting::ServerSettings
|
108
|
+
|
109
|
+
process_settings_response(response, event)
|
110
|
+
report_configuration(response, event)
|
111
|
+
end
|
87
112
|
end
|
88
113
|
|
89
114
|
# Write effective config to file:
|
@@ -91,7 +116,7 @@ module Contrast
|
|
91
116
|
# 200 or 304. In case of 304 there will be no new settings and we can write current ones.
|
92
117
|
# This is done on every settings request.
|
93
118
|
#
|
94
|
-
# @param response [
|
119
|
+
# @param response [Net::HTTPResponse, nil]
|
95
120
|
# @param event [Contrast::Agent::Reporting::ReportingEvent]
|
96
121
|
def report_configuration response, event
|
97
122
|
return unless response
|
@@ -109,14 +134,17 @@ module Contrast
|
|
109
134
|
logger.error('[Reporter] Error while reporting configuration', error: e, event_type: event&.cs__class)
|
110
135
|
end
|
111
136
|
|
137
|
+
# @return [Contrast::Agent::Reporting::ConnectionStatus]
|
112
138
|
def status
|
113
139
|
@_status ||= Contrast::Agent::Reporting::ConnectionStatus.new
|
114
140
|
end
|
115
141
|
|
142
|
+
# @return [Contrast::Agent::Reporting::ResponseHandler]
|
116
143
|
def response_handler
|
117
144
|
@_response_handler ||= Contrast::Agent::Reporting::ResponseHandler.new
|
118
145
|
end
|
119
146
|
|
147
|
+
# @return [Contrast::Config::Diagnostics::Monitor]
|
120
148
|
def diagnostics
|
121
149
|
@_diagnostics ||= Contrast::Config::Diagnostics::Monitor.new(Contrast::LOGGER.path)
|
122
150
|
end
|
@@ -91,6 +91,7 @@ module Contrast
|
|
91
91
|
#
|
92
92
|
# @param event [Contrast::Agent::Reporting::ReportingEvent] The event sent to TeamServer.
|
93
93
|
# @param response [Net::HTTPResponse]
|
94
|
+
# @return [Contrast::Agent::Reporting::Response]
|
94
95
|
def process_settings_response response, event
|
95
96
|
res = response_handler.process(response, event)
|
96
97
|
if res
|
@@ -115,7 +116,6 @@ module Contrast
|
|
115
116
|
return unless response&.body && connection
|
116
117
|
|
117
118
|
findings_to_return = response.body.split(',').delete_if { |el| el.include?('*') }
|
118
|
-
mode.resend.reset_rescue_attempts
|
119
119
|
findings_to_return.each do |index|
|
120
120
|
preflight_message = event.messages[index.to_i]
|
121
121
|
preflight_data = preflight_message&.data
|
@@ -127,6 +127,12 @@ module Contrast
|
|
127
127
|
|
128
128
|
send_event(corresponding_finding, connection)
|
129
129
|
end
|
130
|
+
|
131
|
+
# Event rejected traces should be removed from the set.
|
132
|
+
# We could clean this up to know if the message was already deleted by the loop above.
|
133
|
+
event.messages&.each do |preflight_message|
|
134
|
+
Contrast::Agent::Reporting::ReportingStorage.delete(preflight_message&.data)
|
135
|
+
end
|
130
136
|
rescue StandardError => e
|
131
137
|
logger.error('[Reporter] Unable to handle preflight response', e)
|
132
138
|
end
|
@@ -44,12 +44,7 @@ module Contrast
|
|
44
44
|
def delete key
|
45
45
|
return unless key
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
deleted_value = collection.delete(key)
|
50
|
-
logger.debug('Key wasn\'t found') unless deleted_value
|
51
|
-
|
52
|
-
deleted_value
|
47
|
+
collection.delete(key)
|
53
48
|
end
|
54
49
|
|
55
50
|
# @param rule_id [String] the rule_id
|
@@ -25,6 +25,7 @@ module Contrast
|
|
25
25
|
# @return response [Net::HTTPResponse, nil]
|
26
26
|
def process response, event
|
27
27
|
logger.debug('[Reporter] Received a response')
|
28
|
+
return if event&.cs__is_a?(Contrast::Agent::Reporting::Finding)
|
28
29
|
return unless analyze_response?(response)
|
29
30
|
|
30
31
|
# Handle the response body and obtain server_features or app_settings
|
@@ -14,7 +14,6 @@ module Contrast
|
|
14
14
|
include Contrast::Agent::Reporting::NgResponseExtractor
|
15
15
|
include Contrast::Agent::Reporting::ResponseExtractor
|
16
16
|
|
17
|
-
ANALYZE_WHEN = %w[200 204].cs__freeze
|
18
17
|
ERROR_CODES = {
|
19
18
|
message_not_sent: '400',
|
20
19
|
access_forbidden: '401',
|
@@ -112,11 +111,10 @@ module Contrast
|
|
112
111
|
# used for in observed routes message.
|
113
112
|
return false unless response && (response_code = response&.code)
|
114
113
|
|
115
|
-
# We still need to check the response code even if we are not analyzing it, since the 304 code does not
|
116
|
-
# contain settings to be extracted but we still need to know for the diagnostics. Do not move this bellow
|
117
|
-
# the ANALYZE_WHEN check.
|
118
114
|
@_last_response_code = response_code
|
119
|
-
return true if
|
115
|
+
return true if response_code == '200'
|
116
|
+
return false if response_code == '204'
|
117
|
+
return false if response_code == '304'
|
120
118
|
|
121
119
|
handle_error(response) if ERROR_CODES.value?(response_code) && response&.body
|
122
120
|
# There was error, so analyze the Error and nothing more.
|
@@ -267,7 +265,7 @@ module Contrast
|
|
267
265
|
# @return response [Contrast::Agent::Reporting::Response]
|
268
266
|
def convert_response response, event
|
269
267
|
response_body = response&.body
|
270
|
-
return unless response_body
|
268
|
+
return unless response_body && !response_body.blank?
|
271
269
|
|
272
270
|
response_data = Contrast::Utils::Json.parse(response_body, deep_symbolize: true)
|
273
271
|
return unless response_data.cs__is_a?(Hash)
|
@@ -180,7 +180,7 @@ module Contrast
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
|
183
|
-
# returns or
|
183
|
+
# returns or generates the hash checksum for the request
|
184
184
|
#
|
185
185
|
# @return @_hash_id [String] Contrast::Utils::HashDigest generated string checksum
|
186
186
|
def hash_id
|
@@ -15,7 +15,6 @@ module Contrast
|
|
15
15
|
class HashDigest < Digest::Class
|
16
16
|
include Digest::Instance
|
17
17
|
extend Contrast::Utils::HashDigestExtend
|
18
|
-
CONTENT_LENGTH_HEADER = 'Content-Length'
|
19
18
|
CHARS = %w[a b c d e f g].cs__freeze
|
20
19
|
CRYPTO_RULES = %w[crypto-bad-ciphers crypto-bad-mac].cs__freeze
|
21
20
|
CONFIG_PATH_KEY = 'path'
|
@@ -34,8 +33,6 @@ module Contrast
|
|
34
33
|
#
|
35
34
|
# @param finding [Contrast::Agent::Reporting::Finding] finding to be reported
|
36
35
|
# @param request [Contrast::Agent::Request] our wrapper around the Rack::Request.
|
37
|
-
# @return checksum [Integer, nil] returns nil if there is no request context or tracking
|
38
|
-
# is disabled.
|
39
36
|
def update_on_request finding, request
|
40
37
|
context = Contrast::Agent::REQUEST_TRACKER.current
|
41
38
|
return unless context || ::Contrast::ASSESS.non_request_tracking?
|
@@ -58,7 +55,6 @@ module Contrast
|
|
58
55
|
# Update to CRC checksum the event source name and source type.
|
59
56
|
#
|
60
57
|
# @param events [Array<Contrast::Agent::Reporting::FindingEvent>]
|
61
|
-
# @return checksum [Integer, nil] returns nil if there is no events
|
62
58
|
def update_on_sources events
|
63
59
|
events.each do |event|
|
64
60
|
event.event_sources.each do |source|
|
@@ -68,22 +64,12 @@ module Contrast
|
|
68
64
|
end
|
69
65
|
end
|
70
66
|
|
71
|
-
# This method converts and integer value for length into a string value
|
72
|
-
# that we can hash on, based on the logarithmic value of the length, and
|
73
|
-
# updates the current hash with that value.
|
74
|
-
# @param chr [Numeric] the length to translate
|
75
|
-
def update_on_content_length chr
|
76
|
-
update(CHARS[Math.log10(chr.to_s.length).to_i] || CHARS[-1])
|
77
|
-
end
|
78
|
-
|
79
67
|
# Converts given string to CRC checksum. CRC32 checksum ensures that If error
|
80
68
|
# of a single bit occurs, the CRC checksum will fail, regardless of any other
|
81
69
|
# property of the transmitted data, including its length. Called several times
|
82
70
|
# with previous CRC to recalculate the new output.
|
83
71
|
#
|
84
72
|
# @param str [String]
|
85
|
-
# @return @crc32 [Integer, nil] updated value of crc 32 bit integer checksum or
|
86
|
-
# nil if passed string is nil or empty
|
87
73
|
def update str
|
88
74
|
return unless str
|
89
75
|
|
@@ -17,7 +17,7 @@ module Contrast
|
|
17
17
|
# param names and content length to CRC checksum and returns string representation
|
18
18
|
#
|
19
19
|
# @param request [Contrast::Agent::Request] our wrapper around the Rack::Request.
|
20
|
-
# @return
|
20
|
+
# @return [String] String representation of CRC32 checksum
|
21
21
|
def generate_request_hash request
|
22
22
|
hash = new
|
23
23
|
hash.update(request.request_method)
|
@@ -25,8 +25,6 @@ module Contrast
|
|
25
25
|
request.parameters.each_key do |name|
|
26
26
|
hash.update(name)
|
27
27
|
end
|
28
|
-
cl = request.headers[Contrast::Utils::HashDigest::CONTENT_LENGTH_HEADER]
|
29
|
-
hash.update_on_content_length(cl) if cl
|
30
28
|
hash.finish
|
31
29
|
end
|
32
30
|
|
@@ -37,7 +35,7 @@ module Contrast
|
|
37
35
|
# @param finding [Contrast::Agent::Reporting::Finding] to be reported
|
38
36
|
# @param source [Object] the source of the Trigger Event
|
39
37
|
# @param request [Contrast::Agent::Request] our wrapper around the Rack::Request.
|
40
|
-
# @return
|
38
|
+
# @return [String] String representation of CRC32 checksum
|
41
39
|
def generate_event_hash finding, source, request
|
42
40
|
return generate_dataflow_hash(finding, request) if finding.events.length.to_i > 1
|
43
41
|
|
@@ -51,7 +49,7 @@ module Contrast
|
|
51
49
|
# to CRC32 checksum and returns string representation to be appended to Contrast::Api::Dtm::Finding
|
52
50
|
#
|
53
51
|
# @param finding [Contrast::Agent::Reporting::Finding] to be reported
|
54
|
-
# @return
|
52
|
+
# @return [String] String representation of CRC32 checksum.
|
55
53
|
def generate_config_hash finding
|
56
54
|
hash = new
|
57
55
|
hash.update(finding.rule_id)
|
@@ -80,6 +78,19 @@ module Contrast
|
|
80
78
|
hash.finish
|
81
79
|
end
|
82
80
|
|
81
|
+
# Generates the hash checksum for response scanning. Converts the rule_id and request to CRC32 checksum and
|
82
|
+
# returns string representation.
|
83
|
+
#
|
84
|
+
# @param finding [Contrast::Agent::Reporting::Finding] to be reported
|
85
|
+
# # @param request [Contrast::Agent::Request]
|
86
|
+
# @return [String] String representation of CRC32 checksum.
|
87
|
+
def generate_response_hash finding, request
|
88
|
+
hash = new
|
89
|
+
hash.update(finding.rule_id)
|
90
|
+
hash.update_on_request(finding, request)
|
91
|
+
hash.finish
|
92
|
+
end
|
93
|
+
|
83
94
|
private
|
84
95
|
|
85
96
|
# Generates the hash checksum for crypto(crypto-bad-ciphers, crypto-bad-mac) rules.
|
data/lib/contrast/utils/json.rb
CHANGED
@@ -14,7 +14,7 @@ module Contrast
|
|
14
14
|
|
15
15
|
# Add any known cases where parsing error might arise from older json parser:
|
16
16
|
# @return [Array<String>]
|
17
|
-
SPECIAL_CASES = ["\"\"", "\"0\""].cs__freeze # rubocop:disable Style/StringLiterals
|
17
|
+
SPECIAL_CASES = [nil, "", "\"\"", "\"0\""].cs__freeze # rubocop:disable Style/StringLiterals
|
18
18
|
|
19
19
|
# Parses a string using JSON.parser. This method is used instead of standard JSON.parse to
|
20
20
|
# support older versions of json gem => not supporting key-value second parameter, which is
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contrast-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.6.
|
4
|
+
version: 7.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ruby@contrastsecurity.com
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -1395,7 +1395,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1395
1395
|
- !ruby/object:Gem::Version
|
1396
1396
|
version: '0'
|
1397
1397
|
requirements: []
|
1398
|
-
rubygems_version: 3.3.
|
1398
|
+
rubygems_version: 3.3.27
|
1399
1399
|
signing_key:
|
1400
1400
|
specification_version: 4
|
1401
1401
|
summary: Contrast Security's agent for rack-based applications.
|