contrast-agent 6.7.0 → 6.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.simplecov +0 -1
  4. data/Rakefile +0 -1
  5. data/ext/cs__assess_array/cs__assess_array.c +41 -10
  6. data/ext/cs__assess_array/cs__assess_array.h +4 -1
  7. data/lib/contrast/agent/assess/policy/trigger_method.rb +2 -2
  8. data/lib/contrast/agent/assess/policy/trigger_validation/redos_validator.rb +1 -1
  9. data/lib/contrast/agent/assess/policy/trigger_validation/ssrf_validator.rb +1 -1
  10. data/lib/contrast/agent/assess/policy/trigger_validation/xss_validator.rb +1 -1
  11. data/lib/contrast/agent/excluder.rb +52 -34
  12. data/lib/contrast/agent/exclusion_matcher.rb +21 -9
  13. data/lib/contrast/agent/middleware.rb +4 -4
  14. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +6 -0
  15. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +146 -127
  16. data/lib/contrast/agent/protect/policy/applies_path_traversal_rule.rb +20 -0
  17. data/lib/contrast/agent/protect/policy/rule_applicator.rb +1 -1
  18. data/lib/contrast/agent/protect/rule/base.rb +45 -53
  19. data/lib/contrast/agent/protect/rule/base_service.rb +48 -24
  20. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +98 -0
  21. data/lib/contrast/agent/protect/rule/bot_blocker.rb +81 -0
  22. data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -1
  23. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +8 -5
  24. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +22 -22
  25. data/lib/contrast/agent/protect/rule/cmdi/cmdi_chained_command.rb +69 -0
  26. data/lib/contrast/agent/protect/rule/cmdi/cmdi_dangerous_path.rb +68 -0
  27. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +2 -58
  28. data/lib/contrast/agent/protect/rule/default_scanner.rb +1 -1
  29. data/lib/contrast/agent/protect/rule/deserialization.rb +3 -14
  30. data/lib/contrast/agent/protect/rule/http_method_tampering/http_method_tampering_input_classification.rb +2 -2
  31. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +0 -11
  32. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +29 -34
  33. data/lib/contrast/agent/protect/rule/no_sqli.rb +25 -18
  34. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_input_classification.rb +61 -0
  35. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_semantic_security_bypass.rb +114 -0
  36. data/lib/contrast/agent/protect/rule/path_traversal.rb +38 -12
  37. data/lib/contrast/agent/protect/rule/sql_sample_builder.rb +33 -15
  38. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +0 -14
  39. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -62
  40. data/lib/contrast/agent/protect/rule/sqli.rb +70 -0
  41. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +39 -63
  42. data/lib/contrast/agent/protect/rule/unsafe_file_upload.rb +6 -33
  43. data/lib/contrast/agent/protect/rule/xss/reflected_xss_input_classification.rb +58 -0
  44. data/lib/contrast/agent/protect/rule/xss.rb +14 -20
  45. data/lib/contrast/agent/protect/rule/xxe.rb +4 -24
  46. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +18 -39
  47. data/lib/contrast/agent/reporting/attack_result/response_type.rb +9 -9
  48. data/lib/contrast/agent/reporting/details/ip_denylist_details.rb +10 -2
  49. data/lib/contrast/agent/reporting/details/virtual_patch_details.rb +8 -2
  50. data/lib/contrast/agent/reporting/input_analysis/details/bot_blocker_details.rb +27 -0
  51. data/lib/contrast/agent/reporting/input_analysis/details/protect_rule_details.rb +15 -0
  52. data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +1 -2
  53. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +16 -2
  54. data/lib/contrast/agent/reporting/masker/masker.rb +2 -0
  55. data/lib/contrast/agent/reporting/reporter.rb +1 -14
  56. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +15 -12
  57. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_activity.rb +3 -3
  58. data/lib/contrast/agent/reporting/reporting_events/application_defend_attack_sample.rb +1 -2
  59. data/lib/contrast/agent/reporting/reporting_events/application_update.rb +0 -2
  60. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -1
  61. data/lib/contrast/agent/reporting/reporting_events/finding.rb +4 -4
  62. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +0 -5
  63. data/lib/contrast/agent/reporting/reporting_events/library_discovery.rb +0 -1
  64. data/lib/contrast/agent/reporting/reporting_events/poll.rb +1 -11
  65. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +0 -1
  66. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +0 -1
  67. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +2 -2
  68. data/lib/contrast/agent/reporting/reporting_utilities/response.rb +1 -1
  69. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +0 -3
  70. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +1 -0
  71. data/lib/contrast/agent/reporting/settings/code_exclusion.rb +6 -1
  72. data/lib/contrast/agent/reporting/settings/exclusion_base.rb +18 -0
  73. data/lib/contrast/agent/reporting/settings/exclusions.rb +2 -1
  74. data/lib/contrast/agent/reporting/settings/input_exclusion.rb +9 -3
  75. data/lib/contrast/agent/reporting/settings/protect.rb +15 -15
  76. data/lib/contrast/agent/request.rb +2 -14
  77. data/lib/contrast/agent/request_context.rb +6 -9
  78. data/lib/contrast/agent/request_context_extend.rb +9 -148
  79. data/lib/contrast/agent/thread_watcher.rb +3 -18
  80. data/lib/contrast/agent/version.rb +1 -1
  81. data/lib/contrast/agent.rb +0 -11
  82. data/lib/contrast/agent_lib/api/command_injection.rb +46 -0
  83. data/lib/contrast/agent_lib/api/init.rb +101 -0
  84. data/lib/contrast/agent_lib/api/input_tracing.rb +267 -0
  85. data/lib/contrast/agent_lib/api/method_tempering.rb +29 -0
  86. data/lib/contrast/agent_lib/api/panic.rb +87 -0
  87. data/lib/contrast/agent_lib/api/path_semantic_file_security_bypass.rb +40 -0
  88. data/lib/contrast/agent_lib/interface.rb +260 -0
  89. data/lib/contrast/agent_lib/interface_base.rb +118 -0
  90. data/lib/contrast/agent_lib/return_types/eval_result.rb +44 -0
  91. data/lib/contrast/agent_lib/test.rb +29 -0
  92. data/lib/contrast/api/communication/connection_status.rb +5 -5
  93. data/lib/contrast/components/agent.rb +0 -14
  94. data/lib/contrast/components/app_context.rb +0 -2
  95. data/lib/contrast/components/app_context_extend.rb +0 -25
  96. data/lib/contrast/components/config.rb +1 -18
  97. data/lib/contrast/components/protect.rb +4 -1
  98. data/lib/contrast/components/ruby_component.rb +1 -1
  99. data/lib/contrast/components/settings.rb +37 -89
  100. data/lib/contrast/config/protect_rule_configuration.rb +7 -7
  101. data/lib/contrast/config/protect_rules_configuration.rb +20 -58
  102. data/lib/contrast/configuration.rb +1 -10
  103. data/lib/contrast/extension/assess/array.rb +9 -0
  104. data/lib/contrast/extension/delegator.rb +2 -0
  105. data/lib/contrast/framework/manager.rb +3 -1
  106. data/lib/contrast/framework/rails/railtie.rb +0 -1
  107. data/lib/contrast/framework/rails/support.rb +0 -1
  108. data/lib/contrast/tasks/config.rb +1 -8
  109. data/lib/contrast/utils/duck_utils.rb +1 -0
  110. data/lib/contrast/utils/input_classification_base.rb +156 -0
  111. data/lib/contrast/utils/os.rb +0 -20
  112. data/lib/contrast/utils/response_utils.rb +0 -16
  113. data/lib/contrast/utils/stack_trace_utils.rb +3 -15
  114. data/lib/contrast/utils/string_utils.rb +10 -7
  115. data/lib/contrast.rb +2 -3
  116. data/resources/protect/policy.json +1 -2
  117. data/ruby-agent.gemspec +2 -5
  118. metadata +42 -112
  119. data/exe/contrast_service +0 -23
  120. data/lib/contrast/agent/protect/rule/cmdi/cmdi_worth_watching.rb +0 -64
  121. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +0 -118
  122. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_matcher.rb +0 -45
  123. data/lib/contrast/agent/reaction_processor.rb +0 -47
  124. data/lib/contrast/agent/service_heartbeat.rb +0 -35
  125. data/lib/contrast/api/communication/messaging_queue.rb +0 -128
  126. data/lib/contrast/api/communication/response_processor.rb +0 -90
  127. data/lib/contrast/api/communication/service_lifecycle.rb +0 -77
  128. data/lib/contrast/api/communication/socket.rb +0 -44
  129. data/lib/contrast/api/communication/socket_client.rb +0 -130
  130. data/lib/contrast/api/communication/speedracer.rb +0 -138
  131. data/lib/contrast/api/communication/tcp_socket.rb +0 -32
  132. data/lib/contrast/api/communication/unix_socket.rb +0 -28
  133. data/lib/contrast/api/communication.rb +0 -20
  134. data/lib/contrast/api/decorators/address.rb +0 -59
  135. data/lib/contrast/api/decorators/agent_startup.rb +0 -56
  136. data/lib/contrast/api/decorators/application_settings.rb +0 -43
  137. data/lib/contrast/api/decorators/application_startup.rb +0 -56
  138. data/lib/contrast/api/decorators/bot_blocker.rb +0 -37
  139. data/lib/contrast/api/decorators/http_request.rb +0 -137
  140. data/lib/contrast/api/decorators/input_analysis.rb +0 -18
  141. data/lib/contrast/api/decorators/instrumentation_mode.rb +0 -35
  142. data/lib/contrast/api/decorators/ip_denylist.rb +0 -37
  143. data/lib/contrast/api/decorators/message.rb +0 -67
  144. data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -52
  145. data/lib/contrast/api/decorators/response_type.rb +0 -17
  146. data/lib/contrast/api/decorators/server_features.rb +0 -25
  147. data/lib/contrast/api/decorators/user_input.rb +0 -51
  148. data/lib/contrast/api/decorators/virtual_patch.rb +0 -34
  149. data/lib/contrast/api/decorators.rb +0 -22
  150. data/lib/contrast/api/dtm.pb.rb +0 -363
  151. data/lib/contrast/api/settings.pb.rb +0 -500
  152. data/lib/contrast/api.rb +0 -16
  153. data/lib/contrast/components/contrast_service.rb +0 -88
  154. data/lib/contrast/components/service.rb +0 -55
  155. data/lib/contrast/tasks/service.rb +0 -84
  156. data/lib/contrast/utils/input_classification.rb +0 -73
  157. data/lib/protobuf/code_generator.rb +0 -129
  158. data/lib/protobuf/decoder.rb +0 -28
  159. data/lib/protobuf/deprecation.rb +0 -117
  160. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +0 -79
  161. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +0 -360
  162. data/lib/protobuf/descriptors.rb +0 -3
  163. data/lib/protobuf/encoder.rb +0 -11
  164. data/lib/protobuf/enum.rb +0 -365
  165. data/lib/protobuf/exceptions.rb +0 -9
  166. data/lib/protobuf/field/base_field.rb +0 -380
  167. data/lib/protobuf/field/base_field_object_definitions.rb +0 -504
  168. data/lib/protobuf/field/bool_field.rb +0 -64
  169. data/lib/protobuf/field/bytes_field.rb +0 -67
  170. data/lib/protobuf/field/double_field.rb +0 -25
  171. data/lib/protobuf/field/enum_field.rb +0 -56
  172. data/lib/protobuf/field/field_array.rb +0 -102
  173. data/lib/protobuf/field/field_hash.rb +0 -122
  174. data/lib/protobuf/field/fixed32_field.rb +0 -25
  175. data/lib/protobuf/field/fixed64_field.rb +0 -28
  176. data/lib/protobuf/field/float_field.rb +0 -43
  177. data/lib/protobuf/field/int32_field.rb +0 -21
  178. data/lib/protobuf/field/int64_field.rb +0 -34
  179. data/lib/protobuf/field/integer_field.rb +0 -23
  180. data/lib/protobuf/field/message_field.rb +0 -51
  181. data/lib/protobuf/field/sfixed32_field.rb +0 -27
  182. data/lib/protobuf/field/sfixed64_field.rb +0 -28
  183. data/lib/protobuf/field/signed_integer_field.rb +0 -29
  184. data/lib/protobuf/field/sint32_field.rb +0 -21
  185. data/lib/protobuf/field/sint64_field.rb +0 -21
  186. data/lib/protobuf/field/string_field.rb +0 -51
  187. data/lib/protobuf/field/uint32_field.rb +0 -21
  188. data/lib/protobuf/field/uint64_field.rb +0 -21
  189. data/lib/protobuf/field/varint_field.rb +0 -77
  190. data/lib/protobuf/field.rb +0 -74
  191. data/lib/protobuf/generators/base.rb +0 -85
  192. data/lib/protobuf/generators/enum_generator.rb +0 -39
  193. data/lib/protobuf/generators/extension_generator.rb +0 -27
  194. data/lib/protobuf/generators/field_generator.rb +0 -193
  195. data/lib/protobuf/generators/file_generator.rb +0 -262
  196. data/lib/protobuf/generators/group_generator.rb +0 -122
  197. data/lib/protobuf/generators/message_generator.rb +0 -104
  198. data/lib/protobuf/generators/option_generator.rb +0 -17
  199. data/lib/protobuf/generators/printable.rb +0 -160
  200. data/lib/protobuf/generators/service_generator.rb +0 -50
  201. data/lib/protobuf/lifecycle.rb +0 -33
  202. data/lib/protobuf/logging.rb +0 -39
  203. data/lib/protobuf/message/fields.rb +0 -233
  204. data/lib/protobuf/message/serialization.rb +0 -85
  205. data/lib/protobuf/message.rb +0 -241
  206. data/lib/protobuf/optionable.rb +0 -72
  207. data/lib/protobuf/tasks/compile.rake +0 -80
  208. data/lib/protobuf/tasks.rb +0 -1
  209. data/lib/protobuf/varint.rb +0 -20
  210. data/lib/protobuf/varint_pure.rb +0 -31
  211. data/lib/protobuf/version.rb +0 -3
  212. data/lib/protobuf/wire_type.rb +0 -10
  213. data/lib/protobuf.rb +0 -91
  214. data/proto/dynamic_discovery.proto +0 -46
  215. data/proto/google/protobuf/compiler/plugin.proto +0 -183
  216. data/proto/google/protobuf/descriptor.proto +0 -911
  217. data/proto/rpc.proto +0 -71
  218. data/service_executables/.gitkeep +0 -0
  219. data/service_executables/VERSION +0 -1
  220. data/service_executables/linux/contrast-service +0 -0
  221. data/service_executables/mac/contrast-service +0 -0
@@ -0,0 +1,118 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ module Contrast
5
+ module AgentLib
6
+ # Base class to set basic rule sets and input list.
7
+ class InterfaceBase
8
+ # This could be changed to regular Hash.
9
+ # This format is used to supports this kind of log_level assignment:
10
+ # via Contrast::Api::Settings::LogLevel::WARN => 3
11
+ # ( note -1 is not supported in the protobuf LogLevel)
12
+ LOG_LEVEL = { -1 => 'OFF', 0 => 'TRACE', 1 => 'DEBUG', 2 => 'INFO', 3 => 'WARN', 4 => 'ERROR' }.cs__freeze
13
+ LOG_DIR = File.join(Dir.pwd).cs__freeze
14
+ # Named after Protect rule_id / Names
15
+ # Corresponding to Rust's ulong enum
16
+ RULE_SET = {
17
+ 'unsafe-file-upload' => 1 << 0,
18
+ 'path-traversal' => 1 << 1,
19
+ 'reflected-xss' => 1 << 2,
20
+ 'sql-injection' => 1 << 3,
21
+ 'cmd-injection' => 1 << 4,
22
+ 'nosql-injection' => 1 << 5,
23
+ 'bot-blocker' => 1 << 6,
24
+ 'ssjs-injection' => 1 << 7,
25
+ 'method-tampering' => 1 << 8
26
+ }.cs__freeze
27
+ # Named same as Contrast::Agent::Reporting::InputTypes
28
+ INPUT_SET = {
29
+ COOKIE_NAME: 1,
30
+ COOKIE_VALUE: 2,
31
+ HEADER_NAME: 3,
32
+ HEADER_VALUE: 4,
33
+ JSON_NAME: 5,
34
+ JSON_VALUE: 6,
35
+ METHOD: 7,
36
+ PARAMETER_NAME: 8,
37
+ PARAMETER_VALUE: 9,
38
+ URI: 10,
39
+ URL_PARAMETER: 11,
40
+ MULTIPART_NAME: 12,
41
+ XML_VALUE: 13
42
+ }.cs__freeze
43
+ EVAL_OPTIONS = { NONE: 0, WORTHWATCHING: 1 }.cs__freeze
44
+
45
+ # Initializes the Agent lib.
46
+ #
47
+ # @param enable_logging [Boolean, nil] flag to enable or disable logging.
48
+ # @param set_log_level [Integer, nil]
49
+ # @param set_log_dir [String, nil] dir to write log files.
50
+ # @return [Boolean] true if success.
51
+ # @raise [StandardError] Any Errors raised in the init process are most
52
+ # likely to be a C segfaults and termination, probably redundant but safe.
53
+ def initialize enable_logging = nil, set_log_level = nil, set_log_dir = nil
54
+ # Override
55
+ end
56
+
57
+ # Return list of available rules
58
+ #
59
+ # @return [Hash]
60
+ def rule_set
61
+ RULE_SET
62
+ end
63
+
64
+ # Returns list of available input types.
65
+ #
66
+ # @return [Hash]
67
+ def input_set
68
+ INPUT_SET
69
+ end
70
+
71
+ # Return list of input evaluation options:
72
+ # WorthWatching or none
73
+ #
74
+ # @return [Hash]
75
+ def eval_option
76
+ EVAL_OPTIONS
77
+ end
78
+
79
+ private
80
+
81
+ # Updates the logging status:
82
+ # Enabled && Level
83
+ #
84
+ # @param level [Integer] one of:
85
+ # [-1...4]
86
+ # @param enabled [Boolean] logging status.
87
+ def update_logging level, enabled
88
+ update_log_level(level)
89
+ @enable_log = !!enabled
90
+ end
91
+
92
+ # Updates the log level for the AgentLib.
93
+ #
94
+ # @param level [Integer] one of:
95
+ # [-1...4]
96
+ def update_log_level level
97
+ value = LOG_LEVEL[level]
98
+ @log_level = value if value
99
+ end
100
+
101
+ # Creates the directory for AgentLib log files.
102
+ # If no path provided use default.
103
+ #
104
+ # @param log_dir [String, nil] path to log.
105
+ # @rescue [StandardError] any error concerning
106
+ # the directory creation.
107
+ def create_log_dir log_dir = nil
108
+ path = log_dir.nil? ? LOG_DIR : log_dir
109
+ FileUtils.mkdir_p(path)
110
+ path
111
+ rescue StandardError => e
112
+ logger.debug('Could not create log directory', error: e)
113
+ FileUtils.mkdir_p(LOG_DIR)
114
+ LOG_DIR
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: true
3
+
4
+ require 'contrast/agent_lib/interface'
5
+
6
+ module Contrast
7
+ module AgentLib
8
+ # This class will hold resulst received form AgentLib structs.
9
+ class EvalResult
10
+ # Name of the Protect rule analyzed.
11
+ # @return [String]
12
+ attr_accessor :rule_id
13
+ # Type of the input.
14
+ # @return [String]
15
+ attr_accessor :input_type
16
+ # Score of the input after AgentLib
17
+ # Analysis
18
+ #
19
+ # @return score [Float]
20
+ attr_accessor :score
21
+
22
+ # Init a new EvalResult, and translate results to usable for
23
+ # reporting values.
24
+ #
25
+ # @param hsh [Hash, nil] return from AgentLib populated struct.
26
+ def initialize hsh
27
+ return unless hsh&.cs__is_a?(Hash)
28
+
29
+ @rule_id = Contrast::AgentLib::Interface::RULE_SET.key(hsh[:rule_id])
30
+ @input_type = Contrast::AgentLib::Interface::INPUT_SET.key(hsh[:input_type])
31
+ @score = hsh[:score]
32
+ end
33
+
34
+ # Used in specs.
35
+ def to_controlled_hash
36
+ {
37
+ rule_id: rule_id,
38
+ input_type: input_type,
39
+ score: score
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
+ # frozen_string_literal: false
3
+
4
+ require_relative 'api/init'
5
+
6
+ module Contrast # :nodoc:
7
+ module Test # :nodoc:
8
+ extend Contrast::AgentLib::Init
9
+
10
+ LOG_DIR = File.join(File.dirname(__FILE__))
11
+
12
+ class << self
13
+ def test_init_with_options enable_log, log_level
14
+ dl__init_with_options(enable_log, LOG_DIR, log_level)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ # for the other cases - I tried with loop and everything, but nothing worked
21
+ # Contrast::Test.test_init_with_options(true, "WARN")
22
+ # Contrast::Test.test_init_with_options(true, "ERROR")
23
+ # Contrast::Test.test_init_with_options(true, "DEBUG")
24
+ # Contrast::Test.test_init_with_options(true, "TRACE")
25
+ response = Contrast::Test.test_init_with_options(true, 'INFO')
26
+ puts response # rubocop:disable Rails/Output
27
+
28
+ # we cannot check here for the file as it's being created after the execution of the file is done
29
+ raise(StandardError, 'Not Working') if response == false
@@ -4,7 +4,7 @@
4
4
  module Contrast
5
5
  module Api
6
6
  module Communication
7
- # Keeps track of the state of connections to SpeedRacer.
7
+ # Keeps track of the state of connections to TeamServer.
8
8
  class ConnectionStatus
9
9
  def initialize
10
10
  @last_success = nil
@@ -12,8 +12,8 @@ module Contrast
12
12
  @startup_messages_sent = false
13
13
  end
14
14
 
15
- # Whether we have sent startup message to SpeedRacer. True after successfully sending startup messages to
16
- # SpeedRacer and reset to false if we lose connection.
15
+ # Whether we have sent startup message to TeamServer. True after successfully sending startup messages to
16
+ # TeamServer and reset to false if we lose connection.
17
17
  #
18
18
  # @return [Boolean]
19
19
  def startup_messages_sent?
@@ -27,13 +27,13 @@ module Contrast
27
27
  @last_success && (@last_failure.nil? || @last_success > @last_failure)
28
28
  end
29
29
 
30
- # The current state of the SpeedRacer is active with a successful message sent
30
+ # The current state of the TeamServer is active with a successful message sent
31
31
  def success!
32
32
  @startup_messages_sent = true
33
33
  @last_success = Time.now.to_f
34
34
  end
35
35
 
36
- # The SpeedRacer may be in some sort of error state
36
+ # The TeamServer may be in some sort of error state
37
37
  def failure!
38
38
  @startup_messages_sent = false
39
39
  @last_failure = Time.now.to_f
@@ -6,7 +6,6 @@ require 'contrast/agent/rule_set'
6
6
  require 'contrast/components/logger'
7
7
  require 'contrast/components/security_logger'
8
8
  require 'contrast/components/heap_dump'
9
- require 'contrast/components/service'
10
9
  require 'contrast/components/ruby_component'
11
10
 
12
11
  module Contrast
@@ -22,26 +21,13 @@ module Contrast
22
21
  return unless hsh
23
22
 
24
23
  @_enable = hsh[:enable]
25
- @_start_bundled_service = hsh[:start_bundled_service]
26
24
  @_omit_body = hsh[:omit_body]
27
- @_service = Contrast::Components::Service::Interface.new(hsh[:service])
28
25
  @_logger = Contrast::Components::Logger::Interface.new(hsh[:logger])
29
26
  @_security_logger = Contrast::Components::SecurityLogger::Interface.new(hsh[:security_logger])
30
27
  @_ruby = Contrast::Components::Ruby::Interface.new(hsh[:ruby])
31
28
  @_heap_dump = Contrast::Components::HeapDump::Interface.new(hsh[:heap_dump])
32
29
  end
33
30
 
34
- # @return [Boolean, true]
35
- def start_bundled_service?
36
- @_start_bundled_service.nil? ? true : @_start_bundled_service
37
- end
38
-
39
- def service
40
- return @_service unless @_service.nil?
41
-
42
- @_service = Contrast::Components::Service::Interface.new
43
- end
44
-
45
31
  def logger
46
32
  return @_logger unless @_logger.nil?
47
33
 
@@ -2,8 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'rubygems/version'
5
- require 'contrast/api/decorators/agent_startup'
6
- require 'contrast/api/decorators/application_startup'
7
5
  require 'contrast/utils/object_share'
8
6
  require 'contrast/components/app_context_extend'
9
7
  require 'contrast/config/base_configuration'
@@ -12,23 +12,6 @@ module Contrast
12
12
  SUPPORTED_FRAMEWORKS = %w[rails sinatra grape rack].cs__freeze
13
13
  SUPPORTED_SERVERS = %w[passenger puma thin unicorn].cs__freeze
14
14
 
15
- def build_app_startup_message
16
- @_build_app_startup_message ||= Contrast::Api::Dtm::ApplicationCreate.build
17
- end
18
-
19
- def build_agent_startup_message
20
- msg = Contrast::Api::Dtm::AgentStartup.build(server_name, server_path, server_type)
21
- Contrast::CONFIG.proto_logger.info('Application context',
22
- server_name: msg.server_name,
23
- server_path: msg.server_path,
24
- server_type: msg.server_type,
25
- application_name: name, # rubocop:disable Security/Module/Name
26
- application_path: path,
27
- application_language: Contrast::Utils::ObjectShare::RUBY)
28
-
29
- msg
30
- end
31
-
32
15
  def pid
33
16
  Process.pid
34
17
  end
@@ -37,14 +20,6 @@ module Contrast
37
20
  Process.ppid
38
21
  end
39
22
 
40
- def pgid
41
- Process.getpgid(pid)
42
- end
43
-
44
- def client_id
45
- @_client_id ||= [name, pgid].join('-') # rubocop:disable Security/Module/Name
46
- end
47
-
48
23
  def app_and_server_information
49
24
  {
50
25
  application_info: find_gem_information(SUPPORTED_FRAMEWORKS),
@@ -100,11 +100,6 @@ module Contrast
100
100
  @config.protect
101
101
  end
102
102
 
103
- # @return [Contrast::Components::Service::Interface]
104
- def service
105
- @config.service
106
- end
107
-
108
103
  def valid?
109
104
  @_valid = validate if @_valid.nil?
110
105
  @_valid
@@ -157,13 +152,10 @@ module Contrast
157
152
  true
158
153
  end
159
154
 
160
- # If the agent is to use the bypass to communicate with TeamServer directly, than it must have the
161
- # configuration values required for that connection.
155
+ # The agent must have the configuration values required for the connection to TeamServer.
162
156
  #
163
157
  # @return [boolean]
164
158
  def valid_api?
165
- return true unless bypass
166
-
167
159
  msg = []
168
160
  msg << API_URL unless api_url
169
161
  msg << API_KEY unless api_key
@@ -220,15 +212,6 @@ module Contrast
220
212
  api.user_name
221
213
  end
222
214
 
223
- # Typically, the following values would be accessed through Contrast::Components::AppContext
224
- # and Contrast::Components::API, but we're too early in the initialization of the Agent to use
225
- # that mechanism, so we look it up directly for ourselves.
226
- #
227
- # @return [String, nil]
228
- def bypass
229
- agent.service.bypass
230
- end
231
-
232
215
  # Typically, the following values would be accessed through Contrast::Components::AppContext
233
216
  # and Contrast::Components::Logger, but we're too early in the initialization of the Agent to use
234
217
  # that mechanism, so we look it up directly for ourselves.
@@ -16,6 +16,8 @@ module Contrast
16
16
 
17
17
  # @return [Boolean, nil]
18
18
  attr_accessor :enable
19
+ # @return [Boolean, nil]
20
+ attr_accessor :agent_lib
19
21
 
20
22
  def initialize hsh = {}
21
23
  return unless hsh
@@ -23,6 +25,7 @@ module Contrast
23
25
  @_exceptions = Contrast::Config::ExceptionConfiguration.new(hsh[:exceptions])
24
26
  @_rules = Contrast::Config::ProtectRulesConfiguration.new(hsh[:rules])
25
27
  @enable = hsh[:enable]
28
+ @agent_lib = hsh[:agent_lib]
26
29
  end
27
30
 
28
31
  # @return [Contrast::Config::ExceptionConfiguration]
@@ -71,7 +74,7 @@ module Contrast
71
74
  str = rule_id.tr('-', '_')
72
75
  ::Contrast::CONFIG.protect.rules[str]&.applicable_mode ||
73
76
  ::Contrast::SETTINGS.application_state.modes_by_id[rule_id] ||
74
- Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION
77
+ :NO_ACTION
75
78
  end
76
79
 
77
80
  def rule name
@@ -19,7 +19,7 @@ module Contrast
19
19
  log:clear middleware notes notes:custom rails:template rails:update routes secret spec spec:features
20
20
  spec:requests spec:controllers spec:helpers spec:models spec:views spec:routing spec:rcov stats
21
21
  test test:all test:all:db test:recent test:single test:uncommitted time:zones:all tmp:clear
22
- tmp:create webpacker:compile contrast:service:start contrast:service:status contrast:service:stop
22
+ tmp:create webpacker:compile
23
23
  ].cs__freeze
24
24
 
25
25
  DEFAULT_UNINSTRUMENTED_NAMESPACES = %w[FactoryGirl FactoryBot].cs__freeze
@@ -1,7 +1,6 @@
1
1
  # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'contrast/api/settings.pb'
5
4
  require 'contrast/agent/excluder'
6
5
  require 'contrast/agent/reporting/settings/sensitive_data_masking'
7
6
  require 'contrast/components/config'
@@ -13,8 +12,7 @@ module Contrast
13
12
  # directives (likely provided by TeamServer) about product operation.
14
13
  # 'Settings' is not a generic term for 'configurable stuff'.
15
14
  module Settings
16
- APPLICATION_STATE_BASE = Struct.new(:modes_by_id, :exclusion_matchers).
17
- new(Hash.new(Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION), [])
15
+ APPLICATION_STATE_BASE = Struct.new(:modes_by_id).new(Hash.new(:NO_ACTION))
18
16
  PROTECT_STATE_BASE = Struct.new(:enabled, :rules).new(false, {})
19
17
  ASSESS_STATE_BASE = Struct.new(:enabled, :sampling_settings, :disabled_assess_rules, :session_id).new(false, nil,
20
18
  [], nil) do
@@ -26,7 +24,7 @@ module Contrast
26
24
  SENSITIVE_DATA_MASKING_BASE = Contrast::Agent::Reporting::Settings::SensitiveDataMasking.new
27
25
 
28
26
  # This is a class.
29
- class Interface # rubocop:disable Metrics/ClassLength
27
+ class Interface
30
28
  extend Contrast::Components::Config
31
29
 
32
30
  # tainted_columns are database columns that receive unsanitized input.
@@ -55,30 +53,6 @@ module Contrast
55
53
  # Current Application State.
56
54
  #
57
55
  # modes_by_id [Hash<Rule_id => Mode] Returns Hash with rules and their current mode.
58
- # exclusion_matchers [Array] Array of all the exclusions.
59
- # code_exclusions [Array<CodeExclusion>] Array of CodeExclusion: {
60
- # name [String] The name of the exclusion as defined by the user in TS.
61
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
62
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
63
- # denylist [String] The call, if in the stack, should result in the agent not taking action.
64
- # input_exclusions [Array<InputExclusions>] Array of InputExclusions: {
65
- # name [String] The name of the input.
66
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
67
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
68
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
69
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
70
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
71
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
72
- # }
73
- # url_exclusions [Array<UrlExclusions>] Array of UrlExclusions: {
74
- # name [String] The name of the input.
75
- # modes [String] If this exclusion applies to assess or protect. [assess, defend]
76
- # assess_rules [Array] Array of assess rules to which this exclusion applies. AssessRuleID [String]
77
- # protect_rules [Array] Array of ProtectRuleID [String] The protect rules to which this exclusion applies.
78
- # urls [Array] Array of URLs to which the exclusions apply. URL [String]
79
- # match_strategy [String] If this exclusion applies to all URLs or only those specified. [ALL, ONLY]
80
- # type [String] The type of the input [COOKIE, PARAMETER, HEADER, BODY, QUERYSTRING]
81
- # }
82
56
  attr_reader :application_state
83
57
  # This the structure that will hold the masking rules send from TS.
84
58
  #
@@ -100,37 +74,32 @@ module Contrast
100
74
  end
101
75
 
102
76
  def code_exclusions
103
- @application_state.exclusion_matchers.select(&:code?)
77
+ excluder&.exclusions&.select(&:code?)
104
78
  end
105
79
 
106
- # @param features_response [Contrast::Api::Settings::ServerFeatures, Contrast::Agent::Reporting::Response]
80
+ # @param features_response [Contrast::Agent::Reporting::Response]
107
81
  def update_from_server_features features_response
108
- if features_response.cs__is_a?(Contrast::Agent::Reporting::Response)
109
- update_from_response(features_response)
110
- else
111
- @protect_state.enabled = features_response.protect_enabled?
112
- @assess_state.enabled = features_response.assess_enabled?
113
- @assess_state.sampling_settings = features_response.assess.sampling
114
- @last_server_update_ms = Contrast::Utils::Timer.now_ms
115
- end
82
+ return unless (server_features = features_response&.server_features)
83
+
84
+ log_file = server_features.log_file
85
+ log_level = server_features.log_level
86
+ Contrast::Logger::Log.instance.update(log_file, log_level) if log_file || log_level
87
+ @protect_state.enabled = server_features.protect.enabled?
88
+ @assess_state.enabled = server_features.assess.enabled?
89
+ @assess_state.sampling_settings = server_features.assess.sampling
116
90
  @last_server_update_ms = Contrast::Utils::Timer.now_ms
117
91
  end
118
92
 
119
- # @param settings_response [Contrast::Api::Settings::ApplicationSettings, Contrast::Agent::Reporting::Response]
93
+ # @param settings_response [Contrast::Agent::Reporting::Response]
120
94
  def update_from_application_settings settings_response
121
- if settings_response&.cs__class == Contrast::Agent::Reporting::Response
122
- update_from_response(settings_response)
123
- else
124
- new_vals = settings_response.application_state_translation
125
- @application_state.modes_by_id = new_vals[:modes_by_id]
126
- @application_state.exclusion_matchers = new_vals[:exclusion_matchers]
127
- @excluder = Contrast::Agent::Excluder.new(@application_state.exclusion_matchers)
128
- @assess_state.disabled_assess_rules = new_vals[:disabled_assess_rules]
129
- if settings_response.session_id && !settings_response.session_id.blank?
130
- @assess_state.session_id = settings_response.session_id
131
- end
132
- @last_app_update_ms = Contrast::Utils::Timer.now_ms
133
- end
95
+ return unless (app_settings = settings_response&.application_settings)
96
+
97
+ @application_state.modes_by_id = app_settings.protect.protection_rules_to_settings_hash
98
+ update_exclusion_matchers(app_settings.exclusions)
99
+ update_sensitive_data_policy(app_settings.sensitive_data_masking)
100
+ @assess_state.disabled_assess_rules = app_settings.assess.disabled_rules
101
+ new_session_id = app_settings.assess.session_id
102
+ @assess_state.session_id = new_session_id if new_session_id && !new_session_id.blank?
134
103
  @last_app_update_ms = Contrast::Utils::Timer.now_ms
135
104
  end
136
105
 
@@ -148,6 +117,7 @@ module Contrast
148
117
  @protect_state.rules = {}
149
118
 
150
119
  # Rules. They add themselves on initialize.
120
+ Contrast::Agent::Protect::Rule::BotBlocker.new
151
121
  Contrast::Agent::Protect::Rule::CmdInjection.new
152
122
  Contrast::Agent::Protect::Rule::Deserialization.new
153
123
  Contrast::Agent::Protect::Rule::HttpMethodTampering.new
@@ -159,6 +129,21 @@ module Contrast
159
129
  Contrast::Agent::Protect::Rule::Xxe.new
160
130
  end
161
131
 
132
+ # @param exclusions [Contrast::Agent::Reporting::Settings::Exclusions]
133
+ def update_exclusion_matchers exclusions
134
+ matchers = []
135
+ exclusions.url_exclusions.each do |exclusion|
136
+ matchers << Contrast::Agent::ExclusionMatcher.new(exclusion)
137
+ end
138
+ exclusions.input_exclusions.each do |exclusion|
139
+ matchers << Contrast::Agent::ExclusionMatcher.new(exclusion)
140
+ end
141
+ exclusions.code_exclusions.each do |exclusion|
142
+ matchers << Contrast::Agent::ExclusionMatcher.new(exclusion)
143
+ end
144
+ @excluder = Contrast::Agent::Excluder.new(matchers)
145
+ end
146
+
162
147
  # Update the sensitive data masking policy from settings,
163
148
  # received from TS. In case the settings are empty,
164
149
  # keep current ones.
@@ -179,43 +164,6 @@ module Contrast
179
164
 
180
165
  private
181
166
 
182
- # @param response [Contrast::Agent::Reporting::Response]
183
- def update_from_response response
184
- if (server_features = response.server_features)
185
- update_server_features(server_features)
186
- end
187
- return unless (app_settings = response.application_settings)
188
-
189
- update_application_settings(app_settings)
190
- end
191
-
192
- # @param server_features [Contrast::Agent::Reporting::Settings::FeatureSettings]
193
- def update_server_features server_features
194
- return unless server_features
195
-
196
- log_file = server_features.log_file
197
- log_level = server_features.log_level
198
- Contrast::Logger::Log.instance.update(log_file, log_level) if log_file || log_level
199
- @protect_state.enabled = server_features.protect.enabled?
200
- @assess_state.enabled = server_features.assess.enabled?
201
- @assess_state.sampling_settings = server_features.assess.sampling
202
- @last_server_update_ms = Contrast::Utils::Timer.now_ms
203
- end
204
-
205
- # @param app_settings [Contrast::Agent::Reporting::Settings::ApplicationSettings]
206
- def update_application_settings app_settings
207
- return unless app_settings
208
-
209
- @application_state.modes_by_id = app_settings.protect.protection_rules_to_settings_hash
210
- # TODO: RUBY-1438 this needs to be translated
211
- # @application_state.exclusion_matchers = new_vals[:exclusion_matchers]
212
- update_sensitive_data_policy(app_settings.sensitive_data_masking)
213
- @assess_state.disabled_assess_rules = app_settings.assess.disabled_rules
214
- new_session_id = app_settings.assess.session_id
215
- @assess_state.session_id = new_session_id if new_session_id && !new_session_id.blank?
216
- @last_app_update_ms = Contrast::Utils::Timer.now_ms
217
- end
218
-
219
167
  # check if settings are empty and return true if so.
220
168
  #
221
169
  # @param settings [String, Boolean, Array, Hash]
@@ -33,24 +33,24 @@ module Contrast
33
33
  end
34
34
 
35
35
  # To convert the user input mode from config to a standard format used by TS & SR, we need to convert the given
36
- # String to its Contrast::Api::Settings::ProtectionRule::Mode equivalent. If a nonsense value is provided, it'll
36
+ # String to its recognized symbol equivalent. If a nonsense value is provided, it'll
37
37
  # be treated the same as disabling the rule.
38
38
  #
39
- # @return [Contrast::Api::Settings::ProtectionRule::Mode, nil]
39
+ # @return [Symbol]
40
40
  def applicable_mode
41
41
  return unless mode
42
42
 
43
43
  case mode
44
44
  when 'permit'
45
- Contrast::Api::Settings::ProtectionRule::Mode::PERMIT
45
+ :PERMIT
46
46
  when 'block_at_perimeter'
47
- Contrast::Api::Settings::ProtectionRule::Mode::BLOCK_AT_PERIMETER
47
+ :BLOCK_AT_PERIMETER
48
48
  when 'block'
49
- Contrast::Api::Settings::ProtectionRule::Mode::BLOCK
49
+ :BLOCK
50
50
  when 'monitor'
51
- Contrast::Api::Settings::ProtectionRule::Mode::MONITOR
51
+ :MONITOR
52
52
  else
53
- Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION
53
+ :NO_ACTION
54
54
  end
55
55
  end
56
56
  end