contrast-agent 6.8.0 → 6.9.0
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/policy/trigger_method.rb +1 -1
- data/lib/contrast/agent/assess/property/evented.rb +11 -11
- data/lib/contrast/agent/assess.rb +0 -1
- data/lib/contrast/agent/excluder.rb +1 -1
- data/lib/contrast/agent/middleware.rb +8 -2
- data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +116 -0
- data/lib/contrast/agent/protect/rule/base.rb +2 -2
- data/lib/contrast/agent/protect/rule/bot_blocker.rb +1 -1
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +8 -7
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +0 -5
- data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +0 -5
- data/lib/contrast/agent/protect/rule/path_traversal.rb +4 -3
- data/lib/contrast/agent/protect/rule/sqli.rb +4 -3
- data/lib/contrast/agent/protect/rule/xss.rb +1 -0
- data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +1 -1
- data/lib/contrast/agent/reporting/report.rb +1 -0
- data/lib/contrast/agent/reporting/reporter.rb +34 -0
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +3 -9
- data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +12 -7
- data/lib/contrast/agent/reporting/reporting_events/application_inventory_activity.rb +6 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +2 -2
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +239 -93
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -23
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +10 -9
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -0
- data/lib/contrast/agent/reporting/reporting_events/server_reporting_event.rb +8 -0
- data/lib/contrast/agent/reporting/reporting_events/server_settings.rb +40 -0
- data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +6 -0
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +43 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +8 -4
- data/lib/contrast/agent/reporting/reporting_utilities/response_extractor.rb +58 -4
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +4 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +76 -16
- data/lib/contrast/agent/reporting/server_settings_worker.rb +44 -0
- data/lib/contrast/agent/reporting/settings/assess_server_feature.rb +14 -2
- data/lib/contrast/agent/reporting/settings/helpers.rb +7 -0
- data/lib/contrast/agent/reporting/settings/protect_server_feature.rb +39 -2
- data/lib/contrast/agent/reporting/settings/rule_definition.rb +3 -0
- data/lib/contrast/agent/reporting/settings/security_logger.rb +77 -0
- data/lib/contrast/agent/reporting/settings/server_features.rb +9 -0
- data/lib/contrast/agent/reporting/settings/syslog.rb +34 -5
- data/lib/contrast/agent/request.rb +1 -0
- data/lib/contrast/agent/request_handler.rb +5 -10
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +1 -1
- data/lib/contrast/agent/thread_watcher.rb +35 -1
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +6 -0
- data/lib/contrast/api/communication/connection_status.rb +15 -0
- data/lib/contrast/components/agent.rb +34 -0
- data/lib/contrast/components/api.rb +23 -0
- data/lib/contrast/components/app_context.rb +23 -3
- data/lib/contrast/components/assess.rb +34 -4
- data/lib/contrast/components/assess_rules.rb +18 -0
- data/lib/contrast/components/base.rb +40 -0
- data/lib/contrast/components/config/sources.rb +95 -0
- data/lib/contrast/components/config.rb +18 -1
- data/lib/contrast/components/heap_dump.rb +10 -0
- data/lib/contrast/components/inventory.rb +15 -2
- data/lib/contrast/components/logger.rb +18 -0
- data/lib/contrast/components/polling.rb +36 -0
- data/lib/contrast/components/protect.rb +48 -1
- data/lib/contrast/components/ruby_component.rb +15 -0
- data/lib/contrast/components/sampling.rb +70 -13
- data/lib/contrast/components/security_logger.rb +13 -0
- data/lib/contrast/components/settings.rb +74 -7
- data/lib/contrast/config/certification_configuration.rb +14 -0
- data/lib/contrast/config/config.rb +46 -0
- data/lib/contrast/config/diagnostics.rb +114 -0
- data/lib/contrast/config/diagnostics_tools.rb +98 -0
- data/lib/contrast/config/effective_config.rb +65 -0
- data/lib/contrast/config/effective_config_value.rb +32 -0
- data/lib/contrast/config/exception_configuration.rb +12 -0
- data/lib/contrast/config/protect_rule_configuration.rb +1 -1
- data/lib/contrast/config/protect_rules_configuration.rb +8 -7
- data/lib/contrast/config/request_audit_configuration.rb +13 -0
- data/lib/contrast/config/server_configuration.rb +41 -2
- data/lib/contrast/configuration.rb +28 -2
- data/lib/contrast/extension/assess/erb.rb +1 -1
- data/lib/contrast/utils/assess/event_limit_utils.rb +31 -9
- data/lib/contrast/utils/assess/trigger_method_utils.rb +5 -4
- data/lib/contrast/utils/hash_digest.rb +2 -2
- data/lib/contrast/utils/input_classification_base.rb +1 -2
- data/lib/contrast/utils/reporting/application_activity_batch_utils.rb +81 -0
- data/lib/contrast/utils/routes_sent.rb +60 -0
- data/lib/contrast/utils/telemetry_client.rb +1 -2
- data/lib/contrast/utils/timer.rb +16 -0
- data/lib/contrast.rb +3 -1
- data/ruby-agent.gemspec +5 -1
- metadata +29 -20
- data/lib/contrast/agent/assess/contrast_event.rb +0 -157
- data/lib/contrast/agent/assess/events/event_factory.rb +0 -34
- data/lib/contrast/agent/assess/events/source_event.rb +0 -46
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -36
|
@@ -1,157 +0,0 @@
|
|
|
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/utils/assess/tracking_util'
|
|
5
|
-
require 'contrast/utils/class_util'
|
|
6
|
-
require 'contrast/utils/duck_utils'
|
|
7
|
-
require 'contrast/utils/object_share'
|
|
8
|
-
require 'contrast/utils/stack_trace_utils'
|
|
9
|
-
require 'contrast/utils/string_utils'
|
|
10
|
-
require 'contrast/utils/timer'
|
|
11
|
-
require 'contrast/agent/assess/contrast_object'
|
|
12
|
-
require 'contrast/agent/reporting/reporting_events/finding_event'
|
|
13
|
-
|
|
14
|
-
module Contrast
|
|
15
|
-
module Agent
|
|
16
|
-
module Assess
|
|
17
|
-
# This class holds the data about an event in the application We'll use it to build an event that TeamServer can
|
|
18
|
-
# consume if the object to which this event belongs ends in a trigger.
|
|
19
|
-
class ContrastEvent
|
|
20
|
-
# @return [Integer] the atomic id of this event
|
|
21
|
-
attr_reader :event_id
|
|
22
|
-
# @return [Contrast::Agent::Assess::Policy::PolicyNode] the node that governs this event.
|
|
23
|
-
attr_reader :policy_node
|
|
24
|
-
# @return [Array<String>] the execution stack at the time the method for this event was invoked
|
|
25
|
-
attr_reader :stack_trace
|
|
26
|
-
# @return [Integer] the time, in epoch ms, when this event was created
|
|
27
|
-
attr_reader :time
|
|
28
|
-
# @return [Integer] the object id of the thread on which this event was generated
|
|
29
|
-
attr_reader :thread
|
|
30
|
-
# @return [Contrast::Agent::Assess::ContrastObject] the safe representation of the Object on which the method
|
|
31
|
-
# was invoked
|
|
32
|
-
attr_reader :object
|
|
33
|
-
# @return [Contrast::Agent::Assess::ContrastObject] the safe representation of the Return of the invoked method
|
|
34
|
-
attr_reader :ret
|
|
35
|
-
# @return [Array<Contrast::Agent::Assess::ContrastObject, nil>] the safe representation of the Arguments with
|
|
36
|
-
# which the method was invoked
|
|
37
|
-
attr_reader :args
|
|
38
|
-
# @return [Hash<Contrast::Agent::Assess::Tag>]
|
|
39
|
-
attr_reader :tags
|
|
40
|
-
|
|
41
|
-
# We need this to track the parent id's of events to build up a flow chart of the finding
|
|
42
|
-
@atomic_id = 0
|
|
43
|
-
@atomic_mutex = Mutex.new
|
|
44
|
-
def self.next_atomic_id
|
|
45
|
-
@atomic_mutex.synchronize do
|
|
46
|
-
@atomic_id += 1
|
|
47
|
-
# Rollover things
|
|
48
|
-
rescue StandardError
|
|
49
|
-
@atomic_id = 1
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# @param event_data [Contrast::Agent::Assess::Events::EventData]
|
|
54
|
-
def initialize event_data
|
|
55
|
-
@policy_node = event_data.policy_node
|
|
56
|
-
@time = Contrast::Utils::Timer.now_ms
|
|
57
|
-
@thread = Thread.current.object_id
|
|
58
|
-
|
|
59
|
-
# These methods rely on the above being set. Don't move them!
|
|
60
|
-
@event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id
|
|
61
|
-
@tags = Contrast::Agent::Assess::Tracker.properties(event_data.tagged)&.get_tags
|
|
62
|
-
find_parent_events!(event_data.policy_node, event_data.object, event_data.ret, event_data.args)
|
|
63
|
-
snapshot!(event_data.object, event_data.ret, event_data.args)
|
|
64
|
-
capture_stacktrace!
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# @return [Array<Contrast::Agent::Assess::ContrastEvent>]
|
|
68
|
-
def parent_events
|
|
69
|
-
@_parent_events ||= []
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
private
|
|
73
|
-
|
|
74
|
-
# Parent events are the events of all the sources of this event which were tracked prior to this event
|
|
75
|
-
# occurring. Depending on which, if any of the sources were tracked, there may be more than one parent.
|
|
76
|
-
#
|
|
77
|
-
# All events except for [Contrast::Agent::Assess::Events::SourceEvent] will have at least one parent.
|
|
78
|
-
#
|
|
79
|
-
# We set those events to this event's instance variables.
|
|
80
|
-
#
|
|
81
|
-
# @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode] the node that governs this event.
|
|
82
|
-
# @param object [Object] the Object on which the method was invoked
|
|
83
|
-
# @param ret [Object] the Return of the invoked method
|
|
84
|
-
# @param args [Array<Object>] the Arguments with which the method was invoked
|
|
85
|
-
def find_parent_events! policy_node, object, ret, args
|
|
86
|
-
policy_node.sources.each do |source_marker|
|
|
87
|
-
source = value_of_source(source_marker, object, ret, args)
|
|
88
|
-
next unless source
|
|
89
|
-
|
|
90
|
-
event = Contrast::Agent::Assess::Tracker.properties(source)&.event
|
|
91
|
-
parent_events << event if event
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# @param source [String] the marker for the source type
|
|
96
|
-
# @param object [Object] the Object on which the method was invoked
|
|
97
|
-
# @param ret [Object] the Return of the invoked method
|
|
98
|
-
# @param args [Array<Object>] the Arguments with which the method was invoked
|
|
99
|
-
# @return [Object,nil] the literal value of the source indicated by the given marker
|
|
100
|
-
def value_of_source source, object, ret, args
|
|
101
|
-
case source
|
|
102
|
-
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
103
|
-
object
|
|
104
|
-
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
105
|
-
ret
|
|
106
|
-
else
|
|
107
|
-
args[source]
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
# Everything* is mutable in Ruby. As such, to ensure we can accurately report the application state at the time
|
|
112
|
-
# of this method's invocation, we have to snapshot the given values, making safe representations of them for
|
|
113
|
-
# our later use. We set those safe values to this event's instance variables.
|
|
114
|
-
#
|
|
115
|
-
# @param object [Object] the Object on which the method was invoked
|
|
116
|
-
# @param ret [Object] the Return of the invoked method
|
|
117
|
-
# @param args [Array<Object>] the Arguments with which the method was invoked
|
|
118
|
-
def snapshot! object, ret, args
|
|
119
|
-
@object = Contrast::Agent::Assess::ContrastObject.new(object) if object
|
|
120
|
-
@ret = Contrast::Agent::Assess::ContrastObject.new(ret) if ret
|
|
121
|
-
@args = safe_args_representation(args)
|
|
122
|
-
self
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# Given an array of arguments, copy them into a safe, meaning String, format that we can use to send to SR and
|
|
126
|
-
# TS for rendering.
|
|
127
|
-
#
|
|
128
|
-
# @param args [Array<Object>] the arguments to translate
|
|
129
|
-
# @return [Array<Contrast::Agent::Assess::ContrastObject>] the String forms of those Objects, as determined by
|
|
130
|
-
# Contrast::Utils::ClassUtil.to_contrast_string
|
|
131
|
-
def safe_args_representation args
|
|
132
|
-
return unless args
|
|
133
|
-
return Contrast::Utils::ObjectShare::EMPTY_ARRAY if args.empty?
|
|
134
|
-
|
|
135
|
-
args.map { |arg| arg ? Contrast::Agent::Assess::ContrastObject.new(arg) : nil }
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Capture stack traces only as configured. We'll use this to grab the start of the call stack as if the
|
|
139
|
-
# instrumented method were the caller. This means we'll start at the entry just after the first block of
|
|
140
|
-
# Contrast code.
|
|
141
|
-
def capture_stacktrace!
|
|
142
|
-
# If we're configured to not capture the stacktrace, usually for performance reasons, then don't and return an
|
|
143
|
-
# empty array instead
|
|
144
|
-
unless ::Contrast::ASSESS.capture_stacktrace?(policy_node)
|
|
145
|
-
@stack_trace = Contrast::Utils::ObjectShare::EMPTY_ARRAY
|
|
146
|
-
return
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Otherwise, find where in the stack the application / Ruby code starts
|
|
150
|
-
start = caller(0, 20)&.find_index { |stack| !stack.include?('/lib/contrast') }
|
|
151
|
-
# And then use that to build out the reported stacktrace, or a fallback if we couldn't find it.
|
|
152
|
-
@stack_trace = start ? caller(start + 1, 20) : caller(20, 20)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
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/assess/contrast_event'
|
|
5
|
-
require 'contrast/agent/assess/events/source_event'
|
|
6
|
-
require 'contrast/agent/assess/events/event_data'
|
|
7
|
-
|
|
8
|
-
module Contrast
|
|
9
|
-
module Agent
|
|
10
|
-
module Assess
|
|
11
|
-
module Events
|
|
12
|
-
# This module returns the event type appropriate to the given Node
|
|
13
|
-
module EventFactory
|
|
14
|
-
# This method returns the event type appropriate to the given Node
|
|
15
|
-
#
|
|
16
|
-
# @param event_data [Contrast::Agent::Assess::Events::EventData]
|
|
17
|
-
# @param source_type [String] the type of this source, from the
|
|
18
|
-
# source_node, or a KEY_TYPE if invoked for a map,
|
|
19
|
-
# @param source_name [String, nil] the name of this source, i.e.
|
|
20
|
-
# the key used to accessed if from a map or nil if a type like,
|
|
21
|
-
# @return [Contrast::Agent::Assess::Events::SourceEvent, Contrast::Agent::Assess::ContrastEvent]
|
|
22
|
-
def self.build event_data, source_type = nil, source_name = nil
|
|
23
|
-
case event_data.policy_node
|
|
24
|
-
when Contrast::Agent::Assess::Policy::SourceNode
|
|
25
|
-
Contrast::Agent::Assess::Events::SourceEvent.new(event_data, source_type, source_name)
|
|
26
|
-
when Contrast::Agent::Assess::Policy::PolicyNode
|
|
27
|
-
Contrast::Agent::Assess::ContrastEvent.new(event_data)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
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/assess/contrast_event'
|
|
5
|
-
require 'contrast/agent/reporting/reporting_events/finding_event'
|
|
6
|
-
require 'contrast/agent/reporting/reporting_events/finding_event_source'
|
|
7
|
-
require 'contrast/utils/string_utils'
|
|
8
|
-
|
|
9
|
-
module Contrast
|
|
10
|
-
module Agent
|
|
11
|
-
module Assess
|
|
12
|
-
module Events
|
|
13
|
-
# This class holds the data about an event in the application. We'll use it to build an event that TeamServer
|
|
14
|
-
# can consume if the object to which this event belongs ends in a trigger.
|
|
15
|
-
class SourceEvent < Contrast::Agent::Assess::ContrastEvent
|
|
16
|
-
# @return [Contrast::Agent::Request] our wrapper around the Rack::Request at the time this source
|
|
17
|
-
# was created
|
|
18
|
-
attr_reader :request
|
|
19
|
-
# @return [String] the name of the source if it comes from a map-like entity
|
|
20
|
-
attr_reader :source_name
|
|
21
|
-
# @return [String] the TeamServer understood type of source; i.e. parameter
|
|
22
|
-
attr_reader :source_type
|
|
23
|
-
# @return [Contrast::Agent::Reporting::FindingEventSource] the source of this trace
|
|
24
|
-
attr_reader :event_source
|
|
25
|
-
|
|
26
|
-
# @param event_data [Contrast::Agent::Assess::Events::EventData]
|
|
27
|
-
# @param source_type [String] the type of this source, from the source_node, or a KEY_TYPE if invoked for a
|
|
28
|
-
# Hash
|
|
29
|
-
# @param source_name [String, nil] the name of this source, i.e. the key used to accessed if from a Hash or
|
|
30
|
-
# nil if a type like
|
|
31
|
-
def initialize event_data, source_type = nil, source_name = nil
|
|
32
|
-
super(event_data)
|
|
33
|
-
@source_type = Contrast::Utils::StringUtils.force_utf8(source_type)
|
|
34
|
-
@source_name = Contrast::Utils::StringUtils.force_utf8(source_name)
|
|
35
|
-
@event_source = Contrast::Agent::Reporting::FindingEventSource.new(@source_type, @source_name)
|
|
36
|
-
@request = Contrast::Agent::REQUEST_TRACKER.current&.request
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def parent_events
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
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/reporting_events/server_reporting_event'
|
|
5
|
-
|
|
6
|
-
module Contrast
|
|
7
|
-
module Agent
|
|
8
|
-
module Reporting
|
|
9
|
-
# This class will initialize empty ServerActivity body to be send to TS. The server activity endpoint records
|
|
10
|
-
# actions taken on the server or process as a whole. It currently only reports the number of times a defensive
|
|
11
|
-
# action was taken and is most likely not populated by most agents. The main purpose of sending this message is
|
|
12
|
-
# for its response, which contains any updated server feature settings from TeamServer. The new Server Settings
|
|
13
|
-
# endpoint should let us remove this.
|
|
14
|
-
class ServerActivity < Contrast::Agent::Reporting::ServerReportingEvent
|
|
15
|
-
def initialize
|
|
16
|
-
@event_method = :PUT
|
|
17
|
-
@event_endpoint = "#{ Contrast::API.api_url }/api/ng/activity/server"
|
|
18
|
-
super
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def file_name
|
|
22
|
-
'server-activity'
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Convert the instance variables on the class, and other information, into the identifiers required for
|
|
26
|
-
# TeamServer to process the JSON form of this message.
|
|
27
|
-
#
|
|
28
|
-
# @return [Hash]
|
|
29
|
-
# @raise [ArgumentError]
|
|
30
|
-
def to_controlled_hash
|
|
31
|
-
{ lastUpdate: since_last_update }
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|