contrast-agent 6.2.0 → 6.5.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/.gitignore +0 -3
- data/.simplecov +1 -0
- data/Rakefile +0 -27
- data/ext/cs__assess_basic_object/cs__assess_basic_object.c +7 -5
- data/ext/cs__assess_kernel/cs__assess_kernel.c +14 -3
- data/ext/cs__assess_kernel/cs__assess_kernel.h +2 -0
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +10 -3
- data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +2 -1
- data/ext/cs__assess_regexp/cs__assess_regexp.c +9 -7
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.c → cs__assess_string_interpolation/cs__assess_string_interpolation.c} +14 -3
- data/ext/{cs__assess_string_interpolation26/cs__assess_string_interpolation26.h → cs__assess_string_interpolation/cs__assess_string_interpolation.h} +1 -1
- data/ext/{cs__assess_string_interpolation26 → cs__assess_string_interpolation}/extconf.rb +0 -0
- data/ext/cs__common/cs__common.c +5 -4
- data/ext/cs__contrast_patch/cs__contrast_patch.c +17 -11
- data/lib/contrast/agent/assess/events/source_event.rb +16 -12
- data/lib/contrast/agent/assess/finalizers/hash.rb +1 -0
- data/lib/contrast/agent/assess/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/assess/policy/propagation_method.rb +8 -42
- data/lib/contrast/agent/assess/policy/propagation_node.rb +8 -0
- data/lib/contrast/agent/assess/policy/propagator/base.rb +2 -0
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +4 -0
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +5 -0
- data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +7 -47
- data/lib/contrast/agent/assess/policy/source_node.rb +1 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +9 -3
- data/lib/contrast/agent/assess/policy/trigger_node.rb +8 -0
- data/lib/contrast/agent/assess/property/evented.rb +4 -18
- data/lib/contrast/agent/assess/tag.rb +19 -0
- data/lib/contrast/agent/assess/tracker.rb +12 -0
- data/lib/contrast/agent/at_exit_hook.rb +8 -8
- data/lib/contrast/agent/inventory/database_config.rb +6 -3
- data/lib/contrast/agent/inventory/dependency_analysis.rb +5 -4
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +11 -11
- data/lib/contrast/agent/inventory/policy/datastores.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/middleware.rb +4 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +27 -2
- data/lib/contrast/agent/patching/policy/method_policy.rb +3 -3
- data/lib/contrast/agent/patching/policy/policy.rb +5 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +6 -0
- data/lib/contrast/agent/patching/policy/trigger_node.rb +3 -0
- data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +3 -4
- data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +1 -0
- data/lib/contrast/agent/protect/policy/rule_applicator.rb +2 -2
- data/lib/contrast/agent/protect/rule/base.rb +1 -0
- data/lib/contrast/agent/protect/rule/no_sqli.rb +2 -0
- data/lib/contrast/agent/reporting/reporter.rb +32 -7
- data/lib/contrast/agent/reporting/reporter_heartbeat.rb +22 -18
- data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +17 -21
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +1 -1
- data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample_activity.rb +26 -3
- data/lib/contrast/agent/reporting/reporting_events/application_update.rb +5 -24
- data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/discovered_route.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/finding.rb +7 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +12 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +11 -1
- data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +29 -32
- data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +13 -1
- data/lib/contrast/agent/reporting/reporting_events/observed_library_usage.rb +11 -8
- data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +12 -5
- data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +8 -1
- data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +9 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +10 -1
- data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +11 -4
- data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +0 -8
- data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -4
- data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -22
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -3
- data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -11
- data/lib/contrast/agent/request.rb +5 -7
- data/lib/contrast/agent/request_context.rb +16 -17
- data/lib/contrast/agent/request_context_extend.rb +8 -9
- data/lib/contrast/agent/request_handler.rb +9 -38
- data/lib/contrast/agent/rule_set.rb +4 -0
- data/lib/contrast/agent/service_heartbeat.rb +3 -4
- data/lib/contrast/agent/static_analysis.rb +7 -12
- data/lib/contrast/agent/telemetry/base.rb +35 -35
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_base.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_event.rb +2 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message.rb +5 -2
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_message_exception.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exception_stack_frame.rb +3 -0
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions.rb +0 -1
- data/lib/contrast/agent/thread_watcher.rb +1 -4
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent/worker_thread.rb +10 -0
- data/lib/contrast/api/communication/socket.rb +1 -0
- data/lib/contrast/api/decorators/message.rb +0 -6
- data/lib/contrast/api/decorators.rb +0 -2
- data/lib/contrast/api/dtm.pb.rb +1 -1
- data/lib/contrast/api/settings.pb.rb +1 -1
- data/lib/contrast/components/agent.rb +51 -13
- data/lib/contrast/components/assess.rb +16 -6
- data/lib/contrast/components/config.rb +18 -2
- data/lib/contrast/components/contrast_service.rb +1 -1
- data/lib/contrast/components/heap_dump.rb +51 -1
- data/lib/contrast/components/inventory.rb +19 -13
- data/lib/contrast/components/logger.rb +18 -0
- data/lib/contrast/config/assess_configuration.rb +28 -0
- data/lib/contrast/config/base_configuration.rb +8 -15
- data/lib/contrast/config/root_configuration.rb +12 -8
- data/lib/contrast/config/ruby_configuration.rb +2 -9
- data/lib/contrast/config/service_configuration.rb +4 -4
- data/lib/contrast/config.rb +0 -6
- data/lib/contrast/configuration.rb +0 -2
- data/lib/contrast/extension/assess/eval_trigger.rb +0 -4
- data/lib/contrast/extension/assess/hash.rb +3 -2
- data/lib/contrast/extension/assess/kernel.rb +22 -0
- data/lib/contrast/extension/assess/marshal.rb +16 -0
- data/lib/contrast/extension/assess/string.rb +21 -20
- data/lib/contrast/extension/object.rb +19 -0
- data/lib/contrast/framework/base_support.rb +8 -0
- data/lib/contrast/framework/manager.rb +6 -20
- data/lib/contrast/framework/manager_extend.rb +0 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +11 -16
- data/lib/contrast/framework/rails/support.rb +4 -1
- data/lib/contrast/logger/aliased_logging.rb +2 -0
- data/lib/contrast/logger/log.rb +2 -1
- data/lib/contrast/utils/assess/event_limit_utils.rb +96 -0
- data/lib/contrast/utils/assess/propagation_method_utils.rb +27 -7
- data/lib/contrast/utils/assess/source_method_utils.rb +0 -9
- data/lib/contrast/utils/log_utils.rb +2 -2
- data/lib/contrast/utils/lru_cache.rb +3 -0
- data/lib/contrast/utils/middleware_utils.rb +2 -0
- data/lib/contrast/utils/patching/policy/patch_utils.rb +6 -23
- data/lib/contrast/utils/telemetry_client.rb +7 -7
- data/lib/contrast.rb +37 -18
- data/lib/protobuf/code_generator.rb +129 -0
- data/lib/protobuf/decoder.rb +28 -0
- data/lib/protobuf/deprecation.rb +117 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +79 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +360 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/encoder.rb +11 -0
- data/lib/protobuf/enum.rb +365 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field/base_field.rb +380 -0
- data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
- data/lib/protobuf/field/bool_field.rb +64 -0
- data/lib/protobuf/field/bytes_field.rb +67 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +56 -0
- data/lib/protobuf/field/field_array.rb +102 -0
- data/lib/protobuf/field/field_hash.rb +122 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +28 -0
- data/lib/protobuf/field/float_field.rb +43 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +34 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +51 -0
- data/lib/protobuf/field/sfixed32_field.rb +27 -0
- data/lib/protobuf/field/sfixed64_field.rb +28 -0
- data/lib/protobuf/field/signed_integer_field.rb +29 -0
- data/lib/protobuf/field/sint32_field.rb +21 -0
- data/lib/protobuf/field/sint64_field.rb +21 -0
- data/lib/protobuf/field/string_field.rb +51 -0
- data/lib/protobuf/field/uint32_field.rb +21 -0
- data/lib/protobuf/field/uint64_field.rb +21 -0
- data/lib/protobuf/field/varint_field.rb +77 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/generators/base.rb +85 -0
- data/lib/protobuf/generators/enum_generator.rb +39 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +193 -0
- data/lib/protobuf/generators/file_generator.rb +262 -0
- data/lib/protobuf/generators/group_generator.rb +122 -0
- data/lib/protobuf/generators/message_generator.rb +104 -0
- data/lib/protobuf/generators/option_generator.rb +17 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/generators/service_generator.rb +50 -0
- data/lib/protobuf/lifecycle.rb +33 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message/fields.rb +233 -0
- data/lib/protobuf/message/serialization.rb +85 -0
- data/lib/protobuf/message.rb +241 -0
- data/lib/protobuf/optionable.rb +72 -0
- data/lib/protobuf/tasks/compile.rake +80 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/varint.rb +20 -0
- data/lib/protobuf/varint_pure.rb +31 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf.rb +91 -0
- data/proto/dynamic_discovery.proto +46 -0
- data/proto/google/protobuf/compiler/plugin.proto +183 -0
- data/proto/google/protobuf/descriptor.proto +911 -0
- data/proto/rpc.proto +71 -0
- data/resources/assess/policy.json +6 -23
- data/ruby-agent.gemspec +4 -2
- metadata +122 -33
- data/lib/contrast/agent/telemetry/events/exceptions/telemetry_exceptions_report.rb +0 -30
- data/lib/contrast/api/decorators/application_update.rb +0 -44
- data/lib/contrast/api/decorators/library.rb +0 -56
- data/lib/contrast/config/agent_configuration.rb +0 -63
- data/lib/contrast/config/heap_dump_configuration.rb +0 -59
- data/lib/contrast/config/inventory_configuration.rb +0 -33
- data/lib/contrast/config/logger_configuration.rb +0 -26
- data/lib/contrast/framework/platform_version.rb +0 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bdb8bbd08206dafbb18eee844e1487701c419d27c1df8e4b58c4c226b1995d5c
|
|
4
|
+
data.tar.gz: 57bbfe5e3dca05729f95f2994246e74d59f7eecc2f7fe434e265fa5c60cc3734
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f6d80b48529b52719fb7aa4608e0cd42f8ec613e61138d7f7a977652054f9a24f05a78c0d79821749bc4cc1d86b0878009e93f65be47155e47c9e1ec084780d
|
|
7
|
+
data.tar.gz: ad3d855319ebf15f1af37cac9507c2774af76a6151d7e9a4559c9de23891bcc41f0642729087165b19d20ee4891e327895f9e0d9c9c5d4e402e3a4b901b44484
|
data/.gitignore
CHANGED
data/.simplecov
CHANGED
data/Rakefile
CHANGED
|
@@ -17,30 +17,3 @@ Dir['ext/cs__*'].each do |extension|
|
|
|
17
17
|
ext.lib_dir = "lib/#{ name }"
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
desc 'compile the protobuf files for the agent, translating them to .rb classes'
|
|
22
|
-
task :contrast_pb_compile do
|
|
23
|
-
# do some stuff before compile
|
|
24
|
-
|
|
25
|
-
# Invoke the protobuf compile task with your sensible defaults
|
|
26
|
-
::Rake::Task['protobuf:compile'].invoke('lib', './agent-service-api/protobuf ./agent-service-api/protobuf/dtm.proto',
|
|
27
|
-
'lib/contrast/api',
|
|
28
|
-
nil)
|
|
29
|
-
|
|
30
|
-
::Rake::Task['protobuf:compile'].reenable
|
|
31
|
-
|
|
32
|
-
::Rake::Task['protobuf:compile'].invoke('lib',
|
|
33
|
-
'./agent-service-api/protobuf ./agent-service-api/protobuf/settings.proto',
|
|
34
|
-
'lib/contrast/api',
|
|
35
|
-
nil)
|
|
36
|
-
|
|
37
|
-
['dtm.pb.rb', 'settings.pb.rb'].each do |target_file|
|
|
38
|
-
target_path = File.absolute_path(File.join(__dir__, "./lib/contrast/api/#{ target_file }"))
|
|
39
|
-
unless File.exist?(target_path)
|
|
40
|
-
puts "File not found #{ target_path }"
|
|
41
|
-
exit 1
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
puts 'Protobuf copied successfully'
|
|
46
|
-
end
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
* }
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
VALUE contrast_check_and_register_instance_patch(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
21
|
+
const char *method_name,
|
|
22
|
+
VALUE(c_fn)(const int, VALUE *,
|
|
23
|
+
const VALUE));
|
|
23
24
|
|
|
24
25
|
void contrast_assess_instance_eval_trigger_check(VALUE self, VALUE source,
|
|
25
26
|
VALUE ret) {
|
|
@@ -65,6 +66,7 @@ void Init_cs__assess_basic_object(void) {
|
|
|
65
66
|
* but if someone else patched BasicObject#instance_eval,
|
|
66
67
|
* IDK if this is intentional... noting it. -ajm
|
|
67
68
|
*/
|
|
68
|
-
contrast_check_and_register_instance_patch(
|
|
69
|
-
|
|
69
|
+
contrast_check_and_register_instance_patch(
|
|
70
|
+
"BasicObject", "instance_eval",
|
|
71
|
+
contrast_assess_basic_object_instance_eval);
|
|
70
72
|
}
|
|
@@ -26,14 +26,25 @@ contrast_patched_kernel_exec(const int argc, const VALUE *argv,
|
|
|
26
26
|
return rb_funcall(self, rb_sym_assess_kernel_exec, argc, *argv);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/* Check and see if the Kernel#exec is already prepended */
|
|
30
|
+
VALUE contrast_is_kernel_exec_prepended() {
|
|
31
|
+
return contrast_check_prepended(
|
|
32
|
+
rb_const_get(rb_cObject, rb_intern("Kernel")), rb_sym_kernel_exec,
|
|
33
|
+
Qfalse);
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
void Init_cs__assess_kernel(void) {
|
|
37
|
+
VALUE rb_sym_kernel_exec = ID2SYM(rb_intern("exec"));
|
|
30
38
|
kernel_propagator = rb_define_module_under(core_assess, "KernelPropagator");
|
|
31
39
|
exec_apply_trigger = rb_intern("apply_trigger");
|
|
32
40
|
|
|
33
41
|
rb_sym_assess_kernel_exec =
|
|
34
42
|
contrast_register_patch("Kernel", "exec", contrast_patched_kernel_exec);
|
|
35
43
|
|
|
36
|
-
/*
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
/* check if prepended and register singleton patch if true */
|
|
45
|
+
if (contrast_is_kernel_exec_prepended() == Qtrue) {
|
|
46
|
+
/* should return the same value as above */
|
|
47
|
+
rb_sym_assess_kernel_exec = contrast_register_singleton_patch(
|
|
48
|
+
"Kernel", "exec", contrast_patched_kernel_exec);
|
|
49
|
+
}
|
|
39
50
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* return rb_marshal_load_with_proc(port, proc);
|
|
19
19
|
* }
|
|
20
20
|
*/
|
|
21
|
-
static VALUE
|
|
21
|
+
static VALUE contrast_marshal_module_prepend(const int argc, const VALUE *argv) {
|
|
22
22
|
VALUE result;
|
|
23
23
|
VALUE source_string;
|
|
24
24
|
|
|
@@ -67,6 +67,13 @@ void Init_cs__assess_marshal_module(void) {
|
|
|
67
67
|
rb_sym_assess_marshal_load = rb_intern("cs__load_assess");
|
|
68
68
|
rb_sym_protect_marshal_load = rb_intern("cs__load_protect");
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
/* check if prepended called form the after_load_patcher */
|
|
71
|
+
VALUE marshal = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
|
72
|
+
VALUE marshal_load = ID2SYM(rb_intern("load"));
|
|
73
|
+
VALUE is_prepended = contrast_check_prepended(marshal, marshal_load, Qfalse);
|
|
74
|
+
|
|
75
|
+
if (is_prepended == Qtrue) {
|
|
76
|
+
contrast_register_singleton_prepend_patch("Marshal", "load",
|
|
77
|
+
&contrast_marshal_module_prepend);
|
|
78
|
+
}
|
|
72
79
|
}
|
|
@@ -5,6 +5,7 @@ static VALUE marshal_propagator;
|
|
|
5
5
|
static VALUE rb_sym_assess_marshal_load;
|
|
6
6
|
static VALUE rb_sym_protect_marshal_load;
|
|
7
7
|
static VALUE properties_hash;
|
|
8
|
+
static VALUE marshal, marshal_load, is_prepended;
|
|
8
9
|
|
|
9
10
|
/*
|
|
10
11
|
* Rails is a jerk. In Rails 5, they decided to do away with the alias chaining
|
|
@@ -14,7 +15,7 @@ static VALUE properties_hash;
|
|
|
14
15
|
* special case this for now.
|
|
15
16
|
* -HM (shamelessly commenting on DP's work)
|
|
16
17
|
*/
|
|
17
|
-
static VALUE
|
|
18
|
+
static VALUE contrast_marshal_module_prepend(const int argc,
|
|
18
19
|
const VALUE *argv);
|
|
19
20
|
|
|
20
21
|
void Init_cs__assess_marshal_module(void);
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
#include <ruby.h>
|
|
8
8
|
|
|
9
9
|
extern VALUE contrast_force_patch(const int argc, VALUE *argv) {
|
|
10
|
-
|
|
10
|
+
return contrast_check_and_register_instance_patch(
|
|
11
11
|
"Regexp", "=~", contrast_assess_regexp_equal_squiggle);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/* check if method is prepended and register instance alias or prepend patch */
|
|
15
15
|
VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const char *method_name,
|
|
17
|
+
VALUE(c_fn)(const int, VALUE *,
|
|
18
|
+
const VALUE));
|
|
19
19
|
|
|
20
20
|
void contrast_alias_method(const VALUE target, const char *to,
|
|
21
21
|
const char *from);
|
|
@@ -58,8 +58,10 @@ void Init_cs__assess_regexp(void) {
|
|
|
58
58
|
rb_global_variable(&rb_sym_string);
|
|
59
59
|
rb_sym_back_ref = ID2SYM(rb_intern("back_ref"));
|
|
60
60
|
rb_global_variable(&rb_sym_back_ref);
|
|
61
|
-
rb_define_singleton_method(assess, "contrast_force_repatch_regexp",
|
|
61
|
+
rb_define_singleton_method(assess, "contrast_force_repatch_regexp",
|
|
62
|
+
contrast_force_patch, 0);
|
|
62
63
|
|
|
63
|
-
rb_sym_assess_regexp_equal_squiggle =
|
|
64
|
-
|
|
64
|
+
rb_sym_assess_regexp_equal_squiggle =
|
|
65
|
+
contrast_check_and_register_instance_patch(
|
|
66
|
+
"Regexp", "=~", contrast_assess_regexp_equal_squiggle);
|
|
65
67
|
}
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
/* Copyright (c) 2022 Contrast Security, Inc. See
|
|
2
2
|
* https://www.contrastsecurity.com/enduser-terms-0317a for more details. */
|
|
3
3
|
|
|
4
|
-
#include "
|
|
4
|
+
#include "cs__assess_string_interpolation.h"
|
|
5
5
|
#include "../cs__common/cs__common.h"
|
|
6
|
+
#include "../cs__scope/cs__scope.h"
|
|
6
7
|
#include <ruby.h>
|
|
7
8
|
|
|
8
9
|
static VALUE rb_str_concat_literals_hook(size_t num, VALUE *strary) {
|
|
9
10
|
VALUE result = rb_str_concat_literals_original(num, strary);
|
|
10
11
|
VALUE rb_params = rb_ary_new_from_values((int)num, strary);
|
|
11
|
-
|
|
12
|
+
VALUE in_contrast_scope = inst_methods_in_cntr_scope(contrast_patcher(), 0);
|
|
13
|
+
|
|
14
|
+
if (in_contrast_scope == Qfalse) {
|
|
15
|
+
/* enter scope */
|
|
16
|
+
inst_methods_enter_cntr_scope(contrast_patcher(), 0);
|
|
17
|
+
rb_funcall(string_propagator, track_interpolation, 2, rb_params,
|
|
18
|
+
result);
|
|
19
|
+
/* exit scope */
|
|
20
|
+
inst_methods_exit_cntr_scope(contrast_patcher(), 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
return result;
|
|
13
24
|
}
|
|
14
25
|
|
|
@@ -20,7 +31,7 @@ static int install_hooks() {
|
|
|
20
31
|
return 0;
|
|
21
32
|
}
|
|
22
33
|
|
|
23
|
-
void
|
|
34
|
+
void Init_cs__assess_string_interpolation(void) {
|
|
24
35
|
string_propagator =
|
|
25
36
|
rb_define_class_under(core_assess, "StringPropagator", rb_cObject);
|
|
26
37
|
track_interpolation = rb_intern("track_interpolation");
|
|
File without changes
|
data/ext/cs__common/cs__common.c
CHANGED
|
@@ -97,9 +97,10 @@ VALUE contrast_register_singleton_prepend_patch(const char *module_name,
|
|
|
97
97
|
/* module name c_char "Module"; */
|
|
98
98
|
/* method name c_char "method"; */
|
|
99
99
|
/* c_func => pointer */
|
|
100
|
-
VALUE contrast_check_and_register_instance_patch(
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
VALUE contrast_check_and_register_instance_patch(const char *module_name,
|
|
101
|
+
const char *method_name,
|
|
102
|
+
VALUE(c_fn)(const int, VALUE *,
|
|
103
|
+
const VALUE)) {
|
|
103
104
|
|
|
104
105
|
VALUE object, method, is_prepended, patch_type;
|
|
105
106
|
/* check if method is prepended */
|
|
@@ -291,5 +292,5 @@ void Init_cs__common(void) {
|
|
|
291
292
|
contrast_check_prepended, 2);
|
|
292
293
|
/* defined for object lookout */
|
|
293
294
|
rb_define_singleton_method(assess, "cs__object_method_prepended?",
|
|
294
|
-
contrast_lookout_prepended,
|
|
295
|
+
contrast_lookout_prepended, 3);
|
|
295
296
|
}
|
|
@@ -101,7 +101,18 @@ VALUE rescue_func(VALUE arg1) {
|
|
|
101
101
|
return Qnil;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* In the event that the original_method call throws an exception we need to ensure that contrast_post_patch is called
|
|
106
|
+
* to report that error. However, if there is no error we will call post_patch with the original_return instead of
|
|
107
|
+
* Qnil.
|
|
108
|
+
*
|
|
109
|
+
**/
|
|
104
110
|
VALUE contrast_patch_call_ensure(const VALUE *args) {
|
|
111
|
+
// we do not need to ensure that post patch is called if no error was thrown
|
|
112
|
+
if(!RTEST(rb_errinfo())) {
|
|
113
|
+
return Qnil;
|
|
114
|
+
}
|
|
115
|
+
|
|
105
116
|
int argc;
|
|
106
117
|
VALUE object, preshift, method_policy, method;
|
|
107
118
|
VALUE *argv;
|
|
@@ -125,6 +136,7 @@ VALUE ensure_wrapper(const VALUE *args) {
|
|
|
125
136
|
original_args = (VALUE)args[1];
|
|
126
137
|
ensure_args = (VALUE)args[2];
|
|
127
138
|
|
|
139
|
+
//this ensure if being treated as a rescue due to issues surrounding Kernel#throw
|
|
128
140
|
return rb_ensure(original_method, original_args, contrast_patch_call_ensure,
|
|
129
141
|
(VALUE)ensure_args);
|
|
130
142
|
}
|
|
@@ -220,21 +232,15 @@ VALUE contrast_run_patches(const VALUE *wrapped_args) {
|
|
|
220
232
|
* If the original method threw an exception, contrast_patch_call_rescue
|
|
221
233
|
* re-raises the original exception, which unwinds the stack back to the
|
|
222
234
|
* call site. This means the rest of this function is not executed.
|
|
235
|
+
* post_patch is called in the ensure_wrapper on exception. rb_rescue
|
|
236
|
+
* raises the exception so the below will not be executed in that event.
|
|
223
237
|
*/
|
|
224
238
|
|
|
225
|
-
/* Invoke Contrast post-call patching.
|
|
226
|
-
|
|
227
|
-
* hence the assignment.
|
|
228
|
-
*/
|
|
229
|
-
transformed_ret = contrast_call_post_patch(method_policy, preshift, object,
|
|
239
|
+
/* Invoke Contrast post-call patching. */
|
|
240
|
+
contrast_call_post_patch(method_policy, preshift, object,
|
|
230
241
|
original_ret, argc, argv);
|
|
231
242
|
|
|
232
|
-
|
|
233
|
-
if (transformed_ret != Qnil) {
|
|
234
|
-
return transformed_ret;
|
|
235
|
-
} else {
|
|
236
|
-
return original_ret;
|
|
237
|
-
}
|
|
243
|
+
return original_ret;
|
|
238
244
|
}
|
|
239
245
|
|
|
240
246
|
VALUE contrast_ensure_function(const VALUE method_policy) {
|
|
@@ -56,18 +56,8 @@ module Contrast
|
|
|
56
56
|
|
|
57
57
|
# Probably only for source events, but we'll go with source_type instead. java & .net support source_type
|
|
58
58
|
# in propagation events, so we'll future proof this
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return unless source_type
|
|
62
|
-
|
|
63
|
-
dtm = Contrast::Api::Dtm::TraceEventSource.new
|
|
64
|
-
dtm.type = forced_source_type
|
|
65
|
-
dtm.name = forced_source_name
|
|
66
|
-
dtm
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Probably only for source events, but we'll go with source_type instead. java & .net support source_type
|
|
70
|
-
# in propagation events, so we'll future proof this
|
|
59
|
+
#
|
|
60
|
+
# @return [Contrast::Agent::Reporting::TraceEventSource, nil]
|
|
71
61
|
def build_event_source
|
|
72
62
|
# You can have a source w/o a name, but not w/o a type
|
|
73
63
|
return unless source_type
|
|
@@ -89,6 +79,20 @@ module Contrast
|
|
|
89
79
|
event_dtm.target = @policy_node.target_string
|
|
90
80
|
@policy_node.targets[0]
|
|
91
81
|
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
# Probably only for source events, but we'll go with source_type instead. java & .net support source_type
|
|
86
|
+
# in propagation events, so we'll future proof this
|
|
87
|
+
def build_event_source_dtm
|
|
88
|
+
# You can have a source w/o a name, but not w/o a type
|
|
89
|
+
return unless source_type
|
|
90
|
+
|
|
91
|
+
dtm = Contrast::Api::Dtm::TraceEventSource.new
|
|
92
|
+
dtm.type = forced_source_type
|
|
93
|
+
dtm.name = forced_source_name
|
|
94
|
+
dtm
|
|
95
|
+
end
|
|
92
96
|
end
|
|
93
97
|
end
|
|
94
98
|
end
|
|
@@ -5,6 +5,7 @@ require 'contrast/agent/patching/policy/policy_node'
|
|
|
5
5
|
require 'contrast/api/decorators/trace_taint_range_tags'
|
|
6
6
|
require 'contrast/utils/object_share'
|
|
7
7
|
require 'contrast/agent/assess/policy/policy_node_utils'
|
|
8
|
+
require 'contrast/components/logger'
|
|
8
9
|
|
|
9
10
|
module Contrast
|
|
10
11
|
module Agent
|
|
@@ -13,6 +14,7 @@ module Contrast
|
|
|
13
14
|
# This class functions to translate our policy.json into an actionable
|
|
14
15
|
# Ruby object, allowing for dynamic patching over hardcoded patching.
|
|
15
16
|
class PolicyNode < Contrast::Agent::Patching::Policy::PolicyNode
|
|
17
|
+
include Contrast::Components::Logger::InstanceMethods
|
|
16
18
|
include PolicyNodeUtils
|
|
17
19
|
JSON_TAGS = 'tags'
|
|
18
20
|
JSON_DATAFLOW = 'dataflow'
|
|
@@ -107,12 +109,16 @@ module Contrast
|
|
|
107
109
|
def validate
|
|
108
110
|
super
|
|
109
111
|
validate_tags
|
|
112
|
+
rescue ArgumentError => e
|
|
113
|
+
logger.debug('Validation of policy node failed with: ', e)
|
|
114
|
+
nil
|
|
110
115
|
end
|
|
111
116
|
|
|
112
117
|
# TeamServer is picky. The tags here match to ENUMs there. If there
|
|
113
118
|
# isn't a matching ENUM in TS land, the database gets got. We really
|
|
114
119
|
# don't want to get them, so we're going to prevent the node from being
|
|
115
120
|
# made.
|
|
121
|
+
# @raise[ArgumentError] raises if any of the tags is invalid
|
|
116
122
|
def validate_tags
|
|
117
123
|
return unless tags
|
|
118
124
|
|
|
@@ -8,6 +8,7 @@ require 'contrast/components/logger'
|
|
|
8
8
|
require 'contrast/utils/object_share'
|
|
9
9
|
require 'contrast/utils/sha256_builder'
|
|
10
10
|
require 'contrast/utils/assess/propagation_method_utils'
|
|
11
|
+
require 'contrast/utils/assess/event_limit_utils'
|
|
11
12
|
require 'contrast/agent/assess/events/event_data'
|
|
12
13
|
require 'contrast/utils/assess/object_store'
|
|
13
14
|
|
|
@@ -21,6 +22,7 @@ module Contrast
|
|
|
21
22
|
module PropagationMethod
|
|
22
23
|
extend Contrast::Components::Logger::InstanceMethods
|
|
23
24
|
extend Contrast::Utils::Assess::PropagationMethodUtils
|
|
25
|
+
extend Contrast::Utils::Assess::EventLimitUtils
|
|
24
26
|
|
|
25
27
|
@properties = Contrast::Utils::Assess::ObjectStore.new
|
|
26
28
|
|
|
@@ -38,6 +40,7 @@ module Contrast
|
|
|
38
40
|
def apply_propagation method_policy, preshift, object, ret, args, block
|
|
39
41
|
return unless (propagation_node = method_policy.propagation_node)
|
|
40
42
|
return unless propagation_node.use_original_object? || preshift
|
|
43
|
+
return if event_limit?(method_policy)
|
|
41
44
|
|
|
42
45
|
target = determine_target(propagation_node, ret, object, args)
|
|
43
46
|
propagation_data = Contrast::Agent::Assess::Events::EventData.new(nil, nil, object, ret, args)
|
|
@@ -58,8 +61,6 @@ module Contrast
|
|
|
58
61
|
# ret [Object] the Return of the invoked method
|
|
59
62
|
# args [Array<Object>] the Arguments with which the method was invoked
|
|
60
63
|
# @param block [Block] the Block passed to the original method
|
|
61
|
-
# @return [Object, nil] the tracked Return or nil if no changes were made; will replace the return of the
|
|
62
|
-
# original function if not nil
|
|
63
64
|
def apply_propagator propagation_node, preshift, target, propagation_data, block
|
|
64
65
|
return unless propagation_possible?(propagation_node, target)
|
|
65
66
|
|
|
@@ -133,16 +134,6 @@ module Contrast
|
|
|
133
134
|
true
|
|
134
135
|
end
|
|
135
136
|
|
|
136
|
-
# Safely duplicate the target, or return nil
|
|
137
|
-
#
|
|
138
|
-
# @param target [Object] the thing to check for duplication
|
|
139
|
-
# @return [Object, nil]
|
|
140
|
-
def safe_dup target
|
|
141
|
-
target.dup
|
|
142
|
-
rescue StandardError => _e
|
|
143
|
-
nil
|
|
144
|
-
end
|
|
145
|
-
|
|
146
137
|
# Iterate over each key and value in a hash to allow for propagation to each.
|
|
147
138
|
#
|
|
148
139
|
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs this
|
|
@@ -196,28 +187,15 @@ module Contrast
|
|
|
196
187
|
# @param _block [Block] the Block passed to the original method
|
|
197
188
|
def handle_cs_properties_propagation propagation_node, preshift, target, propagation_data, _block
|
|
198
189
|
return if propagation_node.action == NOOP_ACTION
|
|
199
|
-
return unless can_propagate?(propagation_node, preshift, target)
|
|
190
|
+
return unless can_propagate?(propagation_node, preshift, target, propagation_data)
|
|
200
191
|
return unless (propagation_class = find_propagation_class(propagation_node))
|
|
201
192
|
|
|
202
|
-
restore_frozen_state = false
|
|
203
|
-
if target.cs__frozen? && !Contrast::Agent::Assess::Tracker.trackable?(target)
|
|
204
|
-
return unless can_handle_frozen?(propagation_node)
|
|
205
|
-
return unless (dup = safe_dup(propagation_data.ret))
|
|
206
|
-
|
|
207
|
-
restore_frozen_state = true
|
|
208
|
-
ret = dup
|
|
209
|
-
target = ret
|
|
210
|
-
Contrast::Agent::Assess::Tracker.pre_freeze(ret)
|
|
211
|
-
ret.cs__freeze
|
|
212
|
-
# double check that we were able to finalize the replaced return
|
|
213
|
-
return unless Contrast::Agent::Assess::Tracker.trackable?(target)
|
|
214
|
-
end
|
|
215
|
-
|
|
216
193
|
# If we are using the original object tracking, the preshift object is not created.
|
|
217
194
|
# Instead identify the source as the original object itself and propagate with it.
|
|
218
195
|
source = propagation_node.use_original_object? ? propagation_data.object : preshift
|
|
219
196
|
handle_propagation(propagation_class, propagation_node, source, target)
|
|
220
|
-
update_properties(
|
|
197
|
+
update_properties(propagation_node, target, propagation_data)
|
|
198
|
+
increment_event_count(propagation_node)
|
|
221
199
|
end
|
|
222
200
|
|
|
223
201
|
def handle_propagation propagation_class, propagation_node, source, target
|
|
@@ -228,7 +206,7 @@ module Contrast
|
|
|
228
206
|
end
|
|
229
207
|
end
|
|
230
208
|
|
|
231
|
-
def update_properties
|
|
209
|
+
def update_properties propagation_node, target, propagation_data
|
|
232
210
|
if propagation_node.use_original_on_bang_method?
|
|
233
211
|
properties = use_original_object_properties(propagation_data)
|
|
234
212
|
|
|
@@ -248,11 +226,10 @@ module Contrast
|
|
|
248
226
|
event_data = Contrast::Agent::Assess::Events::EventData.new(propagation_node,
|
|
249
227
|
target,
|
|
250
228
|
propagation_data.object,
|
|
251
|
-
ret,
|
|
229
|
+
propagation_data.ret,
|
|
252
230
|
propagation_data.args)
|
|
253
231
|
properties.build_event(event_data)
|
|
254
232
|
logger.trace('Propagation detected', node_id: propagation_node.id, target_id: target.__id__)
|
|
255
|
-
restore_frozen_state ? ret : nil
|
|
256
233
|
end
|
|
257
234
|
|
|
258
235
|
# Find the propagation class from the given node, if one exists.
|
|
@@ -269,17 +246,6 @@ module Contrast
|
|
|
269
246
|
propagation_class
|
|
270
247
|
end
|
|
271
248
|
|
|
272
|
-
# We can handle frozen propagation iff we're allowed to, as determined by configuration, and the target of
|
|
273
|
-
# the propagation is a return, as that's a replaceable value.
|
|
274
|
-
#
|
|
275
|
-
# @param propagation_node [Contrast::Agent::Assess::Policy::PropagationNode] the node that governs a
|
|
276
|
-
# propagation event.
|
|
277
|
-
# @return [Boolean]
|
|
278
|
-
def can_handle_frozen? propagation_node
|
|
279
|
-
::Contrast::ASSESS.track_frozen_sources? &&
|
|
280
|
-
propagation_node.targets[0] == Contrast::Utils::ObjectShare::RETURN_KEY
|
|
281
|
-
end
|
|
282
|
-
|
|
283
249
|
# For certain bang methods we return the same object, no need to create expensive new properties.
|
|
284
250
|
#
|
|
285
251
|
# @param propagation_data [Contrast::Agent::Assess::Events::EventData] used to hold object, args
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
require 'contrast/agent/assess/policy/policy_node'
|
|
5
5
|
require 'contrast/api/decorators/trace_taint_range_tags'
|
|
6
|
+
require 'contrast/components/logger'
|
|
6
7
|
|
|
7
8
|
module Contrast
|
|
8
9
|
module Agent
|
|
@@ -14,6 +15,8 @@ module Contrast
|
|
|
14
15
|
# untrusted data (indicate points in the application where user
|
|
15
16
|
# controlled input is modified).
|
|
16
17
|
class PropagationNode < PolicyNode
|
|
18
|
+
include Contrast::Components::Logger::InstanceMethods
|
|
19
|
+
|
|
17
20
|
JSON_ACTION = 'action'
|
|
18
21
|
JSON_UNTAGS = 'untags'
|
|
19
22
|
JSON_PATCH_CLASS = 'patch_class'
|
|
@@ -41,6 +44,9 @@ module Contrast
|
|
|
41
44
|
@patch_method = propagation_hash[JSON_PATCH_METHOD]
|
|
42
45
|
@patch_method = @patch_method.to_sym if @patch_method
|
|
43
46
|
validate
|
|
47
|
+
rescue ArgumentError => e
|
|
48
|
+
logger.error('Propagation Node Initialization failed with: ', e)
|
|
49
|
+
nil
|
|
44
50
|
end
|
|
45
51
|
|
|
46
52
|
def node_class
|
|
@@ -56,6 +62,7 @@ module Contrast
|
|
|
56
62
|
|
|
57
63
|
# Standard validation + TS trace version two rules:
|
|
58
64
|
# Must have source, target, and action
|
|
65
|
+
# @raise[ArgumentError] raises if any of the required propagation node field is not valid, or is missing
|
|
59
66
|
def validate
|
|
60
67
|
super
|
|
61
68
|
raise(ArgumentError, "Propagator #{ id } did not have a proper action. Unable to create.") unless action
|
|
@@ -78,6 +85,7 @@ module Contrast
|
|
|
78
85
|
validate_untags
|
|
79
86
|
end
|
|
80
87
|
|
|
88
|
+
# @raise[ArgumentError] raises if any of the tags is invalid
|
|
81
89
|
def validate_untags
|
|
82
90
|
return unless untags
|
|
83
91
|
|
|
@@ -25,6 +25,8 @@ module Contrast
|
|
|
25
25
|
Contrast::Agent::Assess::Tracker.tracked?(value)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# @raise [NoMethodError] This is being raised if any of the implementing subclasses does not have
|
|
29
|
+
# that method implemented, but is being called on.
|
|
28
30
|
def propagate _propagation_node, _preshift, _target
|
|
29
31
|
raise(NoMethodError("Expected Base propagator subclass: #{ cs__class } to implement #propagate"))
|
|
30
32
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/extension/module'
|
|
5
|
+
require 'contrast/utils/assess/event_limit_utils'
|
|
5
6
|
|
|
6
7
|
module Contrast
|
|
7
8
|
module Agent
|
|
@@ -13,6 +14,8 @@ module Contrast
|
|
|
13
14
|
# action knows the class and method it should call to preform this
|
|
14
15
|
# action.
|
|
15
16
|
module Custom
|
|
17
|
+
extend Contrast::Utils::Assess::EventLimitUtils
|
|
18
|
+
|
|
16
19
|
class << self
|
|
17
20
|
def propagate propagation_node, preshift, ret, block
|
|
18
21
|
clazz = propagation_node.patch_class
|
|
@@ -26,6 +29,7 @@ module Contrast
|
|
|
26
29
|
propagation_node.patch_class = clazz
|
|
27
30
|
end
|
|
28
31
|
clazz.send(method, propagation_node, preshift, ret, block)
|
|
32
|
+
increment_event_count(propagation_node)
|
|
29
33
|
end
|
|
30
34
|
end
|
|
31
35
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
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/utils/assess/event_limit_utils'
|
|
5
|
+
|
|
4
6
|
module Contrast
|
|
5
7
|
module Agent
|
|
6
8
|
module Assess
|
|
@@ -11,6 +13,8 @@ module Contrast
|
|
|
11
13
|
# results in new source nodes to track which columns in the database
|
|
12
14
|
# have been tainted.
|
|
13
15
|
class DatabaseWrite < Contrast::Agent::Assess::Policy::Propagator::Base
|
|
16
|
+
extend Contrast::Utils::Assess::EventLimitUtils
|
|
17
|
+
|
|
14
18
|
class << self
|
|
15
19
|
def propagate propagation_node, preshift, target
|
|
16
20
|
return unless Contrast::ASSESS.require_dynamic_sources?
|
|
@@ -22,6 +26,7 @@ module Contrast
|
|
|
22
26
|
known_tainted = ::Contrast::ASSESS.tainted_columns[class_name]
|
|
23
27
|
propagation_node.sources.each do |source|
|
|
24
28
|
handle_write(propagation_node, source, preshift, target, known_tainted, tainted_columns)
|
|
29
|
+
increment_event_count(propagation_node)
|
|
25
30
|
end
|
|
26
31
|
return if tainted_columns.empty?
|
|
27
32
|
|