contrast-agent 3.15.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.c +22 -10
  4. data/ext/cs__assess_marshal_module/cs__assess_marshal_module.h +4 -3
  5. data/lib/contrast/agent.rb +4 -12
  6. data/lib/contrast/agent/assess/contrast_event.rb +121 -130
  7. data/lib/contrast/agent/assess/contrast_object.rb +51 -0
  8. data/lib/contrast/agent/assess/events/source_event.rb +5 -10
  9. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +10 -3
  10. data/lib/contrast/agent/assess/policy/patcher.rb +4 -3
  11. data/lib/contrast/agent/assess/policy/policy_node.rb +46 -69
  12. data/lib/contrast/agent/assess/policy/policy_scanner.rb +19 -2
  13. data/lib/contrast/agent/assess/policy/preshift.rb +3 -3
  14. data/lib/contrast/agent/assess/policy/propagation_method.rb +13 -19
  15. data/lib/contrast/agent/assess/policy/propagation_node.rb +12 -24
  16. data/lib/contrast/agent/assess/policy/propagator/append.rb +1 -2
  17. data/lib/contrast/agent/assess/policy/propagator/center.rb +1 -2
  18. data/lib/contrast/agent/assess/policy/propagator/custom.rb +1 -1
  19. data/lib/contrast/agent/assess/policy/propagator/database_write.rb +1 -3
  20. data/lib/contrast/agent/assess/policy/propagator/insert.rb +2 -3
  21. data/lib/contrast/agent/assess/policy/propagator/keep.rb +1 -2
  22. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +3 -5
  23. data/lib/contrast/agent/assess/policy/propagator/next.rb +1 -2
  24. data/lib/contrast/agent/assess/policy/propagator/prepend.rb +1 -2
  25. data/lib/contrast/agent/assess/policy/propagator/remove.rb +2 -4
  26. data/lib/contrast/agent/assess/policy/propagator/replace.rb +1 -2
  27. data/lib/contrast/agent/assess/policy/propagator/reverse.rb +1 -2
  28. data/lib/contrast/agent/assess/policy/propagator/select.rb +4 -7
  29. data/lib/contrast/agent/assess/policy/propagator/splat.rb +2 -9
  30. data/lib/contrast/agent/assess/policy/propagator/split.rb +77 -122
  31. data/lib/contrast/agent/assess/policy/propagator/substitution.rb +32 -25
  32. data/lib/contrast/agent/assess/policy/propagator/trim.rb +3 -7
  33. data/lib/contrast/agent/assess/policy/source_method.rb +2 -14
  34. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +9 -13
  35. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +1 -1
  36. data/lib/contrast/agent/assess/policy/trigger_method.rb +39 -14
  37. data/lib/contrast/agent/assess/policy/trigger_node.rb +31 -37
  38. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
  39. data/lib/contrast/agent/assess/property/evented.rb +5 -18
  40. data/lib/contrast/agent/assess/property/tagged.rb +28 -16
  41. data/lib/contrast/agent/assess/property/updated.rb +0 -5
  42. data/lib/contrast/agent/assess/rule/provider/hardcoded_key.rb +58 -5
  43. data/lib/contrast/agent/assess/rule/provider/hardcoded_password.rb +23 -8
  44. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +83 -14
  45. data/lib/contrast/agent/assess/rule/redos.rb +1 -1
  46. data/lib/contrast/agent/assess/tag.rb +1 -1
  47. data/lib/contrast/agent/assess/tracker.rb +16 -18
  48. data/lib/contrast/agent/at_exit_hook.rb +5 -5
  49. data/lib/contrast/agent/deadzone/policy/deadzone_node.rb +7 -0
  50. data/lib/contrast/agent/inventory.rb +15 -0
  51. data/lib/contrast/agent/inventory/dependencies.rb +50 -0
  52. data/lib/contrast/agent/inventory/dependency_analysis.rb +37 -0
  53. data/lib/contrast/agent/inventory/dependency_usage_analysis.rb +104 -0
  54. data/lib/contrast/agent/inventory/gemfile_digest_cache.rb +38 -0
  55. data/lib/contrast/agent/middleware.rb +51 -3
  56. data/lib/contrast/agent/patching/policy/after_load_patch.rb +5 -5
  57. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +20 -20
  58. data/lib/contrast/agent/patching/policy/method_policy.rb +1 -1
  59. data/lib/contrast/agent/patching/policy/module_policy.rb +10 -10
  60. data/lib/contrast/agent/patching/policy/patch.rb +6 -0
  61. data/lib/contrast/agent/patching/policy/policy.rb +16 -2
  62. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +3 -5
  63. data/lib/contrast/agent/protect/policy/applies_deserialization_rule.rb +47 -1
  64. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +4 -3
  65. data/lib/contrast/agent/protect/policy/applies_xxe_rule.rb +1 -1
  66. data/lib/contrast/agent/protect/policy/rule_applicator.rb +53 -0
  67. data/lib/contrast/agent/protect/rule/base.rb +63 -14
  68. data/lib/contrast/agent/protect/rule/cmd_injection.rb +12 -28
  69. data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -4
  70. data/lib/contrast/agent/protect/rule/deserialization.rb +4 -1
  71. data/lib/contrast/agent/protect/rule/no_sqli.rb +3 -3
  72. data/lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb +1 -0
  73. data/lib/contrast/agent/protect/rule/sqli.rb +3 -3
  74. data/lib/contrast/agent/protect/rule/xxe.rb +32 -11
  75. data/lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb +10 -6
  76. data/lib/contrast/agent/reaction_processor.rb +1 -1
  77. data/lib/contrast/agent/request.rb +34 -34
  78. data/lib/contrast/agent/request_handler.rb +1 -1
  79. data/lib/contrast/agent/response.rb +5 -5
  80. data/lib/contrast/agent/rewriter.rb +3 -3
  81. data/lib/contrast/agent/scope.rb +81 -55
  82. data/lib/contrast/agent/static_analysis.rb +15 -9
  83. data/lib/contrast/agent/tracepoint_hook.rb +1 -1
  84. data/lib/contrast/agent/version.rb +1 -1
  85. data/lib/contrast/api/communication/socket_client.rb +36 -1
  86. data/lib/contrast/api/decorators.rb +3 -0
  87. data/lib/contrast/api/decorators/address.rb +13 -14
  88. data/lib/contrast/api/decorators/application_update.rb +1 -1
  89. data/lib/contrast/api/decorators/library.rb +54 -0
  90. data/lib/contrast/api/decorators/library_usage_update.rb +31 -0
  91. data/lib/contrast/api/decorators/message.rb +1 -0
  92. data/lib/contrast/api/decorators/trace_event.rb +31 -41
  93. data/lib/contrast/api/decorators/trace_event_object.rb +11 -3
  94. data/lib/contrast/api/decorators/trace_event_signature.rb +27 -5
  95. data/lib/contrast/api/decorators/user_input.rb +2 -1
  96. data/lib/contrast/common_agent_configuration.rb +2 -1
  97. data/lib/contrast/components/agent.rb +6 -5
  98. data/lib/contrast/components/app_context.rb +39 -30
  99. data/lib/contrast/components/assess.rb +36 -0
  100. data/lib/contrast/components/config.rb +29 -37
  101. data/lib/contrast/components/contrast_service.rb +9 -9
  102. data/lib/contrast/components/interface.rb +30 -6
  103. data/lib/contrast/components/inventory.rb +6 -1
  104. data/lib/contrast/components/scope.rb +72 -6
  105. data/lib/contrast/components/settings.rb +23 -23
  106. data/lib/contrast/config/assess_configuration.rb +2 -1
  107. data/lib/contrast/config/inventory_configuration.rb +2 -2
  108. data/lib/contrast/config/service_configuration.rb +4 -2
  109. data/lib/contrast/configuration.rb +1 -1
  110. data/lib/contrast/extension/assess/array.rb +9 -6
  111. data/lib/contrast/extension/assess/erb.rb +6 -3
  112. data/lib/contrast/extension/assess/eval_trigger.rb +6 -6
  113. data/lib/contrast/extension/assess/exec_trigger.rb +0 -3
  114. data/lib/contrast/extension/assess/fiber.rb +5 -6
  115. data/lib/contrast/extension/assess/hash.rb +7 -5
  116. data/lib/contrast/extension/assess/kernel.rb +19 -22
  117. data/lib/contrast/extension/assess/marshal.rb +40 -28
  118. data/lib/contrast/extension/assess/regexp.rb +6 -11
  119. data/lib/contrast/extension/assess/string.rb +14 -13
  120. data/lib/contrast/extension/protect/kernel.rb +3 -3
  121. data/lib/contrast/framework/base_support.rb +51 -53
  122. data/lib/contrast/framework/manager.rb +6 -5
  123. data/lib/contrast/framework/rack/patch/session_cookie.rb +10 -10
  124. data/lib/contrast/framework/rack/support.rb +2 -1
  125. data/lib/contrast/framework/rails/patch/action_controller_live_buffer.rb +14 -14
  126. data/lib/contrast/framework/rails/patch/assess_configuration.rb +1 -1
  127. data/lib/contrast/framework/rails/patch/rails_application_configuration.rb +11 -11
  128. data/lib/contrast/framework/rails/patch/support.rb +1 -1
  129. data/lib/contrast/framework/rails/rewrite/action_controller_railties_helper_inherited.rb +12 -12
  130. data/lib/contrast/framework/rails/rewrite/active_record_attribute_methods_read.rb +13 -13
  131. data/lib/contrast/framework/rails/rewrite/active_record_named.rb +3 -3
  132. data/lib/contrast/framework/rails/rewrite/active_record_time_zone_inherited.rb +13 -13
  133. data/lib/contrast/framework/rails/support.rb +5 -1
  134. data/lib/contrast/framework/sinatra/patch/base.rb +11 -11
  135. data/lib/contrast/framework/sinatra/support.rb +7 -6
  136. data/lib/contrast/logger/application.rb +1 -4
  137. data/lib/contrast/logger/log.rb +7 -2
  138. data/lib/contrast/utils/duck_utils.rb +1 -1
  139. data/lib/contrast/utils/heap_dump_util.rb +1 -1
  140. data/lib/contrast/utils/invalid_configuration_util.rb +2 -5
  141. data/lib/contrast/utils/inventory_util.rb +0 -7
  142. data/lib/contrast/utils/object_share.rb +3 -3
  143. data/lib/contrast/utils/preflight_util.rb +1 -1
  144. data/lib/contrast/utils/prevent_serialization.rb +1 -1
  145. data/lib/contrast/utils/resource_loader.rb +1 -1
  146. data/lib/contrast/utils/sha256_builder.rb +2 -14
  147. data/lib/contrast/utils/string_utils.rb +1 -1
  148. data/lib/contrast/utils/tag_util.rb +9 -13
  149. data/resources/assess/policy.json +31 -12
  150. data/resources/deadzone/policy.json +156 -0
  151. data/resources/protect/policy.json +12 -0
  152. data/ruby-agent.gemspec +11 -6
  153. data/service_executables/VERSION +1 -1
  154. data/service_executables/linux/contrast-service +0 -0
  155. data/service_executables/mac/contrast-service +0 -0
  156. metadata +91 -28
  157. data/lib/contrast/utils/boolean_util.rb +0 -30
  158. data/lib/contrast/utils/gemfile_reader.rb +0 -193
@@ -1,30 +0,0 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
- # frozen_string_literal: true
3
-
4
- require 'contrast/utils/object_share'
5
-
6
- module Contrast
7
- module Utils
8
- # Utility methods for asserting truthy or falsy state of a value expected
9
- # to equate to a boolean
10
- class BooleanUtil
11
- class << self
12
- def false? config
13
- return false if config == true
14
- return true if config == false
15
- return false unless config.cs__is_a?(String)
16
-
17
- Contrast::Utils::ObjectShare::FALSE.casecmp?(config)
18
- end
19
-
20
- def true? config
21
- return false if config == false
22
- return true if config == true
23
- return false unless config.cs__is_a?(String)
24
-
25
- Contrast::Utils::ObjectShare::TRUE.casecmp?(config)
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,193 +0,0 @@
1
- # Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
- # frozen_string_literal: true
3
-
4
- require 'set'
5
- require 'contrast/utils/sha256_builder'
6
- require 'contrast/utils/string_utils'
7
- require 'contrast/components/interface'
8
- require 'contrast/api'
9
-
10
- module Contrast
11
- module Utils
12
- # GemfileReader has methods for extracting information from gem specs
13
- # it also has a cache of library file digests to the lines of code found.
14
- class GemfileReader
15
- include Singleton
16
- include Contrast::Components::Interface
17
-
18
- access_component :config, :logging
19
-
20
- CONTRAST_AGENT = 'contrast-agent'
21
-
22
- def initialize
23
- # Map of a Gem's Spec Digest to all loaded files from that Gem
24
- @spec_to_files = {}
25
- end
26
-
27
- # the #clone is necessary here, as a require in another thread could
28
- # potentially result in adding a key to the loaded_specs hash during
29
- # iteration. (as in RUBY-330)
30
- def loaded_specs
31
- Gem.loaded_specs.clone
32
- end
33
-
34
- # indicates if there's been an update to library information, allowing us
35
- # to only serialize this information on change.
36
- def updated?
37
- @updated
38
- end
39
-
40
- def updated!
41
- @updated = true
42
- end
43
-
44
- # Once we're Contrasted, we intercept require calls to do inventory.
45
- # In order to catch up, we do a one-time manual catchup, & inventory
46
- # all the already-loaded gems.
47
- def map_loaded_classes
48
- loaded_specs.each do |name, spec|
49
- # Don't count Contrast gems
50
- next if contrast_gems.include? name
51
-
52
- # Get a digest of the Gem file itself
53
- next unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
54
-
55
- paths = get_by_digest(digest)
56
- path = spec.full_gem_path
57
- $LOADED_FEATURES.each do |line|
58
- next unless line.cs__is_a?(String)
59
- next unless line.start_with?(path)
60
-
61
- logger.trace('Recording loaded gem for inventory analysis', line: line)
62
- updated!
63
- paths << adjust_lib(line)
64
- end
65
- end
66
- end
67
-
68
- def map_class path
69
- path = adjust_lib(path)
70
-
71
- return unless (spec = Gem::Specification.find_by_path(path))
72
- return unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
73
-
74
- updated!
75
- get_by_digest(digest) << path
76
- end
77
-
78
- def library_pb_list
79
- loaded_specs.each_with_object([]) do |(name, spec), arr|
80
- next if contrast_gems.include? name
81
- next unless spec
82
- next unless (digest = Contrast::Utils::Sha256Builder.build_from_spec(spec))
83
-
84
- arr << build_library_pb(digest, spec)
85
- end
86
- end
87
-
88
- def generate_library_usage activity = nil
89
- return unless updated?
90
-
91
- @spec_to_files.each_pair do |digest, files|
92
- usage = Contrast::Api::Dtm::LibraryUsageUpdate.new
93
- usage.hash_code = Contrast::Utils::StringUtils.force_utf8(digest)
94
- activity.library_usages[usage.hash_code] = usage if activity
95
- # TODO: RUBY-882 once TS switches to take filenames, remove the count setter and
96
- # send the class names in usage.class_names
97
- usage.count = files.size
98
- end
99
- # TODO: RUBY-882 once TS switches to take filenames, clear this and remove the
100
- # @updated variable
101
-
102
- # @spec_to_files.clear
103
- @updated = false
104
- end
105
-
106
- private
107
-
108
- # marker for the lib dir in an absolute file path. purposefully includes
109
- # the trailing '/'
110
- LIB = '/lib/'
111
-
112
- # Kernel#load uses the absolute path, but Gems / Specs use the path after
113
- # `/lib`. This method accounts for that and trims out the `/lib/` section
114
- # and starts with the first `/` after and the trailing file extension, if
115
- # present.
116
- #
117
- # @param path [String] the path to parse
118
- # @return [String] the relative path of the file, after the lib directory
119
- def adjust_lib path
120
- idx = path.index(LIB)
121
- path = path[(idx + 4)..-1] if idx
122
- idx = path.rindex(Contrast::Utils::ObjectShare::PERIOD)
123
- path = path[0..idx] if idx
124
- path
125
- end
126
-
127
- def get_by_digest digest
128
- @spec_to_files[digest] = Set.new unless @spec_to_files.key?(digest)
129
- @spec_to_files[digest]
130
- end
131
-
132
- def build_library_pb digest, spec
133
- lib = Contrast::Api::Dtm::Library.new
134
- lib.file_path = Contrast::Utils::StringUtils.force_utf8(spec.name)
135
- lib.hash_code = Contrast::Utils::StringUtils.force_utf8(digest)
136
- lib.version = Contrast::Utils::StringUtils.force_utf8(spec.version)
137
- lib.manifest = Contrast::Utils::StringUtils.force_utf8(build_manifest(spec))
138
- lib.external_ms = date_to_ms(spec.date)
139
- lib.internal_ms = lib.external_ms
140
- lib.url = Contrast::Utils::StringUtils.force_utf8(spec.homepage)
141
- # Library tags are appended in the ApplicationUpdate delegator
142
- update_class_counts(lib, digest, spec)
143
- lib
144
- end
145
-
146
- def date_to_ms date
147
- (date.to_f * 1000.0).to_i
148
- end
149
-
150
- def update_class_counts lib, digest, spec
151
- # Updating the class counts
152
- path = spec.full_gem_path.to_s
153
- lib.class_count = all_files(path).length
154
- lib.used_class_count = @spec_to_files.key?(digest) ? get_by_digest(digest).size : 0
155
- lib
156
- end
157
-
158
- def build_manifest spec
159
- Contrast::Utils::StringUtils.force_utf8(spec.to_yaml.to_s) if defined?(YAML)
160
- rescue StandardError
161
- nil
162
- end
163
-
164
- # These are all the code files that are located in the Gem directory loaded
165
- # by the current environment; this includes more than Ruby files
166
- def all_files path
167
- Contrast::Utils::Sha256Builder.instance.files(path)
168
- end
169
-
170
- # Go through all dependents, given as a pair from the DependencyList: `dependency`
171
- # is the dependency itself, filled with all its specs. `dependents` is the array of reverse
172
- # dependencies for the aforementioned dependency. If the dependency is also in contrast_dep_set,
173
- # then contrast depends on it. If its array of dependents is 1, then contrast is the
174
- # only dependency in that list. Since only contrast depends on it, we should ignore it.
175
- def contrast_gems
176
- @_contrast_gems ||= find_contrast_gems
177
- end
178
-
179
- def find_contrast_gems
180
- ignore = Set.new([CONTRAST_AGENT])
181
- contrast_specs = Gem::DependencyList.from_specs.specs.find do |dependency|
182
- dependency.name == CONTRAST_AGENT
183
- end
184
- contrast_dep_set = contrast_specs.dependencies.map(&:name).to_set
185
-
186
- Gem::DependencyList.from_specs.spec_predecessors.each_pair do |dependency, dependents|
187
- ignore.add(dependency.name) if contrast_dep_set.include?(dependency.name) && dependents.length == 1
188
- end
189
- ignore
190
- end
191
- end
192
- end
193
- end