contrast-agent 3.8.5 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/cs__assess_array/cs__assess_array.c +1 -1
- data/ext/cs__assess_module/cs__assess_module.c +0 -1
- data/ext/cs__assess_yield_track/cs__assess_yield_track.c +34 -0
- data/ext/cs__assess_yield_track/cs__assess_yield_track.h +12 -0
- data/ext/{cs__scope → cs__assess_yield_track}/extconf.rb +0 -0
- data/ext/cs__common/cs__common.c +6 -6
- data/ext/cs__common/cs__common.h +3 -1
- data/ext/cs__contrast_patch/cs__contrast_patch.c +142 -119
- data/ext/cs__contrast_patch/cs__contrast_patch.h +3 -0
- data/funchook/autom4te.cache/requests +48 -48
- data/funchook/config.log +2 -2
- data/lib/contrast/agent.rb +15 -5
- data/lib/contrast/agent/assess.rb +0 -1
- data/lib/contrast/agent/assess/contrast_event.rb +9 -8
- data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +68 -18
- data/lib/contrast/agent/assess/policy/policy.rb +0 -14
- data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
- data/lib/contrast/agent/assess/policy/preshift.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagation_method.rb +4 -2
- data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -1
- data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -2
- data/lib/contrast/agent/assess/policy/propagator/split.rb +166 -1
- data/lib/contrast/agent/assess/policy/rewriter_patch.rb +1 -0
- data/lib/contrast/agent/assess/policy/source_method.rb +199 -140
- data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +30 -0
- data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +36 -0
- data/lib/contrast/agent/assess/policy/trigger_method.rb +238 -153
- data/lib/contrast/agent/assess/policy/trigger_node.rb +54 -9
- data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +13 -0
- data/lib/contrast/agent/assess/properties.rb +29 -0
- data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +35 -31
- data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +1 -1
- data/lib/contrast/agent/class_reopener.rb +98 -55
- data/lib/contrast/agent/feature_state.rb +1 -1
- data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
- data/lib/contrast/agent/logger_manager.rb +2 -2
- data/lib/contrast/agent/middleware.rb +1 -3
- data/lib/contrast/agent/patching/policy/after_load_patch.rb +40 -4
- data/lib/contrast/agent/patching/policy/after_load_patcher.rb +33 -8
- data/lib/contrast/agent/patching/policy/method_policy.rb +20 -7
- data/lib/contrast/agent/patching/policy/patch.rb +54 -23
- data/lib/contrast/agent/patching/policy/patch_status.rb +0 -2
- data/lib/contrast/agent/patching/policy/patcher.rb +10 -11
- data/lib/contrast/agent/patching/policy/policy.rb +4 -0
- data/lib/contrast/agent/patching/policy/policy_node.rb +14 -1
- data/lib/contrast/agent/patching/policy/trigger_node.rb +2 -1
- data/lib/contrast/agent/protect/policy/policy.rb +6 -6
- data/lib/contrast/agent/protect/rule/base.rb +1 -1
- data/lib/contrast/agent/protect/rule/deserialization.rb +3 -25
- data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
- data/lib/contrast/agent/railtie.rb +11 -5
- data/lib/contrast/agent/request.rb +1 -19
- data/lib/contrast/agent/request_context.rb +1 -1
- data/lib/contrast/agent/rewriter.rb +4 -3
- data/lib/contrast/agent/scope.rb +116 -19
- data/lib/contrast/agent/service_heartbeat.rb +5 -2
- data/lib/contrast/agent/settings_state.rb +12 -8
- data/lib/contrast/agent/version.rb +1 -1
- data/lib/contrast/api.rb +1 -0
- data/lib/contrast/api/speedracer.rb +2 -2
- data/lib/contrast/components/agent.rb +26 -7
- data/lib/contrast/components/app_context.rb +8 -45
- data/lib/contrast/components/contrast_service.rb +3 -4
- data/lib/contrast/components/interface.rb +1 -1
- data/lib/contrast/components/scope.rb +56 -26
- data/lib/contrast/config/ruby_configuration.rb +8 -3
- data/lib/contrast/delegators.rb +9 -0
- data/lib/contrast/delegators/application_update.rb +32 -0
- data/lib/contrast/extensions/framework/rack/cookie.rb +24 -0
- data/lib/contrast/extensions/framework/rack/request.rb +24 -0
- data/lib/contrast/extensions/framework/rack/response.rb +23 -0
- data/lib/contrast/extensions/framework/rails/action_controller_railties_helper_inherited.rb +20 -0
- data/lib/contrast/extensions/framework/rails/active_record.rb +26 -0
- data/lib/contrast/extensions/framework/rails/active_record_named.rb +53 -0
- data/lib/contrast/extensions/framework/rails/active_record_time_zone_inherited.rb +21 -0
- data/lib/contrast/extensions/framework/rails/buffer.rb +28 -0
- data/lib/contrast/extensions/framework/rails/configuration.rb +27 -0
- data/lib/contrast/extensions/framework/sinatra/base.rb +59 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess.rb +12 -11
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/array.rb +4 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/assess_extension.rb +0 -2
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/basic_object.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/erb.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/exec_trigger.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/fiber.rb +3 -4
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/hash.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/kernel.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/module.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/regexp.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/string.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/tilt_template_trigger.rb +0 -0
- data/lib/contrast/extensions/ruby_core/assess/xpath_library_trigger.rb +40 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/delegator.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/eval_trigger.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory/datastores.rb +1 -1
- data/lib/contrast/extensions/ruby_core/module.rb +17 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_command_injection_rule.rb +8 -6
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_deserialization_rule.rb +7 -5
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_no_sqli_rule.rb +5 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_path_traversal_rule.rb +31 -27
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_sqli_rule.rb +5 -3
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_xxe_rule.rb +9 -7
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/kernel.rb +0 -0
- data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/psych.rb +1 -1
- data/lib/contrast/{core_extensions → extensions/ruby_core}/thread.rb +0 -0
- data/lib/contrast/framework/base_support.rb +63 -0
- data/lib/contrast/framework/manager.rb +109 -0
- data/lib/contrast/framework/platform_version.rb +21 -0
- data/lib/contrast/framework/rails_support.rb +88 -0
- data/lib/contrast/framework/sinatra_application_helper.rb +49 -0
- data/lib/contrast/framework/sinatra_support.rb +94 -0
- data/lib/contrast/framework/view_technologies_descriptor.rb +20 -0
- data/lib/contrast/utils/assess/tracking_util.rb +2 -4
- data/lib/contrast/utils/class_util.rb +92 -37
- data/lib/contrast/utils/duck_utils.rb +59 -39
- data/lib/contrast/utils/environment_util.rb +5 -75
- data/lib/contrast/utils/freeze_util.rb +3 -7
- data/lib/contrast/utils/invalid_configuration_util.rb +5 -5
- data/lib/contrast/utils/job_servers_running.rb +39 -0
- data/lib/contrast/utils/ruby_ast_rewriter.rb +2 -2
- data/lib/contrast/utils/service_response_util.rb +0 -6
- data/lib/contrast/utils/sinatra_helper.rb +6 -0
- data/lib/contrast/utils/stack_trace_utils.rb +1 -1
- data/resources/assess/policy.json +74 -23
- data/resources/inventory/policy.json +1 -1
- data/resources/protect/policy.json +11 -9
- data/resources/rubocops/object/frozen_cop.rb +1 -1
- data/ruby-agent.gemspec +2 -0
- data/service_executables/VERSION +1 -1
- data/service_executables/linux/contrast-service +0 -0
- data/service_executables/mac/contrast-service +0 -0
- metadata +94 -57
- data/ext/cs__scope/cs__scope.c +0 -96
- data/ext/cs__scope/cs__scope.h +0 -33
- data/lib/contrast/agent/assess/class_reverter.rb +0 -82
- data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +0 -28
- data/lib/contrast/core_extensions/module.rb +0 -42
- data/lib/contrast/core_extensions/object.rb +0 -27
- data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +0 -48
- data/lib/contrast/rails_extensions/assess/active_record.rb +0 -32
- data/lib/contrast/rails_extensions/assess/active_record_named.rb +0 -61
- data/lib/contrast/rails_extensions/assess/configuration.rb +0 -26
- data/lib/contrast/rails_extensions/buffer.rb +0 -30
- data/lib/contrast/rails_extensions/rack.rb +0 -45
- data/lib/contrast/sinatra_extensions/assess/cookie.rb +0 -26
- data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +0 -59
- data/lib/contrast/utils/operating_environment.rb +0 -38
- data/lib/contrast/utils/path_util.rb +0 -151
- data/lib/contrast/utils/scope_util.rb +0 -99
|
@@ -14,64 +14,64 @@
|
|
|
14
14
|
'configure.ac'
|
|
15
15
|
],
|
|
16
16
|
{
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'AC_CONFIG_SUBDIRS' => 1,
|
|
23
|
-
'AM_NLS' => 1,
|
|
24
|
-
'AC_FC_SRCEXT' => 1,
|
|
25
|
-
'LT_SUPPORTED_TAG' => 1,
|
|
26
|
-
'AC_LIBSOURCE' => 1,
|
|
17
|
+
'AC_CONFIG_LINKS' => 1,
|
|
18
|
+
'AC_INIT' => 1,
|
|
19
|
+
'AM_MAKEFILE_INCLUDE' => 1,
|
|
20
|
+
'_AM_SUBST_NOTMAKE' => 1,
|
|
21
|
+
'AM_SILENT_RULES' => 1,
|
|
27
22
|
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
|
28
|
-
'
|
|
23
|
+
'AC_DEFINE_TRACE_LITERAL' => 1,
|
|
24
|
+
'AM_PROG_F77_C_O' => 1,
|
|
29
25
|
'_LT_AC_TAGCONFIG' => 1,
|
|
26
|
+
'AC_FC_SRCEXT' => 1,
|
|
30
27
|
'_AM_COND_ELSE' => 1,
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'AM_PROG_MOC' => 1,
|
|
39
|
-
'AH_OUTPUT' => 1,
|
|
40
|
-
'AC_FC_PP_SRCEXT' => 1,
|
|
41
|
-
'AM_MAINTAINER_MODE' => 1,
|
|
42
|
-
'AM_PROG_CC_C_O' => 1,
|
|
43
|
-
'AC_CONFIG_LINKS' => 1,
|
|
44
|
-
'_m4_warn' => 1,
|
|
45
|
-
'AM_PROG_CXX_C_O' => 1,
|
|
46
|
-
'LT_INIT' => 1,
|
|
47
|
-
'AM_PATH_GUILE' => 1,
|
|
48
|
-
'LT_CONFIG_LTDL_DIR' => 1,
|
|
28
|
+
'm4_pattern_forbid' => 1,
|
|
29
|
+
'_AM_MAKEFILE_INCLUDE' => 1,
|
|
30
|
+
'AM_INIT_AUTOMAKE' => 1,
|
|
31
|
+
'm4_pattern_allow' => 1,
|
|
32
|
+
'include' => 1,
|
|
33
|
+
'AM_ENABLE_MULTILIB' => 1,
|
|
34
|
+
'AC_CANONICAL_TARGET' => 1,
|
|
49
35
|
'AC_FC_FREEFORM' => 1,
|
|
50
|
-
'AM_XGETTEXT_OPTION' => 1,
|
|
51
36
|
'AM_AUTOMAKE_VERSION' => 1,
|
|
52
|
-
'
|
|
37
|
+
'AM_XGETTEXT_OPTION' => 1,
|
|
38
|
+
'AM_PATH_GUILE' => 1,
|
|
39
|
+
'm4_sinclude' => 1,
|
|
53
40
|
'AC_CANONICAL_SYSTEM' => 1,
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'
|
|
41
|
+
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
|
42
|
+
'AC_SUBST' => 1,
|
|
43
|
+
'LT_INIT' => 1,
|
|
44
|
+
'AM_NLS' => 1,
|
|
45
|
+
'_AM_COND_IF' => 1,
|
|
46
|
+
'AM_GNU_GETTEXT' => 1,
|
|
59
47
|
'AC_FC_PP_DEFINE' => 1,
|
|
60
|
-
'
|
|
61
|
-
'
|
|
48
|
+
'AM_PROG_LIBTOOL' => 1,
|
|
49
|
+
'm4_include' => 1,
|
|
50
|
+
'AM_PROG_AR' => 1,
|
|
51
|
+
'AM_PROG_FC_C_O' => 1,
|
|
52
|
+
'AM_PROG_CXX_C_O' => 1,
|
|
53
|
+
'AM_PROG_CC_C_O' => 1,
|
|
54
|
+
'AC_CONFIG_SUBDIRS' => 1,
|
|
55
|
+
'AM_MAINTAINER_MODE' => 1,
|
|
56
|
+
'AC_PROG_LIBTOOL' => 1,
|
|
62
57
|
'AC_CANONICAL_BUILD' => 1,
|
|
63
|
-
'
|
|
58
|
+
'AM_PROG_MOC' => 1,
|
|
59
|
+
'AC_CANONICAL_HOST' => 1,
|
|
60
|
+
'LT_SUPPORTED_TAG' => 1,
|
|
61
|
+
'AC_CONFIG_HEADERS' => 1,
|
|
62
|
+
'LT_CONFIG_LTDL_DIR' => 1,
|
|
63
|
+
'AC_REQUIRE_AUX_FILE' => 1,
|
|
64
64
|
'AM_CONDITIONAL' => 1,
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
65
|
+
'AC_CONFIG_AUX_DIR' => 1,
|
|
66
|
+
'_AM_COND_ENDIF' => 1,
|
|
67
|
+
'_m4_warn' => 1,
|
|
68
|
+
'AC_LIBSOURCE' => 1,
|
|
69
|
+
'AC_CONFIG_FILES' => 1,
|
|
70
|
+
'AH_OUTPUT' => 1,
|
|
71
|
+
'AC_FC_PP_SRCEXT' => 1,
|
|
72
|
+
'AM_POT_TOOLS' => 1,
|
|
68
73
|
'AC_SUBST_TRACE' => 1,
|
|
69
|
-
'
|
|
70
|
-
'AC_CANONICAL_HOST' => 1,
|
|
71
|
-
'm4_pattern_allow' => 1,
|
|
72
|
-
'AM_GNU_GETTEXT' => 1,
|
|
73
|
-
'AC_CANONICAL_TARGET' => 1,
|
|
74
|
-
'AM_ENABLE_MULTILIB' => 1
|
|
74
|
+
'sinclude' => 1
|
|
75
75
|
}
|
|
76
76
|
], 'Autom4te::Request' )
|
|
77
77
|
);
|
data/funchook/config.log
CHANGED
|
@@ -10,7 +10,7 @@ generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
10
10
|
## Platform. ##
|
|
11
11
|
## --------- ##
|
|
12
12
|
|
|
13
|
-
hostname =
|
|
13
|
+
hostname = b8012d0f-931d-4789-bc7a-4c5ac30dcded-9cnnv
|
|
14
14
|
uname -m = x86_64
|
|
15
15
|
uname -r = 4.19.95-flatcar
|
|
16
16
|
uname -s = Linux
|
|
@@ -326,7 +326,7 @@ generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
326
326
|
CONFIG_COMMANDS =
|
|
327
327
|
$ ./config.status
|
|
328
328
|
|
|
329
|
-
on
|
|
329
|
+
on b8012d0f-931d-4789-bc7a-4c5ac30dcded-9cnnv
|
|
330
330
|
|
|
331
331
|
config.status:822: creating Makefile
|
|
332
332
|
config.status:822: creating src/Makefile
|
data/lib/contrast/agent.rb
CHANGED
|
@@ -6,9 +6,8 @@ cs__scoped_require 'English'
|
|
|
6
6
|
# This must precede other Contrast C extensions
|
|
7
7
|
cs__scoped_require 'cs__common/cs__common'
|
|
8
8
|
|
|
9
|
-
cs__scoped_require 'contrast/
|
|
10
|
-
cs__scoped_require 'contrast/
|
|
11
|
-
cs__scoped_require 'contrast/core_extensions/module'
|
|
9
|
+
cs__scoped_require 'contrast/extensions/ruby_core/delegator'
|
|
10
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
12
11
|
|
|
13
12
|
cs__scoped_require 'contrast/utils/object_share'
|
|
14
13
|
cs__scoped_require 'contrast/utils/boolean_util'
|
|
@@ -32,16 +31,22 @@ cs__scoped_require 'contrast/api'
|
|
|
32
31
|
|
|
33
32
|
cs__scoped_require 'contrast/utils/resource_loader'
|
|
34
33
|
cs__scoped_require 'contrast/utils/duck_utils'
|
|
35
|
-
cs__scoped_require 'contrast/utils/scope_util'
|
|
36
34
|
cs__scoped_require 'contrast/agent/tracepoint_hook'
|
|
37
35
|
cs__scoped_require 'contrast/agent/at_exit_hook'
|
|
38
36
|
|
|
37
|
+
# Framework support
|
|
38
|
+
cs__scoped_require 'contrast/framework/manager'
|
|
39
|
+
|
|
39
40
|
module Contrast
|
|
40
41
|
# Top namespace of the Agent section. Holds tracking contexts that will be
|
|
41
42
|
# accessed throughout the Agent.
|
|
42
43
|
module Agent
|
|
43
44
|
# build a map for tracking the context of the current request
|
|
44
45
|
REQUEST_TRACKER = Contrast::Utils::ThreadTracker.new
|
|
46
|
+
|
|
47
|
+
def self.framework_manager
|
|
48
|
+
@_framework_manager ||= Contrast::Framework::Manager.new
|
|
49
|
+
end
|
|
45
50
|
end
|
|
46
51
|
end
|
|
47
52
|
|
|
@@ -67,7 +72,12 @@ cs__scoped_require 'contrast/agent/assess'
|
|
|
67
72
|
# These happen regardless of analysis mode, & should be lightweight.
|
|
68
73
|
cs__scoped_require 'contrast/utils/rack_assess_session_cookie'
|
|
69
74
|
cs__scoped_require 'contrast/utils/rails_assess_configuration'
|
|
70
|
-
|
|
75
|
+
# Also: should document the necessity of patching this ASAP.
|
|
76
|
+
# In Rails, session configuration occurs extremely early & only once.
|
|
77
|
+
# If we defer our patching of the rails session configuration too long
|
|
78
|
+
# (i.e., where we normally patch) we will miss the configuration
|
|
79
|
+
# and will never be able to report session misconfiguration rules.
|
|
80
|
+
cs__scoped_require 'contrast/extensions/framework/rails/configuration' if defined?(Rails)
|
|
71
81
|
|
|
72
82
|
# protect rules
|
|
73
83
|
cs__scoped_require 'contrast/agent/protect/rule'
|
|
@@ -8,7 +8,6 @@ module Contrast
|
|
|
8
8
|
# class under this namespace should be required here, providing a single
|
|
9
9
|
# point of require for this functionality.
|
|
10
10
|
module Assess
|
|
11
|
-
cs__scoped_require 'contrast/agent/assess/class_reverter'
|
|
12
11
|
cs__scoped_require 'contrast/agent/module_data'
|
|
13
12
|
cs__scoped_require 'contrast/agent/rewriter'
|
|
14
13
|
cs__scoped_require 'contrast/agent/assess/policy/preshift'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
cs__scoped_require 'contrast/utils/class_util'
|
|
4
5
|
cs__scoped_require 'contrast/utils/prevent_serialization'
|
|
5
6
|
|
|
6
7
|
module Contrast
|
|
@@ -23,7 +24,7 @@ module Contrast
|
|
|
23
24
|
rep << if arg.is_a?(Hash)
|
|
24
25
|
safe_arg_hash_representation(arg)
|
|
25
26
|
else
|
|
26
|
-
arg
|
|
27
|
+
Contrast::Utils::ClassUtil.to_contrast_string(arg)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
rep
|
|
@@ -32,7 +33,7 @@ module Contrast
|
|
|
32
33
|
def safe_arg_hash_representation hash
|
|
33
34
|
# since this is the named hash for arguments, only the value is
|
|
34
35
|
# suspect here
|
|
35
|
-
hash.transform_values(
|
|
36
|
+
hash.transform_values { |v| Contrast::Utils::ClassUtil.to_contrast_string(v) }
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# if given an object that can be duped, duplicate it. otherwise just
|
|
@@ -110,26 +111,26 @@ module Contrast
|
|
|
110
111
|
# being called. We'll save all the information, but nothing will be
|
|
111
112
|
# marked up, as nothing need be tracked
|
|
112
113
|
when nil
|
|
113
|
-
@object = object
|
|
114
|
+
@object = Contrast::Utils::ClassUtil.to_contrast_string(object)
|
|
114
115
|
@args = cs__class.safe_args_representation(args)
|
|
115
|
-
@ret = ret
|
|
116
|
+
@ret = Contrast::Utils::ClassUtil.to_contrast_string(ret)
|
|
116
117
|
# If the target is O, then we dup the O and safely represent the rest
|
|
117
118
|
when Contrast::Utils::ObjectShare::OBJECT_KEY
|
|
118
119
|
@object = cs__class.safe_dup(tagged)
|
|
119
120
|
@args = cs__class.safe_args_representation(args)
|
|
120
|
-
@ret = ret
|
|
121
|
+
@ret = Contrast::Utils::ClassUtil.to_contrast_string(ret)
|
|
121
122
|
# If the target is R, then we dup the R and safely represent the rest
|
|
122
123
|
when Contrast::Utils::ObjectShare::RETURN_KEY
|
|
123
|
-
@object = object
|
|
124
|
+
@object = Contrast::Utils::ClassUtil.to_contrast_string(object)
|
|
124
125
|
@args = cs__class.safe_args_representation(args)
|
|
125
126
|
@ret = cs__class.safe_dup(tagged)
|
|
126
127
|
# If the target is P*, then we need to dup things a differently. We
|
|
127
128
|
# need to find the true target inside so that we can mark it up
|
|
128
129
|
# later, but the other args should be represented as their safe form.
|
|
129
130
|
else
|
|
130
|
-
@object = object
|
|
131
|
+
@object = Contrast::Utils::ClassUtil.to_contrast_string(object)
|
|
131
132
|
@args = cs__class.safe_args_representation(args)
|
|
132
|
-
@ret = ret
|
|
133
|
+
@ret = Contrast::Utils::ClassUtil.to_contrast_string(ret)
|
|
133
134
|
save_target_arg(target, tagged)
|
|
134
135
|
end
|
|
135
136
|
end
|
|
@@ -15,26 +15,33 @@ module Contrast
|
|
|
15
15
|
READ_TABLE = 'readTable'
|
|
16
16
|
READ_COLUMN = 'readColumn'
|
|
17
17
|
class << self
|
|
18
|
+
# Given a Class representing a table in a Database and a map of
|
|
19
|
+
# methods representing columns, generate sources for each method
|
|
20
|
+
# such that calls to that method will result in a Source Event.
|
|
21
|
+
#
|
|
22
|
+
# @param klass [Class] the Class to taint
|
|
23
|
+
# @param tainted_columns [Hash<String, Contrast::Agent::Assess::Properties>]
|
|
24
|
+
# the name of the method to taint, mapped to the properties it
|
|
25
|
+
# should apply
|
|
18
26
|
def create_sources klass, tainted_columns
|
|
27
|
+
class_name = klass.cs__name
|
|
19
28
|
instance_methods = klass.instance_methods
|
|
20
29
|
instance_methods.concat(klass.private_instance_methods)
|
|
21
|
-
tainted_columns.each_pair do |field,
|
|
22
|
-
|
|
23
|
-
Contrast::Agent::Assess::Policy::Policy.instance.add_node(dynamic_source_node, :dynamic_source)
|
|
30
|
+
tainted_columns.each_pair do |field, properties|
|
|
31
|
+
next unless properties
|
|
24
32
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
method_policy.instance_method = true
|
|
29
|
-
method_policy.source_node = dynamic_source_node
|
|
30
|
-
Contrast::Agent::Patching::Policy::Patcher.patch_method(klass, instance_methods, method_policy)
|
|
33
|
+
method_name = field.to_sym
|
|
34
|
+
# Move on if we already know about this Dynamic Source
|
|
35
|
+
next if Contrast::Agent::Assess::Policy::Policy.instance.find_source_node(class_name, method_name, true)
|
|
31
36
|
|
|
37
|
+
dynamic_source_node = create_source_node(class_name, method_name, Set.new(properties.tag_keys))
|
|
38
|
+
Contrast::Agent::Assess::Policy::Policy.instance.add_node(dynamic_source_node, :dynamic_source)
|
|
39
|
+
method_policy = build_source_policy(method_name, dynamic_source_node)
|
|
40
|
+
Contrast::Agent::Patching::Policy::Patcher.patch_method(klass, instance_methods, method_policy)
|
|
32
41
|
current_context = Contrast::Agent::REQUEST_TRACKER.current
|
|
42
|
+
next unless current_context
|
|
33
43
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
dynamic_source = create_dynamic_source(current_context, dynamic_source_node, field, events)
|
|
37
|
-
|
|
44
|
+
dynamic_source = create_dynamic_source(current_context, dynamic_source_node, field, properties)
|
|
38
45
|
node_id = Contrast::Utils::StringUtils.force_utf8(dynamic_source_node.id)
|
|
39
46
|
current_context.activity.dynamic_sources[node_id] = dynamic_source
|
|
40
47
|
end
|
|
@@ -42,25 +49,68 @@ module Contrast
|
|
|
42
49
|
|
|
43
50
|
private
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
# Given a class and method, create a SourceNode for them that will
|
|
53
|
+
# add the given tags as well as properties required to construct a
|
|
54
|
+
# finding with a TAINTED_DATABASE source
|
|
55
|
+
#
|
|
56
|
+
# @param class_name [String] the name of the Class to patch
|
|
57
|
+
# @param method_name [Symbol] the name of the Method to patch
|
|
58
|
+
# @param tags [Set<String>] the tags this event should apply
|
|
59
|
+
# @return [Contrast::Agent::Assess::Policy::SourceNode]
|
|
60
|
+
def create_source_node class_name, method_name, tags
|
|
46
61
|
node = Contrast::Agent::Assess::Policy::SourceNode.new
|
|
47
|
-
node.class_name =
|
|
62
|
+
node.class_name = class_name
|
|
48
63
|
node.instance_method = true
|
|
49
|
-
node.method_name =
|
|
64
|
+
node.method_name = method_name
|
|
50
65
|
node.method_visibility = :public
|
|
51
66
|
node.target_string = Contrast::Utils::ObjectShare::RETURN_KEY
|
|
52
67
|
node.type = DB_SOURCE_TYPE
|
|
68
|
+
node.tags = tags
|
|
69
|
+
node.tags << 'DATABASE_WRITE'
|
|
53
70
|
node.add_property('dynamic_source_id', node.id)
|
|
71
|
+
node.add_property('dynamic_source_name', "#{ class_name }.#{ method_name }")
|
|
72
|
+
node.add_property(READ_TABLE, class_name)
|
|
73
|
+
node.add_property(READ_COLUMN, method_name)
|
|
74
|
+
node.add_property(WRITE_QUERY_TIME, Contrast::Utils::Timer.now_ms)
|
|
75
|
+
url = Contrast::Agent::REQUEST_TRACKER.current&.request&.normalized_uri
|
|
76
|
+
node.add_property(WRITE_QUERY_URL, url)
|
|
54
77
|
node
|
|
55
78
|
end
|
|
56
79
|
|
|
57
|
-
|
|
80
|
+
# @param method_name [Symbol] the name of the Method to which this
|
|
81
|
+
# method applies
|
|
82
|
+
# @param dynamic_source_node [Contrast::Api::Dtm::DynamicSource]
|
|
83
|
+
# the SourceNode that applies to this method
|
|
84
|
+
# @return [Contrast::Agent::Patching::Policy::MethodPolicy] the
|
|
85
|
+
# policy to apply to the given method
|
|
86
|
+
def build_source_policy method_name, dynamic_source_node
|
|
87
|
+
method_policy = Contrast::Agent::Patching::Policy::MethodPolicy.new
|
|
88
|
+
method_policy.method_visibility = :public
|
|
89
|
+
method_policy.instance_method = true
|
|
90
|
+
method_policy.method_name = method_name
|
|
91
|
+
method_policy.source_node = dynamic_source_node
|
|
92
|
+
method_policy
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param current_context [Contrast::Agent::RequestContext] the
|
|
96
|
+
# context of the request in which this source is to be created.
|
|
97
|
+
# @param source_node [Contrast::Agent::Assess::Policy::SourceNode]
|
|
98
|
+
# the SourceNode that applies to this method
|
|
99
|
+
# @param field [String] the name of the method to which this source
|
|
100
|
+
# applies
|
|
101
|
+
# @param properties [Contrast::Agent::Assess::Properties] the
|
|
102
|
+
# properties which this source should relate to the data tracked
|
|
103
|
+
# as a result of this Source Method
|
|
104
|
+
# @return [Contrast::Api::Dtm::DynamicSource] the message to send
|
|
105
|
+
# to the Service to allow it to report the events leading up to
|
|
106
|
+
# the creation of the Dynamic Source
|
|
107
|
+
def create_dynamic_source current_context, source_node, field, properties
|
|
58
108
|
dynamic_source = Contrast::Api::Dtm::DynamicSource.new
|
|
59
109
|
dynamic_source.class_name = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
|
|
60
110
|
dynamic_source.method_name = Contrast::Utils::StringUtils.force_utf8(field)
|
|
61
111
|
dynamic_source.instance_method = source_node.instance_method?
|
|
62
112
|
dynamic_source.target = Contrast::Utils::StringUtils.force_utf8(source_node.target_string)
|
|
63
|
-
events.each do |event|
|
|
113
|
+
properties.events.each do |event|
|
|
64
114
|
dynamic_source.events << event.to_dtm_event
|
|
65
115
|
end
|
|
66
116
|
dynamic_source.properties[READ_TABLE] = Contrast::Utils::StringUtils.force_utf8(source_node.class_name)
|
|
@@ -95,20 +95,6 @@ module Contrast
|
|
|
95
95
|
Contrast::Agent::Assess::Rule::Provider::HardcodedKey,
|
|
96
96
|
Contrast::Agent::Assess::Rule::Provider::HardcodedPassword
|
|
97
97
|
].cs__freeze
|
|
98
|
-
|
|
99
|
-
# Handles updating the dynamic sources of this Application and indicates
|
|
100
|
-
# if doing so results in a state that requires repatching -- i.e. new
|
|
101
|
-
# dynamic sources have been discovered by agents monitoring other
|
|
102
|
-
# instances of this application
|
|
103
|
-
def update_dynamic_sources dynamic_sources_map
|
|
104
|
-
dynamic_sources_map.each do |key, dynamic_source|
|
|
105
|
-
# key is the dynamic source node id
|
|
106
|
-
next if sources.any? { |source| source.id == key }
|
|
107
|
-
|
|
108
|
-
dynamic_source_node = Contrast::Agent::Assess::Policy::SourceNode.build_dynamic_source(key, dynamic_source)
|
|
109
|
-
add_node(dynamic_source_node, :dynamic_source)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
98
|
end
|
|
113
99
|
end
|
|
114
100
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
cs__scoped_require 'contrast/utils/object_share'
|
|
5
5
|
cs__scoped_require 'contrast/components/interface'
|
|
6
|
-
cs__scoped_require 'contrast/
|
|
6
|
+
cs__scoped_require 'contrast/extensions/ruby_core/assess/assess_extension'
|
|
7
7
|
|
|
8
8
|
module Contrast
|
|
9
9
|
module Agent
|
|
@@ -58,7 +58,7 @@ module Contrast
|
|
|
58
58
|
private
|
|
59
59
|
|
|
60
60
|
def unsafe_io_object? object, initializing
|
|
61
|
-
Contrast::Utils::DuckUtils.
|
|
61
|
+
Contrast::Utils::DuckUtils.closable_io?(object) && !initializing && object.closed?
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def can_dup? initializing, object
|
|
@@ -98,9 +98,9 @@ module Contrast
|
|
|
98
98
|
"Propagator #{ propagation_node.id } detected: propagated to #{ target.__id__ }")
|
|
99
99
|
elsif Contrast::Utils::DuckUtils.quacks_to?(target, :cs__properties)
|
|
100
100
|
handle_cs_properties_propagation(propagation_node, preshift, target, object, ret, invoked, args, block)
|
|
101
|
-
elsif Contrast::Utils::DuckUtils.
|
|
101
|
+
elsif Contrast::Utils::DuckUtils.iterable_hash?(target)
|
|
102
102
|
handle_hash_propagation(propagation_node, preshift, target, object, ret, invoked, args, block)
|
|
103
|
-
elsif Contrast::Utils::DuckUtils.
|
|
103
|
+
elsif Contrast::Utils::DuckUtils.iterable_enumerable?(target)
|
|
104
104
|
handle_enumerable_propagation(propagation_node, preshift, target, object, ret, invoked, args, block)
|
|
105
105
|
end
|
|
106
106
|
rescue StandardError => e
|
|
@@ -227,6 +227,8 @@ module Contrast
|
|
|
227
227
|
ret = Contrast::Utils::FreezeUtil.unfreeze_dup(target)
|
|
228
228
|
target = ret
|
|
229
229
|
end
|
|
230
|
+
return if target.cs__properties == Contrast::Agent::Assess::Insulator.generate_frozen.properties
|
|
231
|
+
|
|
230
232
|
propagation_class.propagate(propagation_node, preshift, target)
|
|
231
233
|
|
|
232
234
|
# Once we've propagated, attempt to tag the target if there is a tag(s) to be applied
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
cs__scoped_require 'contrast/
|
|
4
|
+
cs__scoped_require 'contrast/extensions/ruby_core/module'
|
|
5
5
|
|
|
6
6
|
module Contrast
|
|
7
7
|
module Agent
|
|
@@ -36,7 +36,7 @@ module Contrast
|
|
|
36
36
|
value.cs__properties.build_event(propagation_node, value, preshift.object, target, preshift.args)
|
|
37
37
|
next unless tracked_value?(value)
|
|
38
38
|
|
|
39
|
-
tainted_columns[key] = value.cs__properties
|
|
39
|
+
tainted_columns[key] = value.cs__properties
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|