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.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cs__assess_array/cs__assess_array.c +1 -1
  3. data/ext/cs__assess_module/cs__assess_module.c +0 -1
  4. data/ext/cs__assess_yield_track/cs__assess_yield_track.c +34 -0
  5. data/ext/cs__assess_yield_track/cs__assess_yield_track.h +12 -0
  6. data/ext/{cs__scope → cs__assess_yield_track}/extconf.rb +0 -0
  7. data/ext/cs__common/cs__common.c +6 -6
  8. data/ext/cs__common/cs__common.h +3 -1
  9. data/ext/cs__contrast_patch/cs__contrast_patch.c +142 -119
  10. data/ext/cs__contrast_patch/cs__contrast_patch.h +3 -0
  11. data/funchook/autom4te.cache/requests +48 -48
  12. data/funchook/config.log +2 -2
  13. data/lib/contrast/agent.rb +15 -5
  14. data/lib/contrast/agent/assess.rb +0 -1
  15. data/lib/contrast/agent/assess/contrast_event.rb +9 -8
  16. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +68 -18
  17. data/lib/contrast/agent/assess/policy/policy.rb +0 -14
  18. data/lib/contrast/agent/assess/policy/policy_scanner.rb +1 -1
  19. data/lib/contrast/agent/assess/policy/preshift.rb +1 -1
  20. data/lib/contrast/agent/assess/policy/propagation_method.rb +4 -2
  21. data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
  22. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -1
  23. data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -2
  24. data/lib/contrast/agent/assess/policy/propagator/split.rb +166 -1
  25. data/lib/contrast/agent/assess/policy/rewriter_patch.rb +1 -0
  26. data/lib/contrast/agent/assess/policy/source_method.rb +199 -140
  27. data/lib/contrast/agent/assess/policy/source_validation/cross_site_validator.rb +30 -0
  28. data/lib/contrast/agent/assess/policy/source_validation/source_validation.rb +36 -0
  29. data/lib/contrast/agent/assess/policy/trigger_method.rb +238 -153
  30. data/lib/contrast/agent/assess/policy/trigger_node.rb +54 -9
  31. data/lib/contrast/agent/assess/policy/trigger_validation/trigger_validation.rb +13 -0
  32. data/lib/contrast/agent/assess/properties.rb +29 -0
  33. data/lib/contrast/agent/assess/rule/csrf/csrf_applicator.rb +35 -31
  34. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +1 -1
  35. data/lib/contrast/agent/class_reopener.rb +98 -55
  36. data/lib/contrast/agent/feature_state.rb +1 -1
  37. data/lib/contrast/agent/inventory/policy/policy.rb +1 -1
  38. data/lib/contrast/agent/logger_manager.rb +2 -2
  39. data/lib/contrast/agent/middleware.rb +1 -3
  40. data/lib/contrast/agent/patching/policy/after_load_patch.rb +40 -4
  41. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +33 -8
  42. data/lib/contrast/agent/patching/policy/method_policy.rb +20 -7
  43. data/lib/contrast/agent/patching/policy/patch.rb +54 -23
  44. data/lib/contrast/agent/patching/policy/patch_status.rb +0 -2
  45. data/lib/contrast/agent/patching/policy/patcher.rb +10 -11
  46. data/lib/contrast/agent/patching/policy/policy.rb +4 -0
  47. data/lib/contrast/agent/patching/policy/policy_node.rb +14 -1
  48. data/lib/contrast/agent/patching/policy/trigger_node.rb +2 -1
  49. data/lib/contrast/agent/protect/policy/policy.rb +6 -6
  50. data/lib/contrast/agent/protect/rule/base.rb +1 -1
  51. data/lib/contrast/agent/protect/rule/deserialization.rb +3 -25
  52. data/lib/contrast/agent/protect/rule/sqli.rb +1 -1
  53. data/lib/contrast/agent/railtie.rb +11 -5
  54. data/lib/contrast/agent/request.rb +1 -19
  55. data/lib/contrast/agent/request_context.rb +1 -1
  56. data/lib/contrast/agent/rewriter.rb +4 -3
  57. data/lib/contrast/agent/scope.rb +116 -19
  58. data/lib/contrast/agent/service_heartbeat.rb +5 -2
  59. data/lib/contrast/agent/settings_state.rb +12 -8
  60. data/lib/contrast/agent/version.rb +1 -1
  61. data/lib/contrast/api.rb +1 -0
  62. data/lib/contrast/api/speedracer.rb +2 -2
  63. data/lib/contrast/components/agent.rb +26 -7
  64. data/lib/contrast/components/app_context.rb +8 -45
  65. data/lib/contrast/components/contrast_service.rb +3 -4
  66. data/lib/contrast/components/interface.rb +1 -1
  67. data/lib/contrast/components/scope.rb +56 -26
  68. data/lib/contrast/config/ruby_configuration.rb +8 -3
  69. data/lib/contrast/delegators.rb +9 -0
  70. data/lib/contrast/delegators/application_update.rb +32 -0
  71. data/lib/contrast/extensions/framework/rack/cookie.rb +24 -0
  72. data/lib/contrast/extensions/framework/rack/request.rb +24 -0
  73. data/lib/contrast/extensions/framework/rack/response.rb +23 -0
  74. data/lib/contrast/extensions/framework/rails/action_controller_railties_helper_inherited.rb +20 -0
  75. data/lib/contrast/extensions/framework/rails/active_record.rb +26 -0
  76. data/lib/contrast/extensions/framework/rails/active_record_named.rb +53 -0
  77. data/lib/contrast/extensions/framework/rails/active_record_time_zone_inherited.rb +21 -0
  78. data/lib/contrast/extensions/framework/rails/buffer.rb +28 -0
  79. data/lib/contrast/extensions/framework/rails/configuration.rb +27 -0
  80. data/lib/contrast/extensions/framework/sinatra/base.rb +59 -0
  81. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess.rb +12 -11
  82. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/array.rb +4 -3
  83. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/assess_extension.rb +0 -2
  84. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/basic_object.rb +1 -1
  85. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/erb.rb +0 -0
  86. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/exec_trigger.rb +0 -0
  87. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/fiber.rb +3 -4
  88. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/hash.rb +0 -0
  89. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/kernel.rb +1 -1
  90. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/module.rb +1 -1
  91. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/regexp.rb +0 -0
  92. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/string.rb +0 -0
  93. data/lib/contrast/{core_extensions → extensions/ruby_core}/assess/tilt_template_trigger.rb +0 -0
  94. data/lib/contrast/extensions/ruby_core/assess/xpath_library_trigger.rb +40 -0
  95. data/lib/contrast/{core_extensions → extensions/ruby_core}/delegator.rb +0 -0
  96. data/lib/contrast/{core_extensions → extensions/ruby_core}/eval_trigger.rb +1 -1
  97. data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory.rb +0 -0
  98. data/lib/contrast/{core_extensions → extensions/ruby_core}/inventory/datastores.rb +1 -1
  99. data/lib/contrast/extensions/ruby_core/module.rb +17 -0
  100. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect.rb +0 -0
  101. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_command_injection_rule.rb +8 -6
  102. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_deserialization_rule.rb +7 -5
  103. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_no_sqli_rule.rb +5 -3
  104. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_path_traversal_rule.rb +31 -27
  105. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_sqli_rule.rb +5 -3
  106. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/applies_xxe_rule.rb +9 -7
  107. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/kernel.rb +0 -0
  108. data/lib/contrast/{core_extensions → extensions/ruby_core}/protect/psych.rb +1 -1
  109. data/lib/contrast/{core_extensions → extensions/ruby_core}/thread.rb +0 -0
  110. data/lib/contrast/framework/base_support.rb +63 -0
  111. data/lib/contrast/framework/manager.rb +109 -0
  112. data/lib/contrast/framework/platform_version.rb +21 -0
  113. data/lib/contrast/framework/rails_support.rb +88 -0
  114. data/lib/contrast/framework/sinatra_application_helper.rb +49 -0
  115. data/lib/contrast/framework/sinatra_support.rb +94 -0
  116. data/lib/contrast/framework/view_technologies_descriptor.rb +20 -0
  117. data/lib/contrast/utils/assess/tracking_util.rb +2 -4
  118. data/lib/contrast/utils/class_util.rb +92 -37
  119. data/lib/contrast/utils/duck_utils.rb +59 -39
  120. data/lib/contrast/utils/environment_util.rb +5 -75
  121. data/lib/contrast/utils/freeze_util.rb +3 -7
  122. data/lib/contrast/utils/invalid_configuration_util.rb +5 -5
  123. data/lib/contrast/utils/job_servers_running.rb +39 -0
  124. data/lib/contrast/utils/ruby_ast_rewriter.rb +2 -2
  125. data/lib/contrast/utils/service_response_util.rb +0 -6
  126. data/lib/contrast/utils/sinatra_helper.rb +6 -0
  127. data/lib/contrast/utils/stack_trace_utils.rb +1 -1
  128. data/resources/assess/policy.json +74 -23
  129. data/resources/inventory/policy.json +1 -1
  130. data/resources/protect/policy.json +11 -9
  131. data/resources/rubocops/object/frozen_cop.rb +1 -1
  132. data/ruby-agent.gemspec +2 -0
  133. data/service_executables/VERSION +1 -1
  134. data/service_executables/linux/contrast-service +0 -0
  135. data/service_executables/mac/contrast-service +0 -0
  136. metadata +94 -57
  137. data/ext/cs__scope/cs__scope.c +0 -96
  138. data/ext/cs__scope/cs__scope.h +0 -33
  139. data/lib/contrast/agent/assess/class_reverter.rb +0 -82
  140. data/lib/contrast/agent/patching/policy/policy_unpatcher.rb +0 -28
  141. data/lib/contrast/core_extensions/module.rb +0 -42
  142. data/lib/contrast/core_extensions/object.rb +0 -27
  143. data/lib/contrast/rails_extensions/assess/action_controller_inheritance.rb +0 -48
  144. data/lib/contrast/rails_extensions/assess/active_record.rb +0 -32
  145. data/lib/contrast/rails_extensions/assess/active_record_named.rb +0 -61
  146. data/lib/contrast/rails_extensions/assess/configuration.rb +0 -26
  147. data/lib/contrast/rails_extensions/buffer.rb +0 -30
  148. data/lib/contrast/rails_extensions/rack.rb +0 -45
  149. data/lib/contrast/sinatra_extensions/assess/cookie.rb +0 -26
  150. data/lib/contrast/sinatra_extensions/inventory/sinatra_base.rb +0 -59
  151. data/lib/contrast/utils/operating_environment.rb +0 -38
  152. data/lib/contrast/utils/path_util.rb +0 -151
  153. data/lib/contrast/utils/scope_util.rb +0 -99
@@ -14,64 +14,64 @@
14
14
  'configure.ac'
15
15
  ],
16
16
  {
17
- 'AC_PROG_LIBTOOL' => 1,
18
- 'm4_sinclude' => 1,
19
- 'AM_PROG_F77_C_O' => 1,
20
- 'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
21
- 'AM_POT_TOOLS' => 1,
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
- 'sinclude' => 1,
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
- 'AM_PROG_LIBTOOL' => 1,
32
- 'AC_SUBST' => 1,
33
- '_AM_COND_ENDIF' => 1,
34
- 'AM_PROG_FC_C_O' => 1,
35
- '_AM_SUBST_NOTMAKE' => 1,
36
- 'AC_CONFIG_FILES' => 1,
37
- 'AC_REQUIRE_AUX_FILE' => 1,
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
- 'include' => 1,
37
+ 'AM_XGETTEXT_OPTION' => 1,
38
+ 'AM_PATH_GUILE' => 1,
39
+ 'm4_sinclude' => 1,
53
40
  'AC_CANONICAL_SYSTEM' => 1,
54
- 'AM_INIT_AUTOMAKE' => 1,
55
- 'm4_pattern_forbid' => 1,
56
- 'AC_CONFIG_AUX_DIR' => 1,
57
- 'AM_SILENT_RULES' => 1,
58
- 'AM_PROG_AR' => 1,
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
- 'AC_CONFIG_HEADERS' => 1,
61
- '_AM_MAKEFILE_INCLUDE' => 1,
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
- 'AM_MAKEFILE_INCLUDE' => 1,
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
- 'm4_include' => 1,
66
- 'AC_INIT' => 1,
67
- 'AC_DEFINE_TRACE_LITERAL' => 1,
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
- '_AM_COND_IF' => 1,
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
  );
@@ -10,7 +10,7 @@ generated by GNU Autoconf 2.69. Invocation command line was
10
10
  ## Platform. ##
11
11
  ## --------- ##
12
12
 
13
- hostname = 190fbedb-dc16-42d3-8ff7-6ac407e6f5f6-sf5wp
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 190fbedb-dc16-42d3-8ff7-6ac407e6f5f6-sf5wp
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
@@ -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/core_extensions/object'
10
- cs__scoped_require 'contrast/core_extensions/delegator'
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
- cs__scoped_require 'contrast/rails_extensions/assess/configuration'
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.cs__inspect
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(&:cs__inspect)
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.cs__inspect
114
+ @object = Contrast::Utils::ClassUtil.to_contrast_string(object)
114
115
  @args = cs__class.safe_args_representation(args)
115
- @ret = ret.cs__inspect
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.cs__inspect
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.cs__inspect
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.cs__inspect
131
+ @object = Contrast::Utils::ClassUtil.to_contrast_string(object)
131
132
  @args = cs__class.safe_args_representation(args)
132
- @ret = ret.cs__inspect
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, events|
22
- dynamic_source_node = create_source_node(klass, field)
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
- method_policy = Contrast::Agent::Patching::Policy::MethodPolicy.new
26
- method_policy.method_name = field.to_sym
27
- method_policy.method_visibility = :public
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
- next unless current_context.activity.dynamic_sources[dynamic_source_node.id]
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
- def create_source_node klass, field
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 = klass.cs__name
62
+ node.class_name = class_name
48
63
  node.instance_method = true
49
- node.method_name = field.to_sym
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
- def create_dynamic_source current_context, source_node, field, events
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/core_extensions/assess/assess_extension'
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.quacks_like_closable_io(object) && !initializing && object.closed?
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.quacks_like_tracked_hash?(target)
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.quacks_like_tracked_enumerable?(target)
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/core_extensions/module'
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.events
39
+ tainted_columns[key] = value.cs__properties
40
40
  end
41
41
  end
42
42