contrast-agent 4.0.0 → 4.3.2
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/Rakefile +1 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +22 -10
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +4 -3
- data/lib/contrast/agent/assess/contrast_event.rb +49 -130
- data/lib/contrast/agent/assess/contrast_object.rb +51 -0
- data/lib/contrast/agent/assess/events/source_event.rb +4 -9
- data/lib/contrast/agent/assess/policy/patcher.rb +4 -3
- data/lib/contrast/agent/assess/policy/policy_node.rb +31 -59
- data/lib/contrast/agent/assess/policy/preshift.rb +3 -3
- data/lib/contrast/agent/assess/policy/propagation_method.rb +13 -19
- data/lib/contrast/agent/assess/policy/propagation_node.rb +12 -24
- data/lib/contrast/agent/assess/policy/propagator/append.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/center.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -3
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +2 -4
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -2
- data/lib/contrast/agent/assess/policy/propagator/select.rb +3 -4
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -4
- data/lib/contrast/agent/assess/policy/propagator/split.rb +73 -117
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +11 -11
- data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -7
- data/lib/contrast/agent/assess/policy/source_method.rb +2 -14
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +5 -8
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
- data/lib/contrast/agent/assess/property/tagged.rb +21 -15
- data/lib/contrast/agent/assess/rule/redos.rb +1 -1
- data/lib/contrast/agent/assess/tracker.rb +16 -18
- data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +7 -0
- data/lib/contrast/agent/middleware.rb +50 -1
- data/lib/contrast/agent/patching/policy/method_policy.rb +1 -1
- data/lib/contrast/agent/patching/policy/patch.rb +6 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +47 -1
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +53 -0
- data/lib/contrast/agent/protect/rule/base.rb +63 -14
- data/lib/contrast/agent/protect/rule/cmd_injection.rb +12 -28
- data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -4
- data/lib/contrast/agent/protect/rule/deserialization.rb +4 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +3 -3
- data/lib/contrast/agent/protect/rule/sqli.rb +3 -3
- data/lib/contrast/agent/protect/rule/xxe.rb +32 -11
- data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +10 -6
- data/lib/contrast/agent/reaction_processor.rb +1 -1
- data/lib/contrast/agent/response.rb +5 -5
- data/lib/contrast/agent/rewriter.rb +3 -3
- data/lib/contrast/agent/scope.rb +81 -55
- data/lib/contrast/agent/static_analysis.rb +13 -7
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api/decorators/library.rb +1 -0
- data/lib/contrast/api/decorators/library_usage_update.rb +1 -0
- data/lib/contrast/api/decorators/trace_event.rb +19 -31
- data/lib/contrast/api/decorators/trace_event_object.rb +11 -3
- data/lib/contrast/api/decorators/trace_event_signature.rb +27 -5
- data/lib/contrast/api/decorators/user_input.rb +2 -1
- data/lib/contrast/common_agent_configuration.rb +2 -1
- data/lib/contrast/components/assess.rb +36 -0
- data/lib/contrast/components/interface.rb +5 -3
- data/lib/contrast/components/scope.rb +72 -6
- data/lib/contrast/components/settings.rb +6 -3
- data/lib/contrast/config/assess_configuration.rb +2 -1
- data/lib/contrast/extension/assess/array.rb +2 -3
- data/lib/contrast/extension/assess/erb.rb +1 -3
- data/lib/contrast/extension/assess/exec_trigger.rb +1 -4
- data/lib/contrast/extension/assess/fiber.rb +2 -3
- data/lib/contrast/extension/assess/hash.rb +4 -2
- data/lib/contrast/extension/assess/kernel.rb +1 -2
- data/lib/contrast/extension/assess/marshal.rb +34 -26
- data/lib/contrast/extension/assess/regexp.rb +3 -8
- data/lib/contrast/extension/assess/string.rb +1 -2
- data/lib/contrast/framework/base_support.rb +51 -53
- data/lib/contrast/framework/manager.rb +3 -2
- data/lib/contrast/framework/rack/patch/session_cookie.rb +2 -2
- data/lib/contrast/framework/rack/support.rb +2 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +1 -1
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +1 -1
- data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +1 -1
- data/lib/contrast/framework/rails/support.rb +2 -1
- data/lib/contrast/framework/sinatra/support.rb +3 -2
- data/lib/contrast/logger/application.rb +0 -3
- data/lib/contrast/utils/duck_utils.rb +1 -1
- data/lib/contrast/utils/heap_dump_util.rb +1 -1
- data/lib/contrast/utils/object_share.rb +3 -3
- data/lib/contrast/utils/preflight_util.rb +1 -1
- data/lib/contrast/utils/prevent_serialization.rb +1 -1
- data/lib/contrast/utils/resource_loader.rb +1 -1
- data/lib/contrast/utils/sha256_builder.rb +2 -2
- data/lib/contrast/utils/string_utils.rb +1 -1
- data/lib/contrast/utils/tag_util.rb +9 -13
- data/resources/assess/policy.json +9 -9
- data/resources/deadzone/policy.json +150 -0
- data/resources/protect/policy.json +12 -0
- data/ruby-agent.gemspec +10 -6
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +69 -25
|
@@ -18,12 +18,16 @@ module Contrast
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def external_entity?
|
|
21
|
-
@_external_entity
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
if @_external_entity.nil?
|
|
22
|
+
@_external_entity ||= if @system_id
|
|
23
|
+
external_id?(@system_id)
|
|
24
|
+
elsif @public_id
|
|
25
|
+
external_id?(@public_id)
|
|
26
|
+
else
|
|
27
|
+
false
|
|
28
|
+
end
|
|
26
29
|
end
|
|
30
|
+
@_external_entity
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
# <!ENTITY name SYSTEM "URI">
|
|
@@ -48,7 +52,7 @@ module Contrast
|
|
|
48
52
|
UP_DIR_LINUX = '../'
|
|
49
53
|
UP_DIR_WIN = '..\\'
|
|
50
54
|
# we only use this against lowercase strings, removed A-Z for speed
|
|
51
|
-
FILE_PATTERN_WINDOWS =
|
|
55
|
+
FILE_PATTERN_WINDOWS = /^\\*[a-z]{1,3}:.*/.cs__freeze
|
|
52
56
|
def external_id? entity_id
|
|
53
57
|
return false unless entity_id
|
|
54
58
|
|
|
@@ -22,7 +22,7 @@ module Contrast
|
|
|
22
22
|
# @param application_settings [Contrast::Api::Settings::ApplicationSettings]
|
|
23
23
|
# those settings which the Service has relayed from TeamServer.
|
|
24
24
|
def self.process application_settings
|
|
25
|
-
return
|
|
25
|
+
return unless application_settings&.reactions&.any?
|
|
26
26
|
|
|
27
27
|
application_settings.reactions.each do |reaction|
|
|
28
28
|
# the enums are all uppercase, we need to downcase them before attempting to log
|
|
@@ -118,16 +118,16 @@ module Contrast
|
|
|
118
118
|
# holds, wraps, or is the body of the Response
|
|
119
119
|
# @return [nil, String] the content of the body
|
|
120
120
|
def extract_body body
|
|
121
|
-
return
|
|
121
|
+
return unless body
|
|
122
122
|
|
|
123
123
|
if defined?(Rack::File) && body.is_a?(Rack::File)
|
|
124
124
|
# not sure what to do in this situation, so don't do anything.
|
|
125
125
|
nil
|
|
126
126
|
elsif body.is_a?(Rack::BodyProxy)
|
|
127
127
|
handle_rack_body_proxy(body)
|
|
128
|
-
elsif defined?(ActionDispatch::Response::RackBody) && body.is_a?(ActionDispatch::Response::RackBody)
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
elsif (defined?(ActionDispatch::Response::RackBody) && body.is_a?(ActionDispatch::Response::RackBody)) ||
|
|
129
|
+
body.is_a?(Rack::Response)
|
|
130
|
+
|
|
131
131
|
extract_body(body.body)
|
|
132
132
|
elsif Contrast::Utils::DuckUtils.quacks_to?(body, :each)
|
|
133
133
|
acc = []
|
|
@@ -152,7 +152,7 @@ module Contrast
|
|
|
152
152
|
end
|
|
153
153
|
|
|
154
154
|
def read_or_string obj
|
|
155
|
-
return
|
|
155
|
+
return unless obj
|
|
156
156
|
|
|
157
157
|
if Contrast::Utils::DuckUtils.quacks_to?(obj, :read)
|
|
158
158
|
tmp = obj.read
|
|
@@ -96,11 +96,11 @@ module Contrast
|
|
|
96
96
|
return unless method_exists?(clazz, method_name, type)
|
|
97
97
|
|
|
98
98
|
method_instance = method_instance(clazz, method_name, type)
|
|
99
|
-
return
|
|
99
|
+
return if method_instance.nil?
|
|
100
100
|
|
|
101
101
|
location = method_instance.source_location
|
|
102
|
-
return
|
|
103
|
-
return
|
|
102
|
+
return unless location_available?(location)
|
|
103
|
+
return if opener.written_from_location?(location)
|
|
104
104
|
|
|
105
105
|
opener.written_from_location!(location)
|
|
106
106
|
opener.source_code(location, method_name)
|
data/lib/contrast/agent/scope.rb
CHANGED
|
@@ -15,67 +15,93 @@ module Contrast
|
|
|
15
15
|
# Instead, we should say "If I'm already doing Contrast things, don't track
|
|
16
16
|
# this"
|
|
17
17
|
class Scope
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# in_monkey_scope?
|
|
25
|
-
# with_monkey_scope { special_monkey_function }
|
|
26
|
-
SCOPE_LIST = %i[contrast deserialization].cs__freeze
|
|
27
|
-
|
|
28
|
-
iv_list = SCOPE_LIST.map { |name| :"@#{ name }_scope" }
|
|
29
|
-
define_method 'initialize' do
|
|
30
|
-
iv_list.each do |iv_sym|
|
|
31
|
-
instance_variable_set(iv_sym, 0)
|
|
32
|
-
end
|
|
18
|
+
SCOPE_LIST = %i[contrast deserialization split].cs__freeze
|
|
19
|
+
|
|
20
|
+
def initialize
|
|
21
|
+
@contrast_scope = 0
|
|
22
|
+
@deserialization_scope = 0
|
|
23
|
+
@split_scope = 0
|
|
33
24
|
end
|
|
34
25
|
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
def in_contrast_scope?
|
|
27
|
+
@contrast_scope.positive?
|
|
28
|
+
end
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
def in_deserialization_scope?
|
|
31
|
+
@deserialization_scope.positive?
|
|
32
|
+
end
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
instance_variable_set(iv_sym, level + 1)
|
|
46
|
-
end
|
|
34
|
+
def in_split_scope?
|
|
35
|
+
@split_scope.positive?
|
|
36
|
+
end
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
# every exit/enter pair (regardless of series)
|
|
52
|
-
# should cancel each other out.
|
|
53
|
-
#
|
|
54
|
-
# so we prefer this sequence:
|
|
55
|
-
# scope = 0
|
|
56
|
-
# exit = -1
|
|
57
|
-
# enter = 0
|
|
58
|
-
# enter = 1
|
|
59
|
-
# exit = 0
|
|
60
|
-
# scope = 0
|
|
61
|
-
#
|
|
62
|
-
# over this sequence:
|
|
63
|
-
# scope = 0
|
|
64
|
-
# exit = 0
|
|
65
|
-
# enter = 1
|
|
66
|
-
# enter = 2
|
|
67
|
-
# exit = 1
|
|
68
|
-
# scope = 1
|
|
69
|
-
level = instance_variable_get(iv_sym)
|
|
70
|
-
instance_variable_set(iv_sym, level - 1)
|
|
71
|
-
end
|
|
38
|
+
def enter_contrast_scope!
|
|
39
|
+
@contrast_scope += 1
|
|
40
|
+
end
|
|
72
41
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
42
|
+
def enter_deserialization_scope!
|
|
43
|
+
@deserialization_scope += 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def enter_split_scope!
|
|
47
|
+
@split_scope += 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def split_scope_depth
|
|
51
|
+
@split_scope
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Scope Exits...
|
|
55
|
+
# by design, can go below zero.
|
|
56
|
+
# every exit/enter pair (regardless of series)
|
|
57
|
+
# should cancel each other out.
|
|
58
|
+
#
|
|
59
|
+
# so we prefer this sequence:
|
|
60
|
+
# scope = 0
|
|
61
|
+
# exit = -1
|
|
62
|
+
# enter = 0
|
|
63
|
+
# enter = 1
|
|
64
|
+
# exit = 0
|
|
65
|
+
# scope = 0
|
|
66
|
+
#
|
|
67
|
+
# over this sequence:
|
|
68
|
+
# scope = 0
|
|
69
|
+
# exit = 0
|
|
70
|
+
# enter = 1
|
|
71
|
+
# enter = 2
|
|
72
|
+
# exit = 1
|
|
73
|
+
# scope = 1
|
|
74
|
+
def exit_contrast_scope!
|
|
75
|
+
@contrast_scope -= 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def exit_deserialization_scope!
|
|
79
|
+
@deserialization_scope -= 1
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def exit_split_scope!
|
|
83
|
+
@split_scope -= 1
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def with_contrast_scope
|
|
87
|
+
enter_contrast_scope!
|
|
88
|
+
yield
|
|
89
|
+
ensure
|
|
90
|
+
exit_contrast_scope!
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def with_deserialization_scope
|
|
94
|
+
enter_deserialization_scope!
|
|
95
|
+
yield
|
|
96
|
+
ensure
|
|
97
|
+
exit_deserialization_scope!
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def with_split_scope
|
|
101
|
+
enter_split_scope!
|
|
102
|
+
yield
|
|
103
|
+
ensure
|
|
104
|
+
exit_split_scope!
|
|
79
105
|
end
|
|
80
106
|
|
|
81
107
|
# Dynamic versions of the above.
|
|
@@ -17,14 +17,9 @@ module Contrast
|
|
|
17
17
|
# report the already-loaded gems.
|
|
18
18
|
def catchup
|
|
19
19
|
@_catchup ||= begin
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
send_inventory_message
|
|
23
|
-
true
|
|
24
|
-
end
|
|
20
|
+
threaded_analysis!
|
|
21
|
+
true
|
|
25
22
|
end
|
|
26
|
-
rescue StandardError => e
|
|
27
|
-
logger.warn('Unable to run post-initialization static analysis', e)
|
|
28
23
|
end
|
|
29
24
|
|
|
30
25
|
def send_inventory_message
|
|
@@ -35,6 +30,17 @@ module Contrast
|
|
|
35
30
|
Contrast::Utils::InventoryUtil.append_db_config(app_update_msg)
|
|
36
31
|
Contrast::Agent.messaging_queue.send_event_eventually(app_update_msg)
|
|
37
32
|
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def threaded_analysis!
|
|
37
|
+
Contrast::Agent::Thread.new do
|
|
38
|
+
Contrast::Agent::Inventory::DependencyUsageAnalysis.instance.catchup
|
|
39
|
+
send_inventory_message
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
logger.warn('Unable to run post-initialization static analysis', e)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
40
46
|
end
|
|
@@ -15,44 +15,30 @@ module Contrast
|
|
|
15
15
|
|
|
16
16
|
# Wrapper around build_event_object for the args array. Handles
|
|
17
17
|
# tainting the correct argument.
|
|
18
|
-
def build_event_args contrast_event, taint_target
|
|
18
|
+
def build_event_args! contrast_event, taint_target
|
|
19
19
|
contrast_event.args.each_index do |idx|
|
|
20
20
|
truncate_arg = taint_target != idx
|
|
21
21
|
event_arg = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.args[idx], truncate_arg)
|
|
22
22
|
args << event_arg
|
|
23
23
|
end
|
|
24
|
+
self
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
# TeamServer only supports one object's taint ranges at a time.
|
|
27
|
-
#
|
|
28
|
-
|
|
27
|
+
# TeamServer only supports one object's taint ranges at a time. We keep
|
|
28
|
+
# those tags on the event directly, so we just need to convert them to
|
|
29
|
+
# their DTM form in order to report this.
|
|
30
|
+
#
|
|
31
|
+
# @param contrast_event [Contrast::Agent::AssessContrastEvent]
|
|
32
|
+
def build_taint_ranges! contrast_event
|
|
29
33
|
# If there's no taint_target, this isn't a dataflow trace, but a
|
|
30
34
|
# trigger one
|
|
31
|
-
return
|
|
35
|
+
return self unless contrast_event&.tags
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Contrast::Agent::Assess::Tracker.properties(contrast_event.object)
|
|
36
|
-
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
37
|
-
Contrast::Agent::Assess::Tracker.properties(contrast_event.ret)
|
|
38
|
-
else
|
|
39
|
-
target = contrast_event.args[taint_target]
|
|
40
|
-
if target.is_a?(Hash)
|
|
41
|
-
if contrast_event.policy_node&.targets&.any?
|
|
42
|
-
Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.targets[0]])
|
|
43
|
-
else
|
|
44
|
-
Contrast::Agent::Assess::Tracker.properties(target[contrast_event.policy_node.sources[0]])
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
Contrast::Agent::Assess::Tracker.properties(target)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
return unless properties.tracked?
|
|
51
|
-
|
|
52
|
-
self.taint_ranges += properties.tags_to_dtm
|
|
37
|
+
self.taint_ranges += Contrast::Api::Dtm::TraceTaintRange.build_for_event(contrast_event.tags)
|
|
38
|
+
self
|
|
53
39
|
end
|
|
54
40
|
|
|
55
|
-
def build_parent_ids contrast_event
|
|
41
|
+
def build_parent_ids! contrast_event
|
|
56
42
|
contrast_event&.parent_events&.each do |event|
|
|
57
43
|
next unless event
|
|
58
44
|
|
|
@@ -60,12 +46,14 @@ module Contrast
|
|
|
60
46
|
parent.id = event.event_id.to_i
|
|
61
47
|
parent_object_ids << parent
|
|
62
48
|
end
|
|
49
|
+
self
|
|
63
50
|
end
|
|
64
51
|
|
|
65
|
-
def build_stack contrast_event
|
|
52
|
+
def build_stack! contrast_event
|
|
66
53
|
# We delayed doing this as long as possible b/c it's expensive
|
|
67
54
|
stack_dtms = Contrast::Utils::StackTraceUtils.build_assess_stack_array(contrast_event.stack_trace)
|
|
68
55
|
self.stack += stack_dtms
|
|
56
|
+
self
|
|
69
57
|
end
|
|
70
58
|
|
|
71
59
|
# Class methods for TraceEvent
|
|
@@ -85,10 +73,10 @@ module Contrast
|
|
|
85
73
|
event_dtm.object = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.object, truncate_obj)
|
|
86
74
|
truncate_ret = Contrast::Utils::ObjectShare::RETURN_KEY != taint_target
|
|
87
75
|
event_dtm.ret = Contrast::Api::Dtm::TraceEventObject.build(contrast_event.ret, truncate_ret)
|
|
88
|
-
event_dtm.build_event_args(contrast_event, taint_target)
|
|
89
|
-
event_dtm.build_parent_ids(contrast_event)
|
|
90
|
-
event_dtm.build_taint_ranges(contrast_event
|
|
91
|
-
event_dtm.build_stack(contrast_event)
|
|
76
|
+
event_dtm.build_event_args!(contrast_event, taint_target)
|
|
77
|
+
event_dtm.build_parent_ids!(contrast_event)
|
|
78
|
+
event_dtm.build_taint_ranges!(contrast_event)
|
|
79
|
+
event_dtm.build_stack!(contrast_event)
|
|
92
80
|
event_dtm.object_id = contrast_event.event_id.to_i
|
|
93
81
|
event_dtm.signature = Contrast::Api::Dtm::TraceEventSignature.build(contrast_event.ret, contrast_event.policy_node, contrast_event.args)
|
|
94
82
|
event_dtm
|
|
@@ -29,13 +29,21 @@ module Contrast
|
|
|
29
29
|
ELLIPSIS = '...'
|
|
30
30
|
UNTRUNCATED_PORTION_LENGTH = 25
|
|
31
31
|
TRUNCATION_LENGTH = (UNTRUNCATED_PORTION_LENGTH * 2) + ELLIPSIS.length
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
# Convert the given Object into a Contrast::Api::Dtm::TraceEventObject
|
|
34
|
+
#
|
|
35
|
+
# @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil]
|
|
36
|
+
# the thing to convert, if any
|
|
37
|
+
# @param truncate [Boolean] if the converted object can/should be
|
|
38
|
+
# truncated.
|
|
39
|
+
# @return [Contrast::Api::Dtm::TraceEventObject]
|
|
40
|
+
def build contrast_object, truncate
|
|
33
41
|
event_object = new
|
|
34
42
|
with_contrast_scope do
|
|
35
|
-
obj_string = Contrast::Utils::StringUtils.force_utf8(object)
|
|
43
|
+
obj_string = Contrast::Utils::StringUtils.force_utf8(contrast_object&.object)
|
|
36
44
|
obj_string = truncate(obj_string) if truncate && obj_string.length > TRUNCATION_LENGTH
|
|
37
45
|
event_object.value = Base64.encode64(obj_string)
|
|
38
|
-
event_object.tracked =
|
|
46
|
+
event_object.tracked = contrast_object&.tracked?
|
|
39
47
|
end
|
|
40
48
|
event_object
|
|
41
49
|
end
|
|
@@ -17,27 +17,49 @@ module Contrast
|
|
|
17
17
|
|
|
18
18
|
# Class methods for TraceEventSignature
|
|
19
19
|
module ClassMethods
|
|
20
|
+
# Convert the given composites into components that TeamServer can
|
|
21
|
+
# understand in order to build a representation of the method
|
|
22
|
+
# invoked.
|
|
23
|
+
#
|
|
24
|
+
# @param ret_obj [Contrast::Agent::Assess::ContrastObject, nil] the
|
|
25
|
+
# return value of the method call.
|
|
26
|
+
# @param policy_node [Contrast::Agent::Assess::Policy::PolicyNode]
|
|
27
|
+
# the policy which pertains to the method invoked.
|
|
28
|
+
# @param args [Array<Contrast::Agent::Assess::ContrastObject>, nil]
|
|
29
|
+
# @return [Contrast::Api::Dtm::TraceEventSignature]
|
|
20
30
|
def build ret_obj, policy_node, args
|
|
21
31
|
signature = new
|
|
22
|
-
return_type =
|
|
23
|
-
signature.return_type = Contrast::Utils::StringUtils.force_utf8(return_type)
|
|
32
|
+
signature.return_type = Contrast::Utils::StringUtils.force_utf8(type_name(ret_obj))
|
|
24
33
|
signature.class_name = Contrast::Utils::StringUtils.force_utf8(policy_node.class_name)
|
|
25
34
|
signature.method_name = Contrast::Utils::StringUtils.force_utf8(policy_node.method_name)
|
|
26
35
|
if args
|
|
27
36
|
args&.each do |arg|
|
|
28
|
-
|
|
29
|
-
signature.arg_types << Contrast::Utils::StringUtils.force_utf8(arg_type)
|
|
37
|
+
signature.arg_types << Contrast::Utils::StringUtils.force_utf8(type_name(arg))
|
|
30
38
|
end
|
|
31
39
|
end
|
|
32
40
|
signature.constructor = policy_node.method_name == :new
|
|
33
41
|
# if there's a ret, then this method isn't nil. not 100% full proof since you can
|
|
34
42
|
# return nil, but this is the best we've got currently.
|
|
35
|
-
signature.void_method = ret_obj.nil?
|
|
43
|
+
signature.void_method = ret_obj.nil? || ret_obj.object.nil?
|
|
36
44
|
# 8 is STATIC in Java... we have to placate them for now
|
|
37
45
|
# it has been requested that flags be removed since it isn't used
|
|
38
46
|
signature.flags = 8 unless policy_node.instance_method?
|
|
39
47
|
signature
|
|
40
48
|
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# While Ruby signatures do not require neither a return type and can
|
|
53
|
+
# return anything depending on inputs, code paths, etc, nor constant
|
|
54
|
+
# parameter types, TeamServer was designed with strongly typed
|
|
55
|
+
# languages (Java) in mind, so we need types in our signatures.
|
|
56
|
+
#
|
|
57
|
+
# @param contrast_object [Contrast::Agent::Assess::ContrastObject, nil]
|
|
58
|
+
# the object to find the type of
|
|
59
|
+
# @return [String] the name of the module of the ret_obj, or `nil`
|
|
60
|
+
def type_name contrast_object
|
|
61
|
+
contrast_object ? contrast_object.object_type : Contrast::Utils::ObjectShare::NIL_STRING
|
|
62
|
+
end
|
|
41
63
|
end
|
|
42
64
|
end
|
|
43
65
|
end
|