contrast-agent 3.8.5 → 3.9.0

Sign up to get free protection for your applications and to get access to all the features.
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