contrast-agent 4.9.1 → 4.13.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/.rspec +0 -1
- data/.rspec_parallel +6 -0
- data/ext/cs__assess_module/cs__assess_module.c +48 -0
- data/ext/cs__assess_module/cs__assess_module.h +7 -0
- data/ext/cs__common/cs__common.c +24 -7
- data/ext/cs__common/cs__common.h +12 -2
- data/ext/cs__contrast_patch/cs__contrast_patch.c +48 -12
- data/ext/cs__contrast_patch/cs__contrast_patch.h +5 -4
- data/ext/cs__os_information/cs__os_information.c +31 -0
- data/ext/cs__os_information/cs__os_information.h +7 -0
- data/ext/{cs__protect_kernel → cs__os_information}/extconf.rb +0 -0
- data/lib/contrast/agent/assess/contrast_event.rb +1 -2
- data/lib/contrast/agent/assess/contrast_object.rb +1 -4
- data/lib/contrast/agent/assess/finalizers/hash.rb +0 -1
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +2 -0
- data/lib/contrast/agent/assess/policy/patcher.rb +0 -1
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +0 -2
- data/lib/contrast/agent/assess/policy/preshift.rb +29 -12
- data/lib/contrast/agent/assess/policy/propagation_method.rb +71 -142
- data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +2 -2
- data/lib/contrast/agent/assess/policy/propagator/match_data.rb +31 -11
- data/lib/contrast/agent/assess/policy/propagator/remove.rb +4 -9
- data/lib/contrast/agent/assess/policy/propagator/split.rb +3 -2
- data/lib/contrast/agent/assess/policy/propagator/substitution.rb +1 -0
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +0 -1
- data/lib/contrast/agent/assess/policy/source_method.rb +15 -88
- data/lib/contrast/agent/assess/policy/trigger/xpath.rb +0 -1
- data/lib/contrast/agent/assess/policy/trigger_method.rb +45 -172
- data/lib/contrast/agent/assess/policy/trigger_node.rb +52 -19
- data/lib/contrast/agent/assess/property/evented.rb +2 -1
- data/lib/contrast/agent/assess/property/tagged.rb +15 -132
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +0 -1
- data/lib/contrast/agent/deadzone/policy/policy.rb +6 -0
- data/lib/contrast/agent/disable_reaction.rb +1 -1
- data/lib/contrast/agent/exclusion_matcher.rb +0 -4
- data/lib/contrast/agent/inventory/database_config.rb +117 -0
- data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +7 -5
- data/lib/contrast/agent/inventory/policy/datastores.rb +2 -2
- data/lib/contrast/agent/metric_telemetry_event.rb +26 -0
- data/lib/contrast/agent/middleware.rb +23 -0
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +3 -0
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +17 -12
- data/lib/contrast/agent/patching/policy/method_policy.rb +54 -9
- data/lib/contrast/agent/patching/policy/module_policy.rb +2 -4
- data/lib/contrast/agent/patching/policy/patch.rb +42 -238
- data/lib/contrast/agent/patching/policy/patch_status.rb +3 -7
- data/lib/contrast/agent/patching/policy/patcher.rb +10 -49
- data/lib/contrast/agent/protect/policy/applies_no_sqli_rule.rb +1 -1
- data/lib/contrast/agent/protect/rule/no_sqli.rb +7 -53
- data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +137 -0
- data/lib/contrast/agent/protect/rule/sqli.rb +7 -70
- data/lib/contrast/agent/reaction_processor.rb +1 -1
- data/lib/contrast/agent/request.rb +9 -4
- data/lib/contrast/agent/request_context.rb +51 -33
- data/lib/contrast/agent/request_handler.rb +7 -3
- data/lib/contrast/agent/rule_set.rb +2 -4
- data/lib/contrast/agent/scope.rb +32 -20
- data/lib/contrast/agent/startup_metrics_telemetry_event.rb +71 -0
- data/lib/contrast/agent/static_analysis.rb +5 -3
- data/lib/contrast/agent/telemetry.rb +129 -0
- data/lib/contrast/agent/telemetry_event.rb +34 -0
- data/lib/contrast/agent/thread_watcher.rb +43 -14
- data/lib/contrast/agent/tracepoint_hook.rb +16 -3
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/agent.rb +6 -1
- data/lib/contrast/api/communication/messaging_queue.rb +12 -6
- data/lib/contrast/api/communication/service_lifecycle.rb +4 -1
- data/lib/contrast/api/communication/socket_client.rb +4 -4
- data/lib/contrast/api/decorators/agent_startup.rb +4 -4
- data/lib/contrast/api/decorators/application_startup.rb +6 -5
- data/lib/contrast/api/decorators/route_coverage.rb +24 -1
- data/lib/contrast/components/agent.rb +5 -2
- data/lib/contrast/components/api.rb +34 -0
- data/lib/contrast/components/app_context.rb +24 -0
- data/lib/contrast/components/assess.rb +13 -3
- data/lib/contrast/components/base.rb +2 -2
- data/lib/contrast/components/config.rb +91 -11
- data/lib/contrast/components/contrast_service.rb +10 -2
- data/lib/contrast/components/logger.rb +13 -8
- data/lib/contrast/components/scope.rb +9 -28
- data/lib/contrast/config/api_configuration.rb +22 -0
- data/lib/contrast/config/assess_configuration.rb +1 -0
- data/lib/contrast/config/base_configuration.rb +14 -6
- data/lib/contrast/config/env_variables.rb +25 -0
- data/lib/contrast/config/root_configuration.rb +1 -0
- data/lib/contrast/config/service_configuration.rb +2 -1
- data/lib/contrast/config.rb +1 -0
- data/lib/contrast/configuration.rb +22 -15
- data/lib/contrast/extension/assess/array.rb +1 -11
- data/lib/contrast/extension/assess/eval_trigger.rb +0 -20
- data/lib/contrast/extension/assess/fiber.rb +0 -11
- data/lib/contrast/extension/assess/hash.rb +0 -10
- data/lib/contrast/extension/assess/kernel.rb +1 -10
- data/lib/contrast/extension/assess/marshal.rb +3 -11
- data/lib/contrast/extension/assess/regexp.rb +0 -11
- data/lib/contrast/extension/assess/string.rb +1 -26
- data/lib/contrast/extension/extension.rb +61 -0
- data/lib/contrast/framework/grape/support.rb +174 -0
- data/lib/contrast/framework/manager.rb +56 -18
- data/lib/contrast/framework/rack/support.rb +1 -1
- data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +9 -6
- data/lib/contrast/framework/rails/patch/assess_configuration.rb +0 -1
- data/lib/contrast/framework/rails/patch/support.rb +35 -30
- data/lib/contrast/framework/rails/railtie.rb +1 -1
- data/lib/contrast/framework/rails/rewrite/active_record_named.rb +1 -0
- data/lib/contrast/framework/rails/support.rb +60 -13
- data/lib/contrast/framework/sinatra/support.rb +1 -1
- data/lib/contrast/logger/application.rb +4 -0
- data/lib/contrast/logger/log.rb +89 -15
- data/lib/contrast/utils/assess/propagation_method_utils.rb +129 -0
- data/lib/contrast/utils/assess/property/tagged_utils.rb +142 -0
- data/lib/contrast/utils/assess/source_method_utils.rb +83 -0
- data/lib/contrast/utils/assess/trigger_method_utils.rb +138 -0
- data/lib/contrast/utils/class_util.rb +58 -44
- data/lib/contrast/utils/exclude_key.rb +20 -0
- data/lib/contrast/utils/io_util.rb +43 -35
- data/lib/contrast/utils/lru_cache.rb +45 -0
- data/lib/contrast/utils/metrics_hash.rb +59 -0
- data/lib/contrast/utils/os.rb +23 -0
- data/lib/contrast/utils/patching/policy/patch_utils.rb +232 -0
- data/lib/contrast/utils/patching/policy/patcher_utils.rb +54 -0
- data/lib/contrast/utils/requests_client.rb +150 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +16 -13
- data/lib/contrast/utils/tag_util.rb +2 -1
- data/lib/contrast/utils/telemetry.rb +78 -0
- data/lib/contrast/utils/telemetry_identifier.rb +137 -0
- data/lib/contrast.rb +19 -1
- data/resources/assess/policy.json +208 -7
- data/resources/deadzone/policy.json +91 -0
- data/ruby-agent.gemspec +12 -2
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +102 -18
- data/ext/cs__protect_kernel/cs__protect_kernel.c +0 -47
- data/ext/cs__protect_kernel/cs__protect_kernel.h +0 -12
- data/lib/contrast/extension/protect/kernel.rb +0 -39
- data/lib/contrast/utils/inventory_util.rb +0 -113
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 469e09f0e64dcdb68643154ca601b20b8f61d634789dec642a374d6a51671fec
|
|
4
|
+
data.tar.gz: e4053b76ef09eaf13ee1cf09418d5ae50cd5e518b5e69f611c0a22d15a9bcd4d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 311a76a16c063b1d3afe09921e82efa59ea6367165d78fb26c833ab1dcf1e0daba2c3a0bf3597651cd86d146f4480004e916bb78842c6d8185f824dc768c204d
|
|
7
|
+
data.tar.gz: 3a4c0db4f013ccd0c7427ef01e451fa2d57b9458de7ce2c23df3444f3fcc4c824a7b841d81bf2aa25ecfd378be2afcea3ea57cded948bd350f4c6516a509477e
|
data/.rspec
CHANGED
data/.rspec_parallel
ADDED
|
@@ -57,6 +57,45 @@ contrast_assess_module_module_eval(const int argc, const VALUE *argv,
|
|
|
57
57
|
return ret;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
VALUE
|
|
61
|
+
contrast_assess_module_prepend(const int argc, const VALUE *argv,
|
|
62
|
+
const VALUE self) {
|
|
63
|
+
|
|
64
|
+
rb_prepend_module(self, argv[0]);
|
|
65
|
+
|
|
66
|
+
VALUE module_at;
|
|
67
|
+
VALUE rb_incl_in_mod_ary = rb_funcall(self, rb_intern("included_in"), 0);
|
|
68
|
+
|
|
69
|
+
if (RB_TYPE_P(rb_incl_in_mod_ary, T_ARRAY)) {
|
|
70
|
+
int i = 0;
|
|
71
|
+
int size = rb_funcall(rb_incl_in_mod_ary, rb_intern("length"), 0);
|
|
72
|
+
for (i = 0; i < size; ++i) {
|
|
73
|
+
module_at = rb_ary_entry(rb_incl_in_mod_ary, i);
|
|
74
|
+
if (RB_TYPE_P(module_at, T_MODULE)) {
|
|
75
|
+
rb_include_module(module_at, argv[0]);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return self;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
VALUE
|
|
83
|
+
contrast_assess_module_included(const int argc, const VALUE *argv,
|
|
84
|
+
const VALUE self) {
|
|
85
|
+
VALUE frozen;
|
|
86
|
+
if (RB_TYPE_P(self, T_MODULE)) {
|
|
87
|
+
// check if frozen
|
|
88
|
+
frozen = rb_funcall(self, rb_intern("cs__frozen?"), 0);
|
|
89
|
+
if (frozen == Qfalse) {
|
|
90
|
+
VALUE ary = rb_funcall(self, rb_intern("included_in"), 0);
|
|
91
|
+
if (RB_TYPE_P(ary, T_ARRAY)) {
|
|
92
|
+
rb_ary_push(ary, argv[0]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return self;
|
|
97
|
+
}
|
|
98
|
+
|
|
60
99
|
void Init_cs__assess_module(void) {
|
|
61
100
|
module_eval_trigger =
|
|
62
101
|
rb_define_class_under(core_assess, "EvalTrigger", rb_cObject);
|
|
@@ -76,4 +115,13 @@ void Init_cs__assess_module(void) {
|
|
|
76
115
|
|
|
77
116
|
contrast_register_patch("Module", "module_eval",
|
|
78
117
|
contrast_assess_module_module_eval);
|
|
118
|
+
/*
|
|
119
|
+
* We patch these for better ancestors handling, and only for older ruby versions.
|
|
120
|
+
*/
|
|
121
|
+
if (rb_ver_below_three()) {
|
|
122
|
+
contrast_register_patch("Module", "included",
|
|
123
|
+
contrast_assess_module_included);
|
|
124
|
+
contrast_register_patch("Module", "prepend",
|
|
125
|
+
contrast_assess_module_prepend);
|
|
126
|
+
}
|
|
79
127
|
}
|
|
@@ -24,5 +24,12 @@ contrast_assess_module_class_eval(const int argc, const VALUE *argv,
|
|
|
24
24
|
VALUE
|
|
25
25
|
contrast_assess_module_module_eval(const int argc, const VALUE *argv,
|
|
26
26
|
const VALUE mod);
|
|
27
|
+
VALUE
|
|
28
|
+
contrast_assess_module_prepend(const int argc, const VALUE *argv,
|
|
29
|
+
const VALUE self);
|
|
30
|
+
|
|
31
|
+
VALUE
|
|
32
|
+
contrast_assess_module_included(const int argc, const VALUE *argv,
|
|
33
|
+
const VALUE mod);
|
|
27
34
|
|
|
28
35
|
void Init_cs__assess_module(void);
|
data/ext/cs__common/cs__common.c
CHANGED
|
@@ -73,11 +73,20 @@ VALUE contrast_register_singleton_patch(const char *module_name,
|
|
|
73
73
|
IMPL_ALIAS_SINGLETON);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
VALUE
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
VALUE contrast_register_prepend_patch(const char *module_name,
|
|
77
|
+
const char *method_name,
|
|
78
|
+
VALUE(c_fn)(const int, VALUE *,
|
|
79
|
+
const VALUE)) {
|
|
79
80
|
return _contrast_register_patch(module_name, method_name, c_fn,
|
|
80
|
-
|
|
81
|
+
IMPL_PREPEND_INSTANCE);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
VALUE contrast_register_singleton_prepend_patch(const char *module_name,
|
|
85
|
+
const char *method_name,
|
|
86
|
+
VALUE(c_fn)(const int, VALUE *,
|
|
87
|
+
const VALUE)) {
|
|
88
|
+
return _contrast_register_patch(module_name, method_name, c_fn,
|
|
89
|
+
IMPL_PREPEND_SINGLETON);
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
static VALUE
|
|
@@ -122,8 +131,10 @@ _contrast_register_patch(const char *module_name, const char *method_name,
|
|
|
122
131
|
case IMPL_ALIAS_SINGLETON:
|
|
123
132
|
impl = ID2SYM(rb_sym_alias_singleton);
|
|
124
133
|
break;
|
|
125
|
-
case
|
|
126
|
-
impl = ID2SYM(
|
|
134
|
+
case IMPL_PREPEND_INSTANCE:
|
|
135
|
+
impl = ID2SYM(rb_sym_prepend_instance);
|
|
136
|
+
case IMPL_PREPEND_SINGLETON:
|
|
137
|
+
impl = ID2SYM(rb_sym_prepend_singleton);
|
|
127
138
|
break;
|
|
128
139
|
}
|
|
129
140
|
|
|
@@ -133,6 +144,11 @@ _contrast_register_patch(const char *module_name, const char *method_name,
|
|
|
133
144
|
return SYM2ID(underlying_method_name);
|
|
134
145
|
}
|
|
135
146
|
|
|
147
|
+
int rb_ver_below_three() {
|
|
148
|
+
int ruby_version = FIX2INT(rb_funcall(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")), rb_intern("to_i"), 0));
|
|
149
|
+
return ruby_version < 3;
|
|
150
|
+
}
|
|
151
|
+
|
|
136
152
|
void Init_cs__common(void) {
|
|
137
153
|
cs__send_method = rb_intern("send");
|
|
138
154
|
cs__alias_method_sym = ID2SYM(rb_intern("alias_method"));
|
|
@@ -152,7 +168,8 @@ void Init_cs__common(void) {
|
|
|
152
168
|
rb_sym_register_c_patch = rb_intern("register_c_patch");
|
|
153
169
|
rb_sym_alias_instance = rb_intern("alias_instance");
|
|
154
170
|
rb_sym_alias_singleton = rb_intern("alias_singleton");
|
|
155
|
-
|
|
171
|
+
rb_sym_prepend_instance = rb_intern("prepend_instance");
|
|
172
|
+
rb_sym_prepend_singleton = rb_intern("prepend_singleton");
|
|
156
173
|
|
|
157
174
|
/* Ensure definition of core Contrast instrumentation modules */
|
|
158
175
|
contrast = rb_define_module("Contrast");
|
data/ext/cs__common/cs__common.h
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
typedef enum {
|
|
7
7
|
IMPL_ALIAS_INSTANCE,
|
|
8
8
|
IMPL_ALIAS_SINGLETON,
|
|
9
|
-
|
|
9
|
+
IMPL_PREPEND_INSTANCE,
|
|
10
|
+
IMPL_PREPEND_SINGLETON,
|
|
10
11
|
} patch_impl;
|
|
11
12
|
|
|
12
13
|
static VALUE cs__send_method;
|
|
@@ -30,7 +31,16 @@ static VALUE rb_sym_instance_method;
|
|
|
30
31
|
static VALUE rb_sym_register_c_patch;
|
|
31
32
|
static VALUE rb_sym_alias_instance;
|
|
32
33
|
static VALUE rb_sym_alias_singleton;
|
|
33
|
-
static VALUE
|
|
34
|
+
static VALUE rb_sym_prepend_instance;
|
|
35
|
+
static VALUE rb_sym_prepend_singleton;
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* Check if ruby version is < 3.0.0.
|
|
39
|
+
* We are using this for handling ancestors of included modules.
|
|
40
|
+
* Since this is fixed after Ruby 3.0.0 we should remove this after
|
|
41
|
+
* dropping support for older versions, as no longer needed.
|
|
42
|
+
*/
|
|
43
|
+
int rb_ver_below_three();
|
|
34
44
|
|
|
35
45
|
void patch_via_funchook(void *original_function, void *hook_function);
|
|
36
46
|
|
|
@@ -43,7 +43,7 @@ VALUE contrast_patch_call_original(const VALUE *args) {
|
|
|
43
43
|
if (rb_block_given_p()) {
|
|
44
44
|
return rb_funcall_with_block_kw(object, method_id, argc, params, rb_block_proc(), RB_PASS_CALLED_KEYWORDS);
|
|
45
45
|
} else {
|
|
46
|
-
return rb_funcallv_kw(object, method_id, argc, params, RB_PASS_CALLED_KEYWORDS);
|
|
46
|
+
return rb_funcallv_kw(object, method_id, argc, params, RB_PASS_CALLED_KEYWORDS);
|
|
47
47
|
}
|
|
48
48
|
/* Ruby < 2.7 */
|
|
49
49
|
#else
|
|
@@ -182,7 +182,8 @@ VALUE contrast_run_patches(const VALUE *wrapped_args) {
|
|
|
182
182
|
contrast_patch_call_rescue,
|
|
183
183
|
(VALUE)rescue_args, rb_eException, 0);
|
|
184
184
|
break;
|
|
185
|
-
case
|
|
185
|
+
case IMPL_PREPEND_INSTANCE:
|
|
186
|
+
case IMPL_PREPEND_SINGLETON:
|
|
186
187
|
original_ret = rb_rescue2(contrast_call_super, original_args,
|
|
187
188
|
contrast_patch_call_rescue,
|
|
188
189
|
(VALUE)rescue_args, rb_eException, 0);
|
|
@@ -247,10 +248,14 @@ VALUE contrast_patch_dispatch(const int argc, const VALUE *argv,
|
|
|
247
248
|
*/
|
|
248
249
|
switch (impl) {
|
|
249
250
|
case IMPL_ALIAS_INSTANCE:
|
|
250
|
-
case
|
|
251
|
+
case IMPL_PREPEND_INSTANCE:
|
|
251
252
|
known =
|
|
252
253
|
rb_funcall(patch_status, rb_sym_info_for, 3, object, method, Qtrue);
|
|
253
254
|
break;
|
|
255
|
+
case IMPL_PREPEND_SINGLETON:
|
|
256
|
+
known =
|
|
257
|
+
rb_funcall(patch_status, rb_sym_info_for, 3, object, method, Qfalse);
|
|
258
|
+
break;
|
|
254
259
|
case IMPL_ALIAS_SINGLETON:
|
|
255
260
|
known = rb_funcall(patch_status, rb_sym_info_for, 3, object, method,
|
|
256
261
|
Qfalse);
|
|
@@ -323,7 +328,8 @@ call_original:
|
|
|
323
328
|
case IMPL_ALIAS_INSTANCE:
|
|
324
329
|
case IMPL_ALIAS_SINGLETON:
|
|
325
330
|
return contrast_patch_call_original(original_args);
|
|
326
|
-
case
|
|
331
|
+
case IMPL_PREPEND_INSTANCE:
|
|
332
|
+
case IMPL_PREPEND_SINGLETON:
|
|
327
333
|
return contrast_call_super(original_args);
|
|
328
334
|
};
|
|
329
335
|
}
|
|
@@ -338,9 +344,14 @@ VALUE contrast_alias_singleton_patch(const int argc, const VALUE *argv,
|
|
|
338
344
|
return contrast_patch_dispatch(argc, argv, IMPL_ALIAS_SINGLETON, object);
|
|
339
345
|
}
|
|
340
346
|
|
|
341
|
-
VALUE
|
|
347
|
+
VALUE contrast_prepend_instance_patch(const int argc, const VALUE *argv,
|
|
342
348
|
const VALUE object) {
|
|
343
|
-
return contrast_patch_dispatch(argc, argv,
|
|
349
|
+
return contrast_patch_dispatch(argc, argv, IMPL_PREPEND_INSTANCE, object);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
VALUE contrast_prepend_singleton_patch(const int argc, const VALUE *argv,
|
|
353
|
+
const VALUE object) {
|
|
354
|
+
return contrast_patch_dispatch(argc, argv, IMPL_PREPEND_SINGLETON, object);
|
|
344
355
|
}
|
|
345
356
|
|
|
346
357
|
VALUE contrast_patch_define_method(const VALUE self, const VALUE clazz, const VALUE method_policy,
|
|
@@ -403,29 +414,55 @@ VALUE contrast_patch_define_method(const VALUE self, const VALUE clazz, const VA
|
|
|
403
414
|
VALUE contrast_patch_prepend(const VALUE self, const VALUE originalModule,
|
|
404
415
|
const VALUE method_policy) {
|
|
405
416
|
|
|
417
|
+
const VALUE instance = Qtrue;
|
|
418
|
+
const VALUE singleton = Qfalse;
|
|
406
419
|
const VALUE original_method_name =
|
|
407
420
|
rb_funcall(method_policy, rb_sym_method_name, 0);
|
|
408
421
|
const VALUE is_private =
|
|
409
422
|
rb_funcall(method_policy, rb_sym_private_method, 0);
|
|
410
423
|
const VALUE is_instance_method =
|
|
411
424
|
rb_funcall(method_policy, rb_sym_instance_method, 0);
|
|
412
|
-
|
|
413
|
-
|
|
425
|
+
|
|
426
|
+
// Set the value for instance or singleton method
|
|
427
|
+
if (RTEST(is_instance_method)){
|
|
428
|
+
rb_funcall(patch_status, rb_sym_set_info_for, 5, originalModule,
|
|
429
|
+
original_method_name, method_policy, instance, Qnil);
|
|
430
|
+
|
|
431
|
+
} else {
|
|
432
|
+
rb_funcall(patch_status, rb_sym_set_info_for, 5, originalModule,
|
|
433
|
+
original_method_name, method_policy, singleton, Qnil);
|
|
434
|
+
}
|
|
435
|
+
|
|
414
436
|
VALUE module = rb_define_module_under(originalModule, "ContrastPrepend");
|
|
415
437
|
VALUE str = rb_funcall(original_method_name, rb_sym_cs_to_s, 0);
|
|
416
438
|
char *cMethodName = StringValueCStr(str);
|
|
417
439
|
if (RTEST(is_instance_method)) {
|
|
418
440
|
if (RTEST(is_private)) {
|
|
419
441
|
rb_define_private_method(module, cMethodName,
|
|
420
|
-
|
|
442
|
+
contrast_prepend_instance_patch, -1);
|
|
421
443
|
} else {
|
|
422
|
-
rb_define_method(module, cMethodName,
|
|
444
|
+
rb_define_method(module, cMethodName, contrast_prepend_instance_patch, -1);
|
|
423
445
|
}
|
|
424
446
|
} else {
|
|
425
|
-
rb_define_singleton_method(module, cMethodName,
|
|
447
|
+
rb_define_singleton_method(module, cMethodName, contrast_prepend_singleton_patch,
|
|
426
448
|
-1);
|
|
427
449
|
}
|
|
428
450
|
rb_prepend_module(originalModule, module);
|
|
451
|
+
|
|
452
|
+
if (rb_ver_below_three()) {
|
|
453
|
+
VALUE module_at;
|
|
454
|
+
VALUE rb_incl_in_mod_ary = rb_funcall(originalModule, rb_intern("included_in"), 0);
|
|
455
|
+
if (RB_TYPE_P(rb_incl_in_mod_ary, T_ARRAY)) {
|
|
456
|
+
int i = 0;
|
|
457
|
+
int size = rb_funcall(rb_incl_in_mod_ary, rb_intern("length"), 0);
|
|
458
|
+
for (i = 0; i < size; ++i) {
|
|
459
|
+
module_at = rb_ary_entry(rb_incl_in_mod_ary, i);
|
|
460
|
+
if (RB_TYPE_P(module_at, T_MODULE)) {
|
|
461
|
+
rb_include_module(module_at, module);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
429
466
|
return Qtrue;
|
|
430
467
|
}
|
|
431
468
|
|
|
@@ -437,7 +474,6 @@ void Init_cs__contrast_patch(void) {
|
|
|
437
474
|
rb_sym_contrast_apply_pre_patch = rb_intern("apply_pre_patch");
|
|
438
475
|
rb_sym_cs_to_s = rb_intern("to_s");
|
|
439
476
|
rb_sym_custom_patch = rb_intern("requires_custom_patch?");
|
|
440
|
-
rb_sym_in_request_context = rb_intern("in_request_context?");
|
|
441
477
|
rb_sym_info_for = rb_intern("info_for");
|
|
442
478
|
rb_sym_propagation_node = rb_intern("propagation_node");
|
|
443
479
|
rb_sym_set_info_for = rb_intern("set_info_for");
|
|
@@ -16,8 +16,6 @@ static VALUE rb_sym_contrast_apply_pre_patch;
|
|
|
16
16
|
static VALUE rb_sym_custom_patch;
|
|
17
17
|
static VALUE rb_sym_cs_to_s;
|
|
18
18
|
|
|
19
|
-
static VALUE rb_sym_in_request_context;
|
|
20
|
-
|
|
21
19
|
static VALUE rb_sym_enter_method_scope;
|
|
22
20
|
static VALUE rb_sym_exit_method_scope;
|
|
23
21
|
|
|
@@ -148,8 +146,11 @@ VALUE contrast_alias_instance_patch(const int argc, const VALUE *argv,
|
|
|
148
146
|
VALUE contrast_alias_singleton_patch(const int argc, const VALUE *argv,
|
|
149
147
|
const VALUE object);
|
|
150
148
|
|
|
151
|
-
VALUE
|
|
152
|
-
|
|
149
|
+
VALUE contrast_prepend_instance_patch(const int argc, const VALUE *argv,
|
|
150
|
+
const VALUE object);
|
|
151
|
+
|
|
152
|
+
VALUE contrast_prepend_singleton_patch(const int argc, const VALUE *argv,
|
|
153
|
+
const VALUE object);
|
|
153
154
|
|
|
154
155
|
/*
|
|
155
156
|
* Patches a module's method by prepend:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Copyright (c) 2021 Contrast Security, Inc. See
|
|
2
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a for more details. */
|
|
3
|
+
|
|
4
|
+
#include "cs__os_information.h"
|
|
5
|
+
#include <dlfcn.h>
|
|
6
|
+
#include <ruby.h>
|
|
7
|
+
#include <sys/utsname.h>
|
|
8
|
+
|
|
9
|
+
VALUE contrast, utils, os;
|
|
10
|
+
|
|
11
|
+
VALUE contrast_get_system_information()
|
|
12
|
+
{
|
|
13
|
+
struct utsname uname_pointer;
|
|
14
|
+
|
|
15
|
+
uname (&uname_pointer);
|
|
16
|
+
|
|
17
|
+
VALUE rb_data_hash = rb_hash_new();
|
|
18
|
+
rb_hash_aset(rb_data_hash, rb_str_new2("os_type"), rb_str_new2(uname_pointer.sysname));
|
|
19
|
+
rb_hash_aset(rb_data_hash, rb_str_new2("os_version"), rb_str_new2(uname_pointer.release));
|
|
20
|
+
rb_hash_aset(rb_data_hash, rb_str_new2("os_complete_version"), rb_str_new2(uname_pointer.version));
|
|
21
|
+
rb_hash_aset(rb_data_hash, rb_str_new2("os_arch"), rb_str_new2(uname_pointer.machine));
|
|
22
|
+
return rb_data_hash;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void Init_cs__os_information(void)
|
|
26
|
+
{
|
|
27
|
+
contrast = rb_define_module("Contrast");
|
|
28
|
+
utils = rb_define_module_under(contrast, "Utils");
|
|
29
|
+
os = rb_define_module_under(utils, "OS");
|
|
30
|
+
rb_define_module_function(os, "get_system_information", contrast_get_system_information, 0);
|
|
31
|
+
}
|
|
File without changes
|
|
@@ -28,7 +28,6 @@ module Contrast
|
|
|
28
28
|
# @attr_reader args [Array<Contrast::Agent::Assess::ContrastObject>] the safe representation of the Arguments
|
|
29
29
|
# with which the method was invoked
|
|
30
30
|
class ContrastEvent
|
|
31
|
-
|
|
32
31
|
attr_reader :event_id, :policy_node, :stack_trace, :time, :thread, :object, :ret, :args, :tags
|
|
33
32
|
|
|
34
33
|
# We need this to track the parent id's of events to build up a flow chart of the finding
|
|
@@ -55,7 +54,7 @@ module Contrast
|
|
|
55
54
|
|
|
56
55
|
# These methods rely on the above being set. Don't move them!
|
|
57
56
|
@event_id = Contrast::Agent::Assess::ContrastEvent.next_atomic_id
|
|
58
|
-
@tags = Contrast::Agent::Assess::Tracker.properties(tagged)&.
|
|
57
|
+
@tags = Contrast::Agent::Assess::Tracker.properties(tagged)&.get_tags
|
|
59
58
|
find_parent_events!(policy_node, object, ret, args)
|
|
60
59
|
snapshot!(object, ret, args)
|
|
61
60
|
capture_stacktrace!
|
|
@@ -35,10 +35,7 @@ module Contrast
|
|
|
35
35
|
if object
|
|
36
36
|
@object = Contrast::Utils::ClassUtil.to_contrast_string(object)
|
|
37
37
|
@object_type = object.cs__class.cs__name
|
|
38
|
-
|
|
39
|
-
# restore immutability. For instance, if these tags were on a
|
|
40
|
-
# String that was then #reverse!'d, would our tags be wrong?
|
|
41
|
-
@tags = Contrast::Agent::Assess::Tracker.properties(object)&.tags
|
|
38
|
+
@tags = Contrast::Agent::Assess::Tracker.properties(object)&.get_tags
|
|
42
39
|
else
|
|
43
40
|
@object = Contrast::Utils::ObjectShare::NIL_STRING
|
|
44
41
|
@object_type = nil.cs__class.cs__name
|
|
@@ -10,7 +10,6 @@ module Contrast
|
|
|
10
10
|
# An extension of Hash that doesn't impact GC of the object being stored by storing its ID as a Key to lookup
|
|
11
11
|
# and registering a finalizer on the object to remove its entry from the Hash immediately after it's GC'd.
|
|
12
12
|
class Hash < Hash
|
|
13
|
-
|
|
14
13
|
FROZEN_FINALIZED_IDS = Set.new
|
|
15
14
|
|
|
16
15
|
def []= key, obj
|
|
@@ -24,6 +24,8 @@ module Contrast
|
|
|
24
24
|
# the name of the method to taint, mapped to the properties it
|
|
25
25
|
# should apply
|
|
26
26
|
def create_sources klass, tainted_columns
|
|
27
|
+
return unless Contrast::ASSESS.require_dynamic_sources?
|
|
28
|
+
|
|
27
29
|
class_name = klass.cs__name
|
|
28
30
|
instance_methods = klass.instance_methods
|
|
29
31
|
instance_methods.concat(klass.private_instance_methods)
|
|
@@ -12,8 +12,6 @@ module Contrast
|
|
|
12
12
|
# of a file vs data flow, such as the detection of Hardcoded Passwords
|
|
13
13
|
# or Keys.
|
|
14
14
|
module PolicyScanner
|
|
15
|
-
|
|
16
|
-
|
|
17
15
|
class << self
|
|
18
16
|
# Use the given trace_point, built from an :end event, to determine
|
|
19
17
|
# where the loaded code lives and scan that code for policy
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'contrast/components/logger'
|
|
5
|
+
require 'contrast/utils/lru_cache'
|
|
5
6
|
|
|
6
7
|
module Contrast
|
|
7
8
|
module Agent
|
|
@@ -10,8 +11,9 @@ module Contrast
|
|
|
10
11
|
# caused, we'll need to store the state before the change occurred.
|
|
11
12
|
class PreShift
|
|
12
13
|
include Contrast::Components::Logger::InstanceMethods
|
|
14
|
+
extend Contrast::Components::Logger::InstanceMethods
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
@lru_cache = Contrast::Utils::LRUCache.new
|
|
15
17
|
UNDUPLICABLE_MODULES = [
|
|
16
18
|
Enumerator # dup'ing results in 'can't copy execution context'
|
|
17
19
|
].cs__freeze
|
|
@@ -70,29 +72,44 @@ module Contrast
|
|
|
70
72
|
|
|
71
73
|
def append_object_details preshift, initializing, object
|
|
72
74
|
can = can_dup?(initializing, object)
|
|
73
|
-
preshift.object =
|
|
75
|
+
preshift.object = if @lru_cache.key?(object.__id__) && !Contrast::Agent::Assess::Tracker.tracked?(object)
|
|
76
|
+
@lru_cache[object.__id__]
|
|
77
|
+
else
|
|
78
|
+
can ? object.dup : object
|
|
79
|
+
end
|
|
74
80
|
preshift.object_length = if Contrast::Utils::DuckUtils.quacks_to?(preshift.object, :length)
|
|
75
81
|
object.length
|
|
76
82
|
else
|
|
77
83
|
0
|
|
78
84
|
end
|
|
85
|
+
|
|
79
86
|
return unless can
|
|
87
|
+
|
|
80
88
|
return unless Contrast::Agent::Assess::Tracker.tracked?(object)
|
|
81
89
|
|
|
82
90
|
Contrast::Agent::Assess::Tracker.copy(object, preshift.object)
|
|
91
|
+
@lru_cache[object.__id__] = object
|
|
83
92
|
end
|
|
84
93
|
|
|
85
94
|
def append_arg_details preshift, args
|
|
86
|
-
|
|
87
|
-
preshift.args
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
args_length = args.length
|
|
96
|
+
preshift.args = Array.new(args_length)
|
|
97
|
+
preshift.arg_lengths = Array.new(args_length)
|
|
98
|
+
idx = 0
|
|
99
|
+
while idx < args_length
|
|
100
|
+
or_arg = args[idx]
|
|
101
|
+
p_arg = if @lru_cache.key?(or_arg.__id__)
|
|
102
|
+
@lru_cache[or_arg.__id__]
|
|
103
|
+
else
|
|
104
|
+
can_dup?(false, or_arg) ? or_arg.dup : or_arg
|
|
105
|
+
end
|
|
106
|
+
preshift.args[idx] = p_arg
|
|
107
|
+
preshift.arg_lengths[idx] = Contrast::Utils::DuckUtils.quacks_to?(p_arg, :length) ? p_arg.length : 0
|
|
108
|
+
idx += 1
|
|
109
|
+
next if p_arg.__id__ == or_arg.__id__
|
|
110
|
+
|
|
111
|
+
Contrast::Agent::Assess::Tracker.copy(or_arg, p_arg)
|
|
112
|
+
@lru_cache[p_arg.__id__] = p_arg
|
|
96
113
|
end
|
|
97
114
|
end
|
|
98
115
|
end
|