contrast-agent 7.2.0 → 7.3.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +62 -23
  3. data/lib/contrast/agent/protect/input_analyzer/worth_watching_analyzer.rb +37 -4
  4. data/lib/contrast/agent/protect/rule/base.rb +5 -1
  5. data/lib/contrast/agent/protect/rule/bot_blocker/bot_blocker_input_classification.rb +27 -11
  6. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +0 -1
  7. data/lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb +2 -2
  8. data/lib/contrast/agent/protect/rule/input_classification/base.rb +191 -0
  9. data/lib/contrast/agent/protect/rule/input_classification/base64_statistic.rb +71 -0
  10. data/lib/contrast/agent/protect/rule/input_classification/cached_result.rb +37 -0
  11. data/lib/contrast/agent/protect/rule/input_classification/encoding.rb +109 -0
  12. data/lib/contrast/agent/protect/rule/input_classification/encoding_rates.rb +47 -0
  13. data/lib/contrast/agent/protect/rule/input_classification/extendable.rb +80 -0
  14. data/lib/contrast/agent/protect/rule/input_classification/lru_cache.rb +198 -0
  15. data/lib/contrast/agent/protect/rule/input_classification/match_rates.rb +66 -0
  16. data/lib/contrast/agent/protect/rule/input_classification/rates.rb +53 -0
  17. data/lib/contrast/agent/protect/rule/input_classification/statistics.rb +115 -0
  18. data/lib/contrast/agent/protect/rule/input_classification/utils.rb +23 -0
  19. data/lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb +17 -7
  20. data/lib/contrast/agent/protect/rule/path_traversal/path_traversal_input_classification.rb +18 -15
  21. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +2 -2
  22. data/lib/contrast/agent/protect/rule/unsafe_file_upload/unsafe_file_upload_input_classification.rb +18 -15
  23. data/lib/contrast/agent/protect/rule/xss/reflected_xss_input_classification.rb +19 -17
  24. data/lib/contrast/agent/reporting/attack_result/attack_result.rb +6 -0
  25. data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +2 -7
  26. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +11 -0
  27. data/lib/contrast/agent/reporting/input_analysis/input_type.rb +33 -1
  28. data/lib/contrast/agent/reporting/masker/masker_utils.rb +1 -1
  29. data/lib/contrast/agent/reporting/reporting_events/application_defend_activity.rb +1 -0
  30. data/lib/contrast/agent/reporting/reporting_events/application_defend_attacker_activity.rb +1 -0
  31. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +1 -1
  32. data/lib/contrast/agent/telemetry/base.rb +28 -2
  33. data/lib/contrast/agent/telemetry/base64_hash.rb +55 -0
  34. data/lib/contrast/agent/telemetry/cache_hash.rb +55 -0
  35. data/lib/contrast/agent/telemetry/client.rb +10 -2
  36. data/lib/contrast/agent/telemetry/{hash.rb → exception_hash.rb} +1 -1
  37. data/lib/contrast/agent/telemetry/input_analysis_cache_event.rb +27 -0
  38. data/lib/contrast/agent/telemetry/input_analysis_encoding_event.rb +26 -0
  39. data/lib/contrast/agent/telemetry/input_analysis_event.rb +91 -0
  40. data/lib/contrast/agent/telemetry/metric_event.rb +12 -0
  41. data/lib/contrast/agent/telemetry/startup_metrics_event.rb +0 -8
  42. data/lib/contrast/agent/version.rb +1 -1
  43. data/lib/contrast/components/config.rb +4 -4
  44. data/lib/contrast/components/protect.rb +11 -1
  45. data/lib/contrast/components/sampling.rb +15 -10
  46. data/lib/contrast/config/diagnostics/environment_variables.rb +3 -1
  47. data/lib/contrast/config/yaml_file.rb +8 -0
  48. data/lib/contrast/framework/rails/support.rb +3 -0
  49. data/lib/contrast/utils/assess/event_limit_utils.rb +13 -13
  50. data/lib/contrast/utils/metrics_hash.rb +1 -1
  51. data/lib/contrast/utils/object_share.rb +2 -1
  52. data/lib/contrast/utils/response_utils.rb +12 -0
  53. data/lib/contrast/utils/timer.rb +2 -0
  54. data/lib/contrast.rb +9 -2
  55. data/ruby-agent.gemspec +1 -1
  56. metadata +21 -6
  57. data/lib/contrast/utils/input_classification_base.rb +0 -169
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contrast-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.0
4
+ version: 7.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - galen.palmer@contrastsecurity.com
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: exe
15
15
  cert_chain: []
16
- date: 2023-05-31 00:00:00.000000000 Z
16
+ date: 2023-07-26 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: bundler
@@ -669,14 +669,14 @@ dependencies:
669
669
  requirements:
670
670
  - - '='
671
671
  - !ruby/object:Gem::Version
672
- version: 1.1.0
672
+ version: 1.1.1
673
673
  type: :runtime
674
674
  prerelease: false
675
675
  version_requirements: !ruby/object:Gem::Requirement
676
676
  requirements:
677
677
  - - '='
678
678
  - !ruby/object:Gem::Version
679
- version: 1.1.0
679
+ version: 1.1.1
680
680
  description: This gem instantiates a Rack middleware for rack-based web applications
681
681
  in order to provide Interactive Application Security Testing and Protection.
682
682
  email:
@@ -1023,6 +1023,17 @@ files:
1023
1023
  - lib/contrast/agent/protect/rule/cmdi/cmdi_input_classification.rb
1024
1024
  - lib/contrast/agent/protect/rule/default_scanner.rb
1025
1025
  - lib/contrast/agent/protect/rule/deserialization/deserialization.rb
1026
+ - lib/contrast/agent/protect/rule/input_classification/base.rb
1027
+ - lib/contrast/agent/protect/rule/input_classification/base64_statistic.rb
1028
+ - lib/contrast/agent/protect/rule/input_classification/cached_result.rb
1029
+ - lib/contrast/agent/protect/rule/input_classification/encoding.rb
1030
+ - lib/contrast/agent/protect/rule/input_classification/encoding_rates.rb
1031
+ - lib/contrast/agent/protect/rule/input_classification/extendable.rb
1032
+ - lib/contrast/agent/protect/rule/input_classification/lru_cache.rb
1033
+ - lib/contrast/agent/protect/rule/input_classification/match_rates.rb
1034
+ - lib/contrast/agent/protect/rule/input_classification/rates.rb
1035
+ - lib/contrast/agent/protect/rule/input_classification/statistics.rb
1036
+ - lib/contrast/agent/protect/rule/input_classification/utils.rb
1026
1037
  - lib/contrast/agent/protect/rule/no_sqli/mongo_no_sql_scanner.rb
1027
1038
  - lib/contrast/agent/protect/rule/no_sqli/no_sqli.rb
1028
1039
  - lib/contrast/agent/protect/rule/no_sqli/no_sqli_input_classification.rb
@@ -1176,6 +1187,8 @@ files:
1176
1187
  - lib/contrast/agent/response/response.rb
1177
1188
  - lib/contrast/agent/scope/scope.rb
1178
1189
  - lib/contrast/agent/telemetry/base.rb
1190
+ - lib/contrast/agent/telemetry/base64_hash.rb
1191
+ - lib/contrast/agent/telemetry/cache_hash.rb
1179
1192
  - lib/contrast/agent/telemetry/client.rb
1180
1193
  - lib/contrast/agent/telemetry/event.rb
1181
1194
  - lib/contrast/agent/telemetry/exception.rb
@@ -1185,8 +1198,11 @@ files:
1185
1198
  - lib/contrast/agent/telemetry/exception/message_exception.rb
1186
1199
  - lib/contrast/agent/telemetry/exception/obfuscate.rb
1187
1200
  - lib/contrast/agent/telemetry/exception/stack_frame.rb
1188
- - lib/contrast/agent/telemetry/hash.rb
1201
+ - lib/contrast/agent/telemetry/exception_hash.rb
1189
1202
  - lib/contrast/agent/telemetry/identifier.rb
1203
+ - lib/contrast/agent/telemetry/input_analysis_cache_event.rb
1204
+ - lib/contrast/agent/telemetry/input_analysis_encoding_event.rb
1205
+ - lib/contrast/agent/telemetry/input_analysis_event.rb
1190
1206
  - lib/contrast/agent/telemetry/metric_event.rb
1191
1207
  - lib/contrast/agent/telemetry/startup_metrics_event.rb
1192
1208
  - lib/contrast/agent/telemetry/telemetry.rb
@@ -1310,7 +1326,6 @@ files:
1310
1326
  - lib/contrast/utils/hash_utils.rb
1311
1327
  - lib/contrast/utils/head_dump_utils_extend.rb
1312
1328
  - lib/contrast/utils/heap_dump_util.rb
1313
- - lib/contrast/utils/input_classification_base.rb
1314
1329
  - lib/contrast/utils/invalid_configuration_util.rb
1315
1330
  - lib/contrast/utils/io_util.rb
1316
1331
  - lib/contrast/utils/job_servers_running.rb
@@ -1,169 +0,0 @@
1
- # Copyright (c) 2023 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
- require 'contrast/agent/reporting/input_analysis/input_type'
6
- require 'contrast/agent/reporting/input_analysis/score_level'
7
- require 'contrast/agent/protect/input_analyzer/input_analyzer'
8
- require 'contrast/components/logger'
9
-
10
- module Contrast
11
- module Agent
12
- module Protect
13
- module Rule
14
- # This module will include all the similar information for all input classifications
15
- # between different rules
16
- module InputClassificationBase
17
- UNKNOWN_KEY = 'unknown'
18
- THRESHOLD = 90.cs__freeze
19
- WORTHWATCHING_THRESHOLD = 10.cs__freeze
20
- include Contrast::Agent::Reporting::InputType
21
- include Contrast::Agent::Reporting::ScoreLevel
22
- include Contrast::Components::Logger::InstanceMethods
23
-
24
- KEYS_NEEDED = [COOKIE_VALUE, PARAMETER_VALUE, JSON_VALUE, MULTIPART_VALUE, XML_VALUE, DWR_VALUE].cs__freeze
25
-
26
- # Input Classification stage is done to determine if an user input is
27
- # DEFINITEATTACK or to be ignored.
28
- #
29
- # @param rule_id [String] Name of the protect rule.
30
- # @param input_type [Symbol, Contrast::Agent::Reporting::InputType] The type of the user input.
31
- # @param value [String, Array<String>] the value of the input.
32
- # @param input_analysis [Contrast::Agent::Reporting::InputAnalysis] Holds all the results from the
33
- # agent analysis from the current
34
- # Request.
35
- # @return ia [Contrast::Agent::Reporting::InputAnalysis, nil] with updated results.
36
- def classify rule_id, input_type, value, input_analysis
37
- return unless (rule = Contrast::PROTECT.rule(rule_id))
38
- return unless rule.applicable_user_inputs.include?(input_type)
39
- return unless input_analysis.request
40
-
41
- Array(value).each do |val|
42
- Array(val).each do |v|
43
- next unless v
44
-
45
- result = create_new_input_result(input_analysis.request, rule.rule_name, input_type, v)
46
- append_result(input_analysis, result)
47
- end
48
- end
49
-
50
- input_analysis
51
- rescue StandardError => e
52
- logger.debug("An Error was recorded in the input classification of the #{ rule_id }")
53
- logger.debug(e)
54
- nil
55
- end
56
-
57
- # Creates new isntance of InputAnalysisResult with basic info.
58
- #
59
- # @param rule_id [String] The name of the Protect Rule.
60
- # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input.
61
- # @param value [String, Array<String>] the value of the input.
62
- # @param path [String] the path of the current request context.
63
- #
64
- # @return res [Contrast::Agent::Reporting::InputAnalysisResult]
65
- def new_ia_result rule_id, input_type, path, value = nil
66
- res = Contrast::Agent::Reporting::InputAnalysisResult.new
67
- res.rule_id = rule_id
68
- res.input_type = input_type
69
- res.path = path
70
- res.value = value
71
- res
72
- end
73
-
74
- # This methods checks if input is value that matches a key in the input.
75
- #
76
- # @param request [Contrast::Agent::Request] the current request context.
77
- # @param result [Contrast::Agent::Reporting::InputAnalysisResult] result to be updated.
78
- # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input.
79
- # @param value [String, Array<String>] the value of the input.
80
- #
81
- # @return result [Contrast::Agent::Reporting::InputAnalysisResult] updated with key result.
82
- def add_needed_key request, result, input_type, value
83
- case input_type
84
- when COOKIE_VALUE
85
- result.key = request.cookies.key(value)
86
- when PARAMETER_VALUE, URL_PARAMETER
87
- result.key = request.parameters.key(value)
88
- when HEADER
89
- result.key = request.headers.key(value)
90
- when UNKNOWN
91
- result.key = UNKNOWN_KEY
92
- else
93
- result.key
94
- end
95
- rescue StandardError => e
96
- logger.warn('Could not find proper key for input traced value', message: e)
97
- end
98
-
99
- # Some input types are not yet supported from the AgentLib.
100
- # This will convert the type to the closet possible if viable,
101
- # so that the input tracing could be done.
102
- #
103
- # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input.
104
- # @return [Integer<Contrast::AgentLib::Interface::INPUT_SET>]
105
- def convert_input_type input_type
106
- case input_type
107
- when URI, URL_PARAMETER
108
- Contrast::AGENT_LIB.input_set[:URI_PATH]
109
- when BODY, DWR_VALUE, SOCKET, UNDEFINED_TYPE, UNKNOWN, REQUEST, QUERYSTRING
110
- Contrast::AGENT_LIB.input_set[:PARAMETER_VALUE]
111
- when HEADER
112
- Contrast::AGENT_LIB.input_set[:HEADER_VALUE]
113
- when MULTIPART_VALUE, MULTIPART_FIELD_NAME
114
- Contrast::AGENT_LIB.input_set[:MULTIPART_NAME]
115
- when JSON_ARRAYED_VALUE
116
- Contrast::AGENT_LIB.input_set[:JSON_KEY]
117
- when PARAMETER_NAME
118
- Contrast::AGENT_LIB.input_set[:PARAMETER_KEY]
119
- else
120
- Contrast::AGENT_LIB.input_set[input_type]
121
- end
122
- rescue StandardError => e
123
- logger.debug('Protect Input classification could not determine input type, falling back to default',
124
- error: e)
125
- Contrast::AGENT_LIB.input_set[:PARAMETER_VALUE]
126
- end
127
-
128
- private
129
-
130
- # This methods checks if input is tagged WORTHWATCHING or IGNORE matches value with it's
131
- # key if needed and Creates new instance of InputAnalysisResult.
132
- #
133
- # @param request [Contrast::Agent::Request] the current request context.
134
- # @param rule_id [String] The name of the Protect Rule.
135
- # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input.
136
- # @param value [String, Array<String>] the value of the input.
137
- #
138
- # @return res [Contrast::Agent::Reporting::InputAnalysisResult, nil]
139
- def create_new_input_result request, rule_id, input_type, value
140
- return unless Contrast::AGENT_LIB
141
-
142
- input_eval = Contrast::AGENT_LIB.eval_input(value,
143
- convert_input_type(input_type),
144
- Contrast::AGENT_LIB.rule_set[rule_id],
145
- Contrast::AGENT_LIB.eval_option[:PREFER_WORTH_WATCHING])
146
-
147
- ia_result = new_ia_result(rule_id, input_type, request.path, value)
148
- score = input_eval&.score || 0
149
- if score >= WORTHWATCHING_THRESHOLD
150
- ia_result.score_level = WORTHWATCHING
151
- ia_result.ids << self::WORTHWATCHING_MATCH
152
- else
153
- ia_result.score_level = IGNORE
154
- return
155
- end
156
-
157
- add_needed_key(request, ia_result, input_type, value) if KEYS_NEEDED.include?(input_type)
158
- ia_result
159
- end
160
-
161
- def append_result ia_analysis, result
162
- ia_analysis.results << result if result
163
- ia_analysis
164
- end
165
- end
166
- end
167
- end
168
- end
169
- end