contrast-agent 7.5.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/ext/cs__common/cs__common.c +5 -5
- data/ext/cs__contrast_patch/cs__contrast_patch.c +2 -1
- data/ext/cs__scope/cs__scope.c +6 -5
- data/lib/contrast/agent/assess/events/event_data.rb +11 -2
- data/lib/contrast/agent/assess/finalizers/freeze.rb +1 -0
- data/lib/contrast/agent/assess/finalizers/hash.rb +7 -0
- data/lib/contrast/agent/assess/policy/patcher.rb +2 -0
- data/lib/contrast/agent/assess/policy/policy.rb +4 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +29 -7
- data/lib/contrast/agent/assess/policy/preshift.rb +34 -1
- data/lib/contrast/agent/assess/policy/propagation_method.rb +16 -1
- data/lib/contrast/agent/assess/policy/propagation_node.rb +40 -1
- data/lib/contrast/agent/assess/policy/propagator/append.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +10 -0
- data/lib/contrast/agent/assess/policy/propagator/buffer.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagator/center.rb +14 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +14 -0
- data/lib/contrast/agent/assess/policy/propagator/insert.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +38 -0
- data/lib/contrast/agent/assess/policy/propagator/next.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagator/prepend.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +4 -0
- data/lib/contrast/agent/assess/policy/propagator/replace.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/reverse.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/select.rb +30 -0
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +10 -0
- data/lib/contrast/agent/assess/policy/source_node.rb +5 -1
- data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +4 -0
- data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +16 -0
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +19 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +8 -1
- data/lib/contrast/agent/assess/policy/trigger_node.rb +11 -1
- data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +4 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +6 -0
- data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +6 -0
- data/lib/contrast/agent/assess/rule/response/base_rule.rb +2 -1
- data/lib/contrast/agent/hooks/at_exit_hook.rb +1 -0
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +35 -7
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +8 -2
- data/lib/contrast/agent/reporting/reporting_utilities/reporting_storage.rb +1 -6
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +4 -3
- data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +22 -12
- data/lib/contrast/agent/request/request.rb +1 -1
- data/lib/contrast/agent/request/request_handler.rb +1 -0
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/configuration.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
- data/lib/contrast/utils/middleware_utils.rb +9 -0
- data/lib/contrast/utils/routes_sent.rb +3 -2
- data/lib/contrast.rb +2 -2
- data/resources/assess/policy.json +50 -1
- data/ruby-agent.gemspec +13 -13
- metadata +24 -23
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
|
data/ext/cs__common/cs__common.c
CHANGED
@@ -28,12 +28,12 @@ void patch_via_funchook(void *original_function, void *hook_function) {
|
|
28
28
|
|
29
29
|
void *funchook_lib_handle;
|
30
30
|
void *funchook_reference, *(*funchook_create)(void);
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
/* This variables are used to load the funchook dylib */
|
32
|
+
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
33
|
+
#pragma GCC diagnostic push
|
34
34
|
int prepareResult, (*funchook_prepare)(void *, void **, void *);
|
35
35
|
int installResult, (*funchook_install)(void *, int);
|
36
|
-
|
36
|
+
#pragma GCC diagnostic pop
|
37
37
|
|
38
38
|
funchook_lib_handle =
|
39
39
|
dlopen(StringValueCStr(funchook_path), RTLD_NOW | RTLD_GLOBAL);
|
@@ -198,7 +198,7 @@ extern VALUE contrast_lookout_prepended(VALUE self, VALUE object_name,
|
|
198
198
|
}
|
199
199
|
|
200
200
|
VALUE _contrast_check_prepended(VALUE object, VALUE method_name,
|
201
|
-
|
201
|
+
VALUE is_instance) {
|
202
202
|
VALUE entry, ancestors, entry_methods;
|
203
203
|
VALUE result = Qfalse;
|
204
204
|
VALUE object_idx = Qnil;
|
@@ -107,7 +107,8 @@ VALUE rescue_func(VALUE arg1) {
|
|
107
107
|
*
|
108
108
|
**/
|
109
109
|
VALUE contrast_patch_call_ensure(const VALUE *args) {
|
110
|
-
/* we do not need to ensure that post patch is called if no error was thrown
|
110
|
+
/* we do not need to ensure that post patch is called if no error was thrown
|
111
|
+
*/
|
111
112
|
if (!RTEST(rb_errinfo())) {
|
112
113
|
return Qnil;
|
113
114
|
}
|
data/ext/cs__scope/cs__scope.c
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
|
4
4
|
#include "cs__scope.h"
|
5
5
|
#include "../cs__common/cs__common.h"
|
6
|
+
#include <pthread.h>
|
6
7
|
#include <ruby.h>
|
7
8
|
#include <stdlib.h>
|
8
|
-
#include <pthread.h>
|
9
9
|
|
10
10
|
/*-----------------------------------------
|
11
11
|
| Calls to Contrast modules and classes
|
@@ -161,8 +161,8 @@ VALUE contrast_scope_application_update() {
|
|
161
161
|
return INT2FIX(env_var_set(eVar));
|
162
162
|
}
|
163
163
|
|
164
|
-
/**
|
165
|
-
* @brief Determines if the Contrast Scope should be set with the Trap Context.
|
164
|
+
/**
|
165
|
+
* @brief Determines if the Contrast Scope should be set with the Trap Context.
|
166
166
|
* @return 1 if set, 0 if not set.
|
167
167
|
*/
|
168
168
|
int contrast_scope_with_trap_context() {
|
@@ -556,7 +556,7 @@ VALUE contrast_scope_for_current_ec(VALUE self, VALUE args) {
|
|
556
556
|
* different thread, at once, but since the mutex stays in
|
557
557
|
* the C API context, this might work fine. Still use only
|
558
558
|
* when unusual conditions are met.
|
559
|
-
*
|
559
|
+
*
|
560
560
|
* In addition we could use C mutex lock just in case. Ruby
|
561
561
|
* Threads under the hood are C threads (pthread), so they
|
562
562
|
* should be treated as such. In theory only one thread can
|
@@ -894,7 +894,8 @@ void Init_cs__scope() {
|
|
894
894
|
rb_const_ec = "EXECUTION_CONTEXT";
|
895
895
|
rb_const_ec_keys = "EC_KEYS";
|
896
896
|
c_const_ctr_agent_app_scope = "CONTRAST__AGENT__RUBY__APPLICATION_SCOPE";
|
897
|
-
c_const_ctr_agent_scope_trap_context =
|
897
|
+
c_const_ctr_agent_scope_trap_context =
|
898
|
+
"CONTRAST__AGENT__SCOPE__WITH_TRAP_CONTEXT";
|
898
899
|
|
899
900
|
/* Symbols */
|
900
901
|
rb_sym_scope_mod = rb_intern("Scope");
|
@@ -5,9 +5,18 @@ module Contrast
|
|
5
5
|
module Agent
|
6
6
|
module Assess
|
7
7
|
module Events
|
8
|
-
# this class will gather and build event
|
8
|
+
# this class will gather and build event.
|
9
9
|
class EventData
|
10
|
-
|
10
|
+
# @return [Contrast::Agent::Assess::Policy::PolicyNode, nil] the node that governs this event.
|
11
|
+
attr_reader :policy_node
|
12
|
+
# @return [Object, nil] the Target to which this event pertains.
|
13
|
+
attr_reader :tagged
|
14
|
+
# @return [Object, nil] the Object on which the method was invoked.
|
15
|
+
attr_reader :object
|
16
|
+
# @return [Object, nil] the Return of the invoked method.
|
17
|
+
attr_reader :ret
|
18
|
+
# @return [Array<Object>, nil] the Arguments with which the method was invoked.
|
19
|
+
attr_reader :args
|
11
20
|
|
12
21
|
# Group event data together
|
13
22
|
#
|
@@ -8,6 +8,7 @@ require 'contrast/agent/assess/tracker'
|
|
8
8
|
class Object
|
9
9
|
alias_method :cs__patched_object_freeze, :freeze
|
10
10
|
|
11
|
+
# Applies the the freeze patch and handles the pre-finalizes the object.
|
11
12
|
def freeze
|
12
13
|
Contrast::Agent::Assess::Tracker.pre_freeze(self)
|
13
14
|
cs__patched_object_freeze
|
@@ -16,6 +16,10 @@ module Contrast
|
|
16
16
|
FROZEN_FINALIZED_IDS = Set.new
|
17
17
|
KEEP_AGE = 600_000.cs__freeze # 10 minutes
|
18
18
|
|
19
|
+
# Store the given Object in the Hash, using its __id__ as the key. If the Object is frozen, we need to
|
20
|
+
# pre-finalize it and store its __id__ in our tracking Set.
|
21
|
+
#
|
22
|
+
# @return [Object] the Object stored
|
19
23
|
def []= key, obj
|
20
24
|
return unless obj
|
21
25
|
return unless ::Contrast::AGENT.enabled? && ::Contrast::ASSESS.enabled?
|
@@ -29,6 +33,9 @@ module Contrast
|
|
29
33
|
super(key.__id__, obj)
|
30
34
|
end
|
31
35
|
|
36
|
+
# Retrieves the Object stored in the Hash by its __id__.
|
37
|
+
#
|
38
|
+
# @return [Object, nil] the Object stored.
|
32
39
|
def [] key
|
33
40
|
super(key.__id__)
|
34
41
|
end
|
@@ -34,6 +34,8 @@ module Contrast
|
|
34
34
|
# load. These methods only exist once a module or class eval has been
|
35
35
|
# called. This hook is provided so that patches to those methods can
|
36
36
|
# pass us execution flow once a new method has been made available.
|
37
|
+
#
|
38
|
+
# @param mod [Module]
|
37
39
|
def patch_assess_on_eval mod
|
38
40
|
return unless ::Contrast::ASSESS.enabled?
|
39
41
|
return if in_contrast_scope?
|
@@ -34,6 +34,8 @@ module Contrast
|
|
34
34
|
|
35
35
|
# Indicates is this feature has been disabled by the configuration,
|
36
36
|
# read at startup, and therefore can never be enabled.
|
37
|
+
#
|
38
|
+
# @return [Boolean] if this feature is disabled
|
37
39
|
def disabled_globally?
|
38
40
|
::Contrast::ASSESS.forcibly_disabled?
|
39
41
|
end
|
@@ -49,6 +51,8 @@ module Contrast
|
|
49
51
|
# This let's us be flexible and extensible
|
50
52
|
# * when we want to do lvl 2 rules, we could have the customers unzip
|
51
53
|
# our gem, insert things into the json, zip, and go *
|
54
|
+
#
|
55
|
+
# @param string [String]
|
52
56
|
def from_hash_string string
|
53
57
|
# The default behavior of the agent is to load the policy on startup,
|
54
58
|
# as at this point we do not know in which mode we'll be run.
|
@@ -26,8 +26,17 @@ module Contrast
|
|
26
26
|
JSON_TARGET = 'target'
|
27
27
|
TO_MARKER = '2'
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
# @return [Set<String>]
|
30
|
+
attr_accessor :tags
|
31
|
+
# @return [Symbol]
|
32
|
+
attr_accessor :type
|
33
|
+
attr_reader :sources
|
34
|
+
# @return [Array<String>]
|
35
|
+
attr_reader :targets
|
36
|
+
# @return [String]
|
37
|
+
attr_reader :source_string
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :target_string
|
31
40
|
|
32
41
|
# Here are all methods that can use original objects without mutation the source.
|
33
42
|
# For methods with REMOVE action, their (!) bang alternative is not listed, since
|
@@ -68,6 +77,8 @@ module Contrast
|
|
68
77
|
# String#to_s => self or string. This method is included here to cover the situations such as
|
69
78
|
# String.to_s.html_safe, where normally the dynamic sources properties get lost. To solve this
|
70
79
|
# we will simply return the original object here.
|
80
|
+
#
|
81
|
+
# @param policy_hash [Hash]
|
71
82
|
def assign_on_bang_check policy_hash
|
72
83
|
return true if @_use_original_object && TO_S.include?(policy_hash[JSON_METHOD_NAME])
|
73
84
|
|
@@ -76,18 +87,24 @@ module Contrast
|
|
76
87
|
policy_hash[JSON_METHOD_NAME].end_with?(Contrast::Utils::ObjectShare::BANG)
|
77
88
|
end
|
78
89
|
|
90
|
+
# @return [String]
|
79
91
|
def feature
|
80
92
|
'Assess'
|
81
93
|
end
|
82
94
|
|
95
|
+
# @return [String]
|
83
96
|
def node_class
|
84
97
|
'Node'
|
85
98
|
end
|
86
99
|
|
100
|
+
# @return [Symbol]
|
87
101
|
def node_type
|
88
102
|
:TYPE_METHOD
|
89
103
|
end
|
90
104
|
|
105
|
+
# Set the target string.
|
106
|
+
#
|
107
|
+
# @param value [String]
|
91
108
|
def target_string= value
|
92
109
|
@target_string = value
|
93
110
|
@targets = convert_policy_markers(value)
|
@@ -96,6 +113,9 @@ module Contrast
|
|
96
113
|
# Sometimes we need to tie information to an event. We'll add a
|
97
114
|
# properties section to the patch node, which can pass them along to
|
98
115
|
# the pre-dtm event
|
116
|
+
#
|
117
|
+
# @param name [String]
|
118
|
+
# @param value [String]
|
99
119
|
def add_property name, value
|
100
120
|
return unless name && value
|
101
121
|
|
@@ -103,6 +123,8 @@ module Contrast
|
|
103
123
|
@properties[name] = value
|
104
124
|
end
|
105
125
|
|
126
|
+
# @param name [String]
|
127
|
+
# @return [String]
|
106
128
|
def get_property name
|
107
129
|
return unless @properties
|
108
130
|
|
@@ -112,6 +134,8 @@ module Contrast
|
|
112
134
|
# Don't let nodes be created that will be missing things we need
|
113
135
|
# later on. Really, if they don't have these things, they couldn't have
|
114
136
|
# done their jobs anyway.
|
137
|
+
#
|
138
|
+
# @raise [ArgumentError] raises if the node is invalid.
|
115
139
|
def validate
|
116
140
|
super
|
117
141
|
validate_tags
|
@@ -124,11 +148,10 @@ module Contrast
|
|
124
148
|
# isn't a matching ENUM in TS land, the database gets got. We really
|
125
149
|
# don't want to get them, so we're going to prevent the node from being
|
126
150
|
# made.
|
151
|
+
#
|
127
152
|
# @raise[ArgumentError] raises if any of the tags is invalid
|
128
153
|
def validate_tags
|
129
|
-
|
130
|
-
|
131
|
-
tags.each do |tag|
|
154
|
+
tags&.each do |tag|
|
132
155
|
next if Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_TAGS.include?(tag) ||
|
133
156
|
Contrast::Agent::Reporting::FindingEventTaintRangeTags::VALID_SOURCE_TAGS.include?(tag)
|
134
157
|
|
@@ -159,8 +182,7 @@ module Contrast
|
|
159
182
|
# by changing them to 'A'
|
160
183
|
source = all_type?(source_string) ? ALL_TYPE : source_string
|
161
184
|
target = all_type?(target_string) ? ALL_TYPE : target_string
|
162
|
-
|
163
|
-
str.to_sym
|
185
|
+
(source[0] + TO_MARKER + target[0]).to_sym
|
164
186
|
end
|
165
187
|
end
|
166
188
|
|
@@ -21,7 +21,15 @@ module Contrast
|
|
21
21
|
UNDUPLICABLE_MODULES << IO::Buffer if RUBY_VERSION >= '3.1.0'
|
22
22
|
UNDUPLICABLE_MODULES.cs__freeze
|
23
23
|
|
24
|
-
|
24
|
+
# @return [Object] the object on which the method is to be called.
|
25
|
+
attr_accessor :object
|
26
|
+
# @return [Integer] the length of the object on which the method is to
|
27
|
+
# be called.
|
28
|
+
attr_accessor :object_length
|
29
|
+
# @return [Array<Object>] the arguments to be passed to the method.
|
30
|
+
attr_accessor :args
|
31
|
+
# @return [Array<Integer>] the lengths of the arguments to be passed to
|
32
|
+
attr_accessor :arg_lengths
|
25
33
|
|
26
34
|
class << self
|
27
35
|
# Save the state before we do the propagation. This is one of the
|
@@ -65,10 +73,23 @@ module Contrast
|
|
65
73
|
|
66
74
|
private
|
67
75
|
|
76
|
+
# Determine if the given object is an IO object that is closed, not in
|
77
|
+
# initialization, and therefore unsafe to use.
|
78
|
+
#
|
79
|
+
# @param object [Object] the object on which the method is to be
|
80
|
+
# called.
|
81
|
+
# @param initializing [Boolean] whether or not the method being
|
82
|
+
# called is the initialize method.
|
68
83
|
def unsafe_io_object? object, initializing
|
69
84
|
Contrast::Utils::DuckUtils.closable_io?(object) && !initializing && object.closed?
|
70
85
|
end
|
71
86
|
|
87
|
+
# check if object is duplicable
|
88
|
+
#
|
89
|
+
# @param initializing [Boolean] whether or not the method being
|
90
|
+
# called is the initialize method.
|
91
|
+
# @param object [Object] the object on which the method is to be
|
92
|
+
# called.
|
72
93
|
def can_dup? initializing, object
|
73
94
|
return false if initializing
|
74
95
|
|
@@ -76,6 +97,14 @@ module Contrast
|
|
76
97
|
!UNDUPLICABLE_MODULES.include?(check)
|
77
98
|
end
|
78
99
|
|
100
|
+
# Appends the object details to the given preshift and adds it to the LRU cache.
|
101
|
+
#
|
102
|
+
# @param preshift [Contrast::Agent::Assess::PreShift] the preshift to
|
103
|
+
# which the object details should be appended.
|
104
|
+
# @param initializing [Boolean] whether or not the method being
|
105
|
+
# called is the initialize method.
|
106
|
+
# @param object [Object] the object on which the method is to be
|
107
|
+
# called.
|
79
108
|
def append_object_details preshift, initializing, object
|
80
109
|
can = can_dup?(initializing, object)
|
81
110
|
preshift.object = if @lru_cache.key?(object.__id__) && !Contrast::Agent::Assess::Tracker.tracked?(object)
|
@@ -97,6 +126,10 @@ module Contrast
|
|
97
126
|
@lru_cache[object.__id__] = object
|
98
127
|
end
|
99
128
|
|
129
|
+
# @param preshift [Contrast::Agent::Assess::PreShift] the preshift to
|
130
|
+
# which the argument details should be appended.
|
131
|
+
# @param args [Array<Object>] the arguments to be passed to the
|
132
|
+
# method.
|
100
133
|
def append_arg_details preshift, args
|
101
134
|
args_length = args.length
|
102
135
|
preshift.args = Array.new(args_length)
|
@@ -88,6 +88,7 @@ module Contrast
|
|
88
88
|
end
|
89
89
|
|
90
90
|
# If this patcher has tags, apply them to the entire target
|
91
|
+
#
|
91
92
|
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
|
92
93
|
# propagation event.
|
93
94
|
# @param target [Object] the Target to which to propagate.
|
@@ -101,6 +102,9 @@ module Contrast
|
|
101
102
|
end
|
102
103
|
end
|
103
104
|
|
105
|
+
# Checks to see if the given target is valid for propagation.
|
106
|
+
#
|
107
|
+
# @return [Bool]
|
104
108
|
def context_available?
|
105
109
|
!!Contrast::Agent::REQUEST_TRACKER.current
|
106
110
|
end
|
@@ -121,7 +125,8 @@ module Contrast
|
|
121
125
|
|
122
126
|
private
|
123
127
|
|
124
|
-
# This is checked right before actual propagation
|
128
|
+
# This is checked right before actual propagation.
|
129
|
+
#
|
125
130
|
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
|
126
131
|
# propagation event.
|
127
132
|
# @param target [Object] the Target to which to propagate.
|
@@ -198,6 +203,10 @@ module Contrast
|
|
198
203
|
increment_event_count(propagation_node)
|
199
204
|
end
|
200
205
|
|
206
|
+
# @param propagation_class [Contrast::Agent::Assess::Policy::Propagator]
|
207
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
|
208
|
+
# @param source [Object] The object from which the propagation begins.
|
209
|
+
# @param target [Object] the Target to which to propagate.
|
201
210
|
def handle_propagation propagation_class, propagation_node, source, target
|
202
211
|
if propagation_node.patch_method
|
203
212
|
propagation_class.send(propagation_node.patch_method, propagation_node, source, target)
|
@@ -206,6 +215,12 @@ module Contrast
|
|
206
215
|
end
|
207
216
|
end
|
208
217
|
|
218
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
|
219
|
+
# @param target [Object] the Target to which to propagate.
|
220
|
+
# @param propagation_data [Contrast::Agent::Assess::Events::EventData] this will hold the
|
221
|
+
# object [Object] the Object on which the method was invoked
|
222
|
+
# ret [Object] the Return of the invoked method
|
223
|
+
# args [Array<Object>] the Arguments with which the method was invoked
|
209
224
|
def update_properties propagation_node, target, propagation_data
|
210
225
|
if propagation_node.use_original_on_bang_method?
|
211
226
|
properties = use_original_object_properties(propagation_data)
|
@@ -22,7 +22,34 @@ module Contrast
|
|
22
22
|
JSON_PATCH_CLASS = 'patch_class'
|
23
23
|
JSON_PATCH_METHOD = 'patch_method'
|
24
24
|
|
25
|
-
|
25
|
+
# @return action [String] the action to be taken by this propagation
|
26
|
+
# node. This can be one of the following:
|
27
|
+
# - 'CUSTOM' - the propagation node is a custom propagation node
|
28
|
+
# - 'DB_WRITE' - the propagation node is a database write propagation
|
29
|
+
# node
|
30
|
+
# - 'APPEND' - the propagation node is an append propagation node
|
31
|
+
# - 'CENTER' - the propagation node is a center propagation node
|
32
|
+
# - 'INSERT' - the propagation node is an insert propagation node
|
33
|
+
# - 'KEEP' - the propagation node is a keep propagation node
|
34
|
+
# - 'NEXT' - the propagation node is a next propagation node
|
35
|
+
# - 'BUFFER' - the propagation node is a buffer propagation node
|
36
|
+
# - 'NOOP' - the propagation node is a noop propagation node
|
37
|
+
# - 'PREPEND' - the propagation node is a prepend propagation node
|
38
|
+
# - 'REPLACE' - the propagation node is a replace propagation node
|
39
|
+
# - 'REMOVE' - the propagation node is a remove propagation node
|
40
|
+
# - 'REVERSE' - the propagation node is a reverse propagation node
|
41
|
+
# - 'RESPONSE' - the propagation node is a response propagation node
|
42
|
+
# - 'SPLAT' - the propagation node is a splat propagation node
|
43
|
+
# - 'SPLIT' - the propagation node is a split propagation node
|
44
|
+
attr_reader :action
|
45
|
+
# @return untags [Array<String>] the tags to be removed from the
|
46
|
+
# target of this propagation node.
|
47
|
+
attr_reader :untags
|
48
|
+
# @return patch_class [String] the class name of the class that
|
49
|
+
# contains the method to be called for this propagation node.
|
50
|
+
attr_reader :patch_method
|
51
|
+
# @return patch_method [Symbol] the name of the method to be called
|
52
|
+
# for this propagation node.
|
26
53
|
attr_accessor :patch_class
|
27
54
|
|
28
55
|
TAGGER = 'Tagger'
|
@@ -36,6 +63,9 @@ module Contrast
|
|
36
63
|
# Tags - array of tags to apply to the target, can be nil if no tags are added
|
37
64
|
# Untags - array of tags to remove from the target, can be nil if not tags are removed
|
38
65
|
# id, class_name, instance_method, method_name, source, target, action, tags = nil, untags = nil
|
66
|
+
#
|
67
|
+
# @param propagation_hash [Hash] the hash from which to build the
|
68
|
+
# propagation node.
|
39
69
|
def initialize propagation_hash = {}
|
40
70
|
super(propagation_hash)
|
41
71
|
@action = propagation_hash[JSON_ACTION]
|
@@ -49,6 +79,7 @@ module Contrast
|
|
49
79
|
nil
|
50
80
|
end
|
51
81
|
|
82
|
+
# @return [String] class name
|
52
83
|
def node_class
|
53
84
|
@_node_class ||= tagger? ? TAGGER : PROPAGATOR
|
54
85
|
end
|
@@ -56,12 +87,15 @@ module Contrast
|
|
56
87
|
# Unlike the other agents, we don't have separate tag & propagation
|
57
88
|
# events. To make TS happy, we need to have different types though.
|
58
89
|
# Pretty straight forward: if there's a tag, this is a tagger
|
90
|
+
#
|
91
|
+
# @return [Symbol] the type of node.
|
59
92
|
def node_type
|
60
93
|
tagger? ? :TYPE_TAG : :TYPE_PROPAGATION
|
61
94
|
end
|
62
95
|
|
63
96
|
# Standard validation + TS trace version two rules:
|
64
97
|
# Must have source, target, and action
|
98
|
+
#
|
65
99
|
# @raise[ArgumentError] raises if any of the required propagation node field is not valid, or is missing
|
66
100
|
def validate
|
67
101
|
super
|
@@ -100,6 +134,8 @@ module Contrast
|
|
100
134
|
end
|
101
135
|
end
|
102
136
|
|
137
|
+
# @return [Boolean]
|
138
|
+
# propagation node.
|
103
139
|
def needs_object?
|
104
140
|
if @_needs_object.nil?
|
105
141
|
@_needs_object = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION ||
|
@@ -110,6 +146,7 @@ module Contrast
|
|
110
146
|
@_needs_object
|
111
147
|
end
|
112
148
|
|
149
|
+
# @return [Boolean]
|
113
150
|
def needs_args?
|
114
151
|
if @_needs_args.nil?
|
115
152
|
@_needs_args = action == Contrast::Utils::Assess::PropagationMethodUtils::CUSTOM_ACTION ||
|
@@ -124,6 +161,8 @@ module Contrast
|
|
124
161
|
# It indicates this method is more than just a transformation,
|
125
162
|
# it is an interesting security event that has a meaningful
|
126
163
|
# change.
|
164
|
+
#
|
165
|
+
# @return [Boolean]
|
127
166
|
def tagger?
|
128
167
|
@_tagger = tags&.any? || untags&.any? if @_tagger.nil?
|
129
168
|
@_tagger
|
@@ -15,6 +15,11 @@ module Contrast
|
|
15
15
|
# if the target length is greater than the source
|
16
16
|
# copy tags from the param to the target in chunks of param size or less
|
17
17
|
# if param is appended in space less than param length
|
18
|
+
#
|
19
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
20
|
+
# propagation action required by this method.
|
21
|
+
# @param preshift [Object] pre call state of the things.
|
22
|
+
# @param target [Object] the object to which the source is being appended
|
18
23
|
def propagate propagation_node, preshift, target
|
19
24
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
|
20
25
|
|
@@ -12,6 +12,10 @@ module Contrast
|
|
12
12
|
# to pass tags from it to a Target.
|
13
13
|
class Base
|
14
14
|
class << self
|
15
|
+
# Retrieve the source from the preshift state.
|
16
|
+
#
|
17
|
+
# @param source [Symbol] the source to retrieve.
|
18
|
+
# @param preshift [Contrast::Agent::Assess::PreShift] the pre-call state of the things.
|
15
19
|
def find_source source, preshift
|
16
20
|
case source
|
17
21
|
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
@@ -21,10 +25,16 @@ module Contrast
|
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
28
|
+
# Check if tags are present on the given target.
|
29
|
+
#
|
30
|
+
# @return [Boolean]
|
24
31
|
def tracked_value? value
|
25
32
|
Contrast::Agent::Assess::Tracker.tracked?(value)
|
26
33
|
end
|
27
34
|
|
35
|
+
# Propagate the tags from the source to the target.
|
36
|
+
# This method should be extended by the subclasses.
|
37
|
+
#
|
28
38
|
# @raise [NoMethodError] This is being raised if any of the implementing subclasses does not have
|
29
39
|
# that method implemented, but is being called on.
|
30
40
|
def propagate _propagation_node, _preshift, _target
|
@@ -17,6 +17,12 @@ module Contrast
|
|
17
17
|
# Once the tag is applied, shift it to the location of the insert
|
18
18
|
# Unlike additive propagation, this currently only supports one source
|
19
19
|
# We assume that insert changes the preshift target
|
20
|
+
#
|
21
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
22
|
+
# propagation action required by this method.
|
23
|
+
# @param preshift [Object] pre call state of the things.
|
24
|
+
# @param target [Object] the object to which the source is being appended
|
25
|
+
# @return [Object] the target with the tags applied
|
20
26
|
def propagate_insert propagation_node, preshift, target
|
21
27
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
|
22
28
|
|
@@ -11,6 +11,11 @@ module Contrast
|
|
11
11
|
# are unaffected beyond any merging of overlapping tags.
|
12
12
|
class Center < Contrast::Agent::Assess::Policy::Propagator::Base
|
13
13
|
class << self
|
14
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
15
|
+
# propagation action required by this method.
|
16
|
+
# @param preshift [Object] pre call state of the things.
|
17
|
+
# @param target [Object] the object to which the source is being appended
|
18
|
+
# @return [Object] the target with the tags applied
|
14
19
|
def propagate propagation_node, preshift, target
|
15
20
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
|
16
21
|
|
@@ -56,6 +61,15 @@ module Contrast
|
|
56
61
|
iterate_tags(target, propagation_node, source, end_index, target.length)
|
57
62
|
end
|
58
63
|
|
64
|
+
# This method will iterate over the tags of the source and apply
|
65
|
+
# them to the target.
|
66
|
+
#
|
67
|
+
# @param target [Object] the thing to apply tags to.
|
68
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode]
|
69
|
+
# the node that indicates how this propagation should be handled.
|
70
|
+
# @param source [Object] the thing to copy tags from.
|
71
|
+
# @param start [Integer] where to start copying tags from.
|
72
|
+
# @param stop [Integer] where to stop copying tags from.
|
59
73
|
def iterate_tags target, propagation_node, source, start, stop
|
60
74
|
properties = Contrast::Agent::Assess::Tracker.properties(target)
|
61
75
|
while start < stop
|
@@ -17,6 +17,12 @@ module Contrast
|
|
17
17
|
extend Contrast::Utils::Assess::EventLimitUtils
|
18
18
|
|
19
19
|
class << self
|
20
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
21
|
+
# propagation action required by this method.
|
22
|
+
# @param preshift [Object] pre call state of the things.
|
23
|
+
# @param ret [Object] the return value of the method.
|
24
|
+
# @param block [Proc] the block passed to the method.
|
25
|
+
# @return [Object] the return value of the method.
|
20
26
|
def propagate propagation_node, preshift, ret, block
|
21
27
|
clazz = propagation_node.patch_class
|
22
28
|
method = propagation_node.patch_method
|
@@ -16,6 +16,11 @@ module Contrast
|
|
16
16
|
extend Contrast::Utils::Assess::EventLimitUtils
|
17
17
|
|
18
18
|
class << self
|
19
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
20
|
+
# propagation action required by this method.
|
21
|
+
# @param preshift [Object] pre call state of the things.
|
22
|
+
# @param target [Object] the object to which the source is being appended
|
23
|
+
# @return [Object] the target with the tags applied
|
19
24
|
def propagate propagation_node, preshift, target
|
20
25
|
return unless Contrast::ASSESS.require_dynamic_sources?
|
21
26
|
|
@@ -41,6 +46,15 @@ module Contrast
|
|
41
46
|
|
42
47
|
private
|
43
48
|
|
49
|
+
# Handles the write propagation for the given source.
|
50
|
+
#
|
51
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
52
|
+
# propagation action required by this method.
|
53
|
+
# @param source [Symbol] the source to retrieve.
|
54
|
+
# @param preshift [Contrast::Agent::Assess::PreShift] the pre-call state of the things.
|
55
|
+
# @param target [Object] the object to which the source is being appended
|
56
|
+
# @param known_tainted [Array] the list of known tainted columns
|
57
|
+
# @param tainted_columns [Hash] the hash of tainted columns
|
44
58
|
def handle_write propagation_node, source, preshift, target, known_tainted, tainted_columns
|
45
59
|
arg = preshift.args[source]
|
46
60
|
return unless arg.cs__respond_to?(:each_pair)
|
@@ -15,6 +15,12 @@ module Contrast
|
|
15
15
|
# Once the tag is applied, shift it to the location of the insert
|
16
16
|
# Unlike additive propagation, this currently only supports one source
|
17
17
|
# We assume that insert changes the preshift target
|
18
|
+
#
|
19
|
+
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node responsible for the
|
20
|
+
# propagation action required by this method.
|
21
|
+
# @param preshift [Object] pre call state of the things.
|
22
|
+
# @param target [Object] the object to which the source is being appended
|
23
|
+
# @return [Object] the target with the tags applied
|
18
24
|
def propagate propagation_node, preshift, target
|
19
25
|
return unless (properties = Contrast::Agent::Assess::Tracker.properties!(target))
|
20
26
|
|