contrast-agent 6.6.5 → 6.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +0 -3
  4. data/ext/cs__scope/cs__scope.c +1 -1
  5. data/lib/contrast/agent/assess/contrast_event.rb +2 -24
  6. data/lib/contrast/agent/assess/events/source_event.rb +7 -61
  7. data/lib/contrast/agent/assess/finalizers/hash.rb +11 -0
  8. data/lib/contrast/agent/assess/policy/dynamic_source_factory.rb +0 -55
  9. data/lib/contrast/agent/assess/policy/policy_node.rb +3 -3
  10. data/lib/contrast/agent/assess/policy/policy_node_utils.rb +0 -1
  11. data/lib/contrast/agent/assess/policy/propagation_node.rb +4 -4
  12. data/lib/contrast/agent/assess/policy/source_method.rb +24 -1
  13. data/lib/contrast/agent/assess/policy/trigger/reflected_xss.rb +7 -5
  14. data/lib/contrast/agent/assess/policy/trigger/xpath.rb +6 -1
  15. data/lib/contrast/agent/assess/policy/trigger_method.rb +36 -132
  16. data/lib/contrast/agent/assess/policy/trigger_node.rb +3 -3
  17. data/lib/contrast/agent/assess/property/evented.rb +2 -12
  18. data/lib/contrast/agent/assess/rule/provider/hardcoded_value_rule.rb +42 -84
  19. data/lib/contrast/agent/assess/rule/response/base_rule.rb +11 -27
  20. data/lib/contrast/agent/assess/rule/response/body_rule.rb +1 -3
  21. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +77 -62
  22. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +1 -1
  23. data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +6 -1
  24. data/lib/contrast/agent/assess/rule/response/header_rule.rb +5 -5
  25. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +1 -1
  26. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +1 -1
  27. data/lib/contrast/agent/assess/tracker.rb +1 -7
  28. data/lib/contrast/agent/excluder.rb +206 -0
  29. data/lib/contrast/agent/exclusion_matcher.rb +6 -0
  30. data/lib/contrast/agent/inventory/database_config.rb +6 -10
  31. data/lib/contrast/agent/protect/policy/applies_command_injection_rule.rb +4 -0
  32. data/lib/contrast/agent/protect/policy/applies_sqli_rule.rb +1 -0
  33. data/lib/contrast/agent/protect/rule/base.rb +49 -5
  34. data/lib/contrast/agent/protect/rule/base_service.rb +1 -0
  35. data/lib/contrast/agent/protect/rule/cmd_injection.rb +18 -105
  36. data/lib/contrast/agent/protect/rule/cmdi/cmdi_backdoors.rb +129 -0
  37. data/lib/contrast/agent/protect/rule/cmdi/cmdi_base_rule.rb +169 -0
  38. data/lib/contrast/agent/protect/rule/deserialization.rb +2 -1
  39. data/lib/contrast/agent/protect/rule/sqli/sqli_base_rule.rb +51 -0
  40. data/lib/contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions.rb +67 -0
  41. data/lib/contrast/agent/protect/rule/sqli.rb +6 -31
  42. data/lib/contrast/agent/protect/rule/xxe.rb +2 -0
  43. data/lib/contrast/agent/protect/rule.rb +3 -1
  44. data/lib/contrast/agent/reporting/attack_result/rasp_rule_sample.rb +6 -0
  45. data/lib/contrast/agent/reporting/details/sqli_dangerous_functions.rb +22 -0
  46. data/lib/contrast/agent/reporting/reporter.rb +1 -2
  47. data/lib/contrast/agent/reporting/reporting_events/agent_startup.rb +2 -2
  48. data/lib/contrast/agent/reporting/reporting_events/application_activity.rb +1 -4
  49. data/lib/contrast/agent/reporting/reporting_events/application_startup.rb +1 -1
  50. data/lib/contrast/agent/reporting/reporting_events/architecture_component.rb +0 -23
  51. data/lib/contrast/agent/reporting/reporting_events/finding.rb +19 -49
  52. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +12 -9
  53. data/lib/contrast/agent/reporting/reporting_events/finding_event_signature.rb +1 -1
  54. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +23 -21
  55. data/lib/contrast/agent/reporting/reporting_events/finding_event_stack.rb +5 -18
  56. data/lib/contrast/agent/reporting/reporting_events/finding_event_taint_range.rb +1 -0
  57. data/lib/contrast/{api/decorators/trace_taint_range_tags.rb → agent/reporting/reporting_events/finding_event_taint_range_tags.rb} +7 -6
  58. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +1 -1
  59. data/lib/contrast/agent/reporting/reporting_events/library_usage_observation.rb +1 -1
  60. data/lib/contrast/agent/reporting/reporting_events/observed_route.rb +2 -2
  61. data/lib/contrast/agent/reporting/reporting_events/preflight_message.rb +10 -14
  62. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +11 -0
  63. data/lib/contrast/agent/reporting/reporting_events/route_coverage.rb +3 -1
  64. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +11 -23
  65. data/lib/contrast/agent/reporting/reporting_events/route_discovery_observation.rb +8 -26
  66. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +1 -1
  67. data/lib/contrast/agent/reporting/reporting_utilities/build_preflight.rb +4 -7
  68. data/lib/contrast/agent/reporting/reporting_utilities/headers.rb +1 -1
  69. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +3 -3
  70. data/lib/contrast/agent/request.rb +2 -2
  71. data/lib/contrast/agent/request_context.rb +8 -20
  72. data/lib/contrast/agent/request_context_extend.rb +15 -36
  73. data/lib/contrast/agent/request_handler.rb +0 -8
  74. data/lib/contrast/agent/response.rb +0 -18
  75. data/lib/contrast/agent/telemetry/events/event.rb +1 -1
  76. data/lib/contrast/agent/telemetry/events/metric_event.rb +1 -1
  77. data/lib/contrast/agent/telemetry/events/startup_metrics_event.rb +3 -3
  78. data/lib/contrast/agent/version.rb +1 -1
  79. data/lib/contrast/api/communication/messaging_queue.rb +2 -3
  80. data/lib/contrast/api/communication/socket_client.rb +4 -4
  81. data/lib/contrast/api/communication/speedracer.rb +4 -8
  82. data/lib/contrast/api/decorators/agent_startup.rb +5 -6
  83. data/lib/contrast/api/decorators/application_settings.rb +2 -1
  84. data/lib/contrast/api/decorators/application_startup.rb +6 -6
  85. data/lib/contrast/api/decorators/message.rb +0 -4
  86. data/lib/contrast/api/decorators/rasp_rule_sample.rb +0 -6
  87. data/lib/contrast/api/decorators.rb +0 -6
  88. data/lib/contrast/api/dtm.pb.rb +0 -489
  89. data/lib/contrast/components/agent.rb +16 -12
  90. data/lib/contrast/components/api.rb +10 -10
  91. data/lib/contrast/components/app_context.rb +3 -3
  92. data/lib/contrast/components/app_context_extend.rb +1 -1
  93. data/lib/contrast/components/assess.rb +92 -38
  94. data/lib/contrast/components/assess_rules.rb +36 -0
  95. data/lib/contrast/components/config.rb +54 -12
  96. data/lib/contrast/components/contrast_service.rb +8 -8
  97. data/lib/contrast/components/heap_dump.rb +1 -1
  98. data/lib/contrast/components/protect.rb +5 -5
  99. data/lib/contrast/components/ruby_component.rb +81 -0
  100. data/lib/contrast/components/sampling.rb +1 -1
  101. data/lib/contrast/components/security_logger.rb +23 -0
  102. data/lib/contrast/components/service.rb +55 -0
  103. data/lib/contrast/components/settings.rb +12 -4
  104. data/lib/contrast/config/base_configuration.rb +1 -1
  105. data/lib/contrast/config/protect_rules_configuration.rb +17 -3
  106. data/lib/contrast/config/server_configuration.rb +1 -1
  107. data/lib/contrast/config.rb +0 -6
  108. data/lib/contrast/configuration.rb +81 -17
  109. data/lib/contrast/extension/assess/exec_trigger.rb +3 -1
  110. data/lib/contrast/extension/assess/marshal.rb +3 -2
  111. data/lib/contrast/extension/assess/string.rb +0 -1
  112. data/lib/contrast/extension/extension.rb +1 -1
  113. data/lib/contrast/framework/base_support.rb +0 -5
  114. data/lib/contrast/framework/grape/support.rb +1 -23
  115. data/lib/contrast/framework/manager.rb +0 -10
  116. data/lib/contrast/framework/rails/support.rb +5 -58
  117. data/lib/contrast/framework/sinatra/support.rb +2 -21
  118. data/lib/contrast/logger/cef_log.rb +21 -3
  119. data/lib/contrast/logger/log.rb +1 -11
  120. data/lib/contrast/tasks/config.rb +4 -2
  121. data/lib/contrast/utils/assess/event_limit_utils.rb +5 -8
  122. data/lib/contrast/utils/assess/trigger_method_utils.rb +10 -18
  123. data/lib/contrast/utils/findings.rb +6 -5
  124. data/lib/contrast/utils/hash_digest.rb +9 -24
  125. data/lib/contrast/utils/hash_digest_extend.rb +6 -6
  126. data/lib/contrast/utils/invalid_configuration_util.rb +21 -58
  127. data/lib/contrast/utils/log_utils.rb +32 -8
  128. data/lib/contrast/utils/net_http_base.rb +2 -2
  129. data/lib/contrast/utils/patching/policy/patch_utils.rb +3 -2
  130. data/lib/contrast/utils/stack_trace_utils.rb +0 -25
  131. data/lib/contrast/utils/string_utils.rb +9 -0
  132. data/lib/contrast/utils/telemetry_client.rb +13 -7
  133. data/lib/contrast.rb +5 -10
  134. metadata +22 -28
  135. data/lib/contrast/agent/reporting/reporting_events/trace_event_source.rb +0 -30
  136. data/lib/contrast/agent/reporting/reporting_utilities/dtm_message.rb +0 -36
  137. data/lib/contrast/api/decorators/activity.rb +0 -33
  138. data/lib/contrast/api/decorators/architecture_component.rb +0 -36
  139. data/lib/contrast/api/decorators/finding.rb +0 -29
  140. data/lib/contrast/api/decorators/route_coverage.rb +0 -91
  141. data/lib/contrast/api/decorators/trace_event.rb +0 -120
  142. data/lib/contrast/api/decorators/trace_event_object.rb +0 -63
  143. data/lib/contrast/api/decorators/trace_event_signature.rb +0 -69
  144. data/lib/contrast/api/decorators/trace_taint_range.rb +0 -52
  145. data/lib/contrast/config/assess_configuration.rb +0 -93
  146. data/lib/contrast/config/assess_rules_configuration.rb +0 -32
  147. data/lib/contrast/config/root_configuration.rb +0 -90
  148. data/lib/contrast/config/ruby_configuration.rb +0 -81
  149. data/lib/contrast/config/service_configuration.rb +0 -49
  150. data/lib/contrast/utils/preflight_util.rb +0 -13
@@ -0,0 +1,67 @@
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/reporting/details/sqli_dangerous_functions'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Protect
9
+ module Rule
10
+ # This class will include the check for SQL Injection Semantic Dangerous Functions
11
+ class SqliDangerousFunctions < Contrast::Agent::Protect::Rule::SqliBaseRule
12
+ NAME = 'sql-injection-semantic-dangerous-functions'
13
+ BLOCK_MESSAGE = 'SQLi Semantic Dangerous Functions rule triggered. Response blocked.'
14
+
15
+ SQL_DANGEROUS_FUNCTIONS = %w[unhex waitfor xp_cmdshell exec].cs__freeze
16
+
17
+ def rule_name
18
+ NAME
19
+ end
20
+
21
+ def infilter context, query_string
22
+ return unless infilter?(context)
23
+ return unless violated?(query_string)
24
+
25
+ result = build_violation(context, query_string)
26
+ return unless result
27
+
28
+ append_to_activity(context, result)
29
+
30
+ cef_logging(result, :successful_attack)
31
+ raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE)) if blocked?
32
+ end
33
+
34
+ protected
35
+
36
+ def violated? attack_string
37
+ SQL_DANGEROUS_FUNCTIONS.any? { |dang_func| attack_string.downcase.include?(dang_func) }
38
+ end
39
+
40
+ def build_violation context, potential_attack_string
41
+ result = build_attack_result(context)
42
+ update_successful_attack_response(context, nil, result, potential_attack_string)
43
+ append_sample(context, nil, result, potential_attack_string)
44
+ result
45
+ end
46
+
47
+ # Override if rule can make use of the candidate string or kwargs to
48
+ # build rasp rule sample.
49
+ def build_sample context, ia_result, candidate_string, **_kwargs
50
+ sample = build_base_sample(context, nil)
51
+ sample.details = Contrast::Agent::Reporting::Details::SqliDangerousFunctions.new
52
+ sample.details.query = candidate_string
53
+
54
+ if ia_result.nil?
55
+ ui = Contrast::Agent::Reporting::UserInput.new
56
+ ui.input_type = :UNKNOWN
57
+ ui.value = candidate_string
58
+ sample.user_input = ui
59
+ end
60
+
61
+ sample
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -5,13 +5,15 @@ require 'contrast/agent/protect/rule/base_service'
5
5
  require 'contrast/agent/protect/policy/applies_sqli_rule'
6
6
  require 'contrast/agent/protect/rule/sql_sample_builder'
7
7
  require 'contrast/agent/reporting/input_analysis/input_type'
8
+ require 'contrast/agent/protect/rule/sqli/sqli_base_rule'
9
+ require 'contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions'
8
10
 
9
11
  module Contrast
10
12
  module Agent
11
13
  module Protect
12
14
  module Rule
13
15
  # The Ruby implementation of the Protect SQL Injection rule.
14
- class Sqli < Contrast::Agent::Protect::Rule::BaseService
16
+ class Sqli < Contrast::Agent::Protect::Rule::SqliBaseRule
15
17
  # Generate a sample for the SQLI injection detection rule, allowing for reporting to and rendering
16
18
  # by TeamServer
17
19
  include SqlSampleBuilder::SqliSample
@@ -22,28 +24,9 @@ module Contrast
22
24
  include Contrast::Agent::Reporting::InputType
23
25
  end
24
26
 
25
- APPLICABLE_USER_INPUTS = [
26
- BODY, COOKIE_NAME, COOKIE_VALUE, HEADER,
27
- PARAMETER_NAME, PARAMETER_VALUE, JSON_VALUE,
28
- MULTIPART_VALUE, MULTIPART_FIELD_NAME,
29
- XML_VALUE, DWR_VALUE
30
- ].cs__freeze
31
27
  NAME = 'sql-injection'
32
- BLOCK_MESSAGE = 'SQLi rule triggered. Response blocked.'
33
28
 
34
- class << self
35
- # @param attack_sample [Contrast::Api::Dtm::RaspRuleSample]
36
- # @return [Hash] the details for this specific rule
37
- def extract_details attack_sample
38
- {
39
- start: attack_sample.sqli.start_idx,
40
- end: attack_sample.sqli.end_idx,
41
- boundaryOverrunIndex: attack_sample.sqli.boundary_overrun_idx,
42
- inputBoundaryIndex: attack_sample.sqli.input_boundary_idx,
43
- query: attack_sample.sqli.query
44
- }
45
- end
46
- end
29
+ SUB_RULES = [Contrast::Agent::Protect::Rule::SqliDangerousFunctions.new].cs__freeze
47
30
 
48
31
  def rule_name
49
32
  NAME
@@ -53,16 +36,8 @@ module Contrast
53
36
  BLOCK_MESSAGE
54
37
  end
55
38
 
56
- def infilter context, database, query_string
57
- return unless infilter?(context)
58
-
59
- result = find_attacker(context, query_string, database: database)
60
- return unless result
61
-
62
- append_to_activity(context, result)
63
-
64
- cef_logging(result, :successful_attack, value: query_string)
65
- raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE)) if blocked?
39
+ def sub_rules
40
+ SUB_RULES
66
41
  end
67
42
  end
68
43
  end
@@ -59,6 +59,8 @@ module Contrast
59
59
  # @raise [Contrast::SecurityException] Security exception if an XXE
60
60
  # attack is found and the rule is in block mode.
61
61
  def infilter context, framework, xml
62
+ return if protect_excluded_by_url?(context)
63
+
62
64
  result = find_attacker(context, xml, framework: framework)
63
65
  return unless result
64
66
 
@@ -28,12 +28,14 @@ require 'contrast/agent/protect/rule/sqli/default_sql_scanner'
28
28
  require 'contrast/agent/protect/rule/sqli/mysql_sql_scanner'
29
29
  require 'contrast/agent/protect/rule/sqli/postgres_sql_scanner'
30
30
  require 'contrast/agent/protect/rule/sqli/sqlite_sql_scanner'
31
+ require 'contrast/agent/protect/rule/sqli/sqli_semantic/sqli_dangerous_functions'
31
32
 
32
33
  # The classes required for Path Traversal
33
34
  require 'contrast/agent/protect/rule/path_traversal'
34
35
 
35
- # The classes required for Command Injection
36
+ # The classes required for Command Injection and sub-rules
36
37
  require 'contrast/agent/protect/rule/cmd_injection'
38
+ require 'contrast/agent/protect/rule/cmdi/cmdi_backdoors'
37
39
 
38
40
  # The classes required for XXE
39
41
  require 'contrast/agent/protect/rule/xxe'
@@ -25,6 +25,10 @@ module Contrast
25
25
  attr_accessor :virtual_patch
26
26
 
27
27
  class << self
28
+ # @param context [Contrast::Agent::RequestContext]
29
+ # @param ia_result [Contrast::Api::Settings::InputAnalysisResult] the analysis of the input that was
30
+ # determined to be an attack
31
+ # @return [Contrast::Agent::Reporting::RaspRuleSample]
28
32
  def build context, ia_result
29
33
  sample = new
30
34
  sample.time_stamp = context&.timer&.start_ms
@@ -35,6 +39,8 @@ module Contrast
35
39
  sample
36
40
  end
37
41
 
42
+ # @param ia_result [Contrast::Api::Settings::InputAnalysisResult] the analysis of the input that was
43
+ # determined to be an attack
38
44
  def build_user_input_from_ia ia_result
39
45
  # TODO: RUBY-99999 remove once only using Agent IA
40
46
  result = if ia_result.cs__is_a?(Contrast::Api::Settings::InputAnalysisResult)
@@ -0,0 +1,22 @@
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/reporting/details/protect_rule_details'
5
+
6
+ module Contrast
7
+ module Agent
8
+ module Reporting
9
+ module Details
10
+ # SqliDangerousFunctions IA result details info.
11
+ class SqliDangerousFunctions < ProtectRuleDetails
12
+ # @return [String]
13
+ attr_accessor :query
14
+
15
+ def to_controlled_hash
16
+ { query: query }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -125,8 +125,7 @@ module Contrast
125
125
  #
126
126
  # @return [Boolean]
127
127
  def app_create_complete?
128
- return true if Contrast::CONTRAST_SERVICE.use_agent_communication?
129
- return true if Contrast::Agent.messaging_queue&.speedracer&.status&.startup_messages_sent?
128
+ return true if Contrast::APP_CONTEXT.session_id
130
129
 
131
130
  logger.debug('Service startup incomplete; Application may not be created; sleeping')
132
131
  sleep(5)
@@ -23,8 +23,8 @@ module Contrast
23
23
 
24
24
  def to_controlled_hash
25
25
  {
26
- environment: ::Contrast::CONFIG.root.server.environment,
27
- tags: ::Contrast::CONFIG.root.server.tags,
26
+ environment: ::Contrast::CONFIG.server.environment,
27
+ tags: ::Contrast::CONFIG.server.tags,
28
28
  version: Contrast::Agent::VERSION
29
29
  }
30
30
  end
@@ -19,14 +19,11 @@ module Contrast
19
19
  attr_accessor :query_count
20
20
  # @return [Array]
21
21
  attr_accessor :routes
22
- # @return [Array]
23
- attr_accessor :dynamic_sources
24
22
  # @return [Contrast::Agent::Response]
25
23
  attr_accessor :response
26
24
 
27
25
  def initialize
28
26
  @routes = []
29
- @dynamic_sources = {}
30
27
  @query_count = 0
31
28
  @event_method = :PUT
32
29
  @event_type = :application_activity
@@ -77,7 +74,7 @@ module Contrast
77
74
  results << case response_type
78
75
  when BLOCKED, BLOCK_AT_PERIMETER
79
76
  attacker.protection_rules[rule_id].blocked
80
- when EXPLOITED
77
+ when MONITORED
81
78
  attacker.protection_rules[rule_id].exploited
82
79
  when PROBED
83
80
  attacker.protection_rules[rule_id].ineffective
@@ -27,7 +27,7 @@ module Contrast
27
27
  #
28
28
  # @return [Hash]
29
29
  def to_controlled_hash
30
- app_config = ::Contrast::CONFIG.root.application
30
+ app_config = ::Contrast::CONFIG.application
31
31
  {
32
32
  code: app_config.code,
33
33
  group: app_config.group,
@@ -29,18 +29,6 @@ module Contrast
29
29
  AC_TYPE_DB = 'db'
30
30
  VALID_TYPES = %w[db ldap ws].cs__freeze
31
31
 
32
- # class << self
33
- # # Convert a DTM for SpeedRacer to an Event for TeamServer.
34
- # #
35
- # # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent]
36
- # # @return [Contrast::Agent::Reporting::ArchitectureComponent]
37
- # def convert component_dtm
38
- # report = new
39
- # report.attach_data(component_dtm)
40
- # report
41
- # end
42
- # end
43
-
44
32
  class << self
45
33
  def build_database
46
34
  msg = new
@@ -49,17 +37,6 @@ module Contrast
49
37
  end
50
38
  end
51
39
 
52
- # # Attach the data from the protobuf models to this reporter so that it can be sent to TeamServer directly.
53
- # #
54
- # # @param component_dtm [Contrast::Api::Dtm::ArchitectureComponent]
55
- # def attach_data component_dtm
56
- # @remote_host = component_dtm.remote_host
57
- # @remote_port = component_dtm.remote_port
58
- # @type = component_dtm.type
59
- # @url = component_dtm.url
60
- # @vendor = component_dtm.vendor
61
- # end
62
-
63
40
  # Convert the instance variables on the class, and other information, into the identifiers required for
64
41
  # TeamServer to process the JSON form of this message.
65
42
  #
@@ -29,14 +29,14 @@ module Contrast
29
29
  # @return [Array<Contrast::Agent::Reporting::FindingEvent>] the events associated with this finding, if the
30
30
  # finding is event (dataflow) based.
31
31
  attr_reader :events
32
- # @return [String] the evidence associated with this finding, if the finding is event based. deprecated in
33
- # favor of properties
32
+ # # @return [String] the evidence associated with this finding, if the finding is event based. deprecated in
33
+ # # favor of properties
34
34
  # attr_reader :evidence
35
35
  # @return [Hash<String,String>] properties that prove the violation of the rule for this finding
36
36
  attr_reader :properties
37
37
  # @return [Contrast::Agent::Reporting::FindingRequest] the request associated with this finding, if the finding
38
38
  # is request based
39
- attr_reader :request
39
+ attr_accessor :request
40
40
  # @return [String] the uniquely identifying hash of this finding
41
41
  attr_accessor :hash_code
42
42
 
@@ -54,16 +54,6 @@ module Contrast
54
54
  xxssprotection-header-disabled
55
55
  ].cs__freeze
56
56
 
57
- class << self
58
- # @param finding_dtm [Contrast::Api::Dtm::Finding]
59
- # @return [Contrast::Agent::Reporting::Finding]
60
- def convert finding_dtm
61
- report = new(finding_dtm.rule_id)
62
- report.attach_property_data(finding_dtm)
63
- report
64
- end
65
- end
66
-
67
57
  def initialize rule_id
68
58
  @event_method = :PUT
69
59
  @event_endpoint = "#{ Contrast::API.api_url }/api/ng/traces"
@@ -100,28 +90,10 @@ module Contrast
100
90
  event_data = Contrast::Agent::Assess::Events::EventData.new(trigger_node, source, object, ret, args)
101
91
  contrast_event = Contrast::Agent::Assess::ContrastEvent.new(event_data)
102
92
  events << Contrast::Agent::Reporting::FindingEvent.convert(contrast_event)
103
- attach_properties
104
93
  return unless request
105
94
 
106
95
  @request = Contrast::Agent::Reporting::FindingRequest.convert(request)
107
- @routes << Contrast::Agent::Reporting::RouteDiscovery.convert(request.route) if request.route
108
- end
109
-
110
- # Attach the data from a Contrast::Api::Dtm::Finding required for property based findings generated during
111
- # response analysis.
112
- #
113
- # @param finding_dtm [Contrast::Api::Dtm::Finding]
114
- def attach_property_data finding_dtm
115
- @hash_code = finding_dtm.hash_code
116
- @rule_id = finding_dtm.rule_id
117
- finding_dtm.properties.each_pair do |key, value|
118
- @properties[key] = value
119
- end
120
- finding_dtm.routes.each do |route|
121
- @routes << Contrast::Agent::Reporting::RouteDiscovery.convert(route)
122
- end
123
- request = Contrast::Agent::REQUEST_TRACKER.current&.request
124
- @request = Contrast::Agent::Reporting::FindingRequest.convert(request) if request
96
+ @routes << request.discovered_route if request.discovered_route
125
97
  end
126
98
 
127
99
  # Convert the instance variables on the class, and other information, into the identifiers required for
@@ -137,16 +109,9 @@ module Contrast
137
109
  return
138
110
  end
139
111
 
140
- hsh = {
141
- created: created,
142
- hash: hash_code.to_s,
143
- ruleId: rule_id,
144
- session_id: ::Contrast::ASSESS.session_id,
145
- version: 4
146
- }
147
- hsh[:events] = events.map(&:to_controlled_hash) if event_based?
148
- # hsh[:evidence] = evidence unless event_based? || property_based?
149
- hsh[:properties] = properties if property_based?
112
+ hsh = base_hash
113
+ hsh[:events] = events.map(&:to_controlled_hash) if events.any?
114
+ hsh[:properties] = properties if properties.any?
150
115
  hsh[:tags] = Contrast::ASSESS.tags if Contrast::ASSESS.tags
151
116
  return hsh unless request_based?
152
117
 
@@ -155,6 +120,17 @@ module Contrast
155
120
  hsh
156
121
  end
157
122
 
123
+ # @return [Hash] the base of every finding, regardless of type
124
+ def base_hash
125
+ {
126
+ created: created,
127
+ hash: hash_code.to_s,
128
+ ruleId: rule_id,
129
+ session_id: ::Contrast::ASSESS.session_id,
130
+ version: 4
131
+ }
132
+ end
133
+
158
134
  # @raise [ArgumentError]
159
135
  def validate
160
136
  raise(ArgumentError, "#{ self } did not have a proper rule. Unable to continue.") unless @rule_id
@@ -174,12 +150,6 @@ module Contrast
174
150
 
175
151
  private
176
152
 
177
- # Our events have properties on them. To report them to TeamServer, we need to pull them from our object up to
178
- # the Contrast::Agent::Reporting::Finding level.
179
- #
180
- # TODO: RUBY-99999 put properties on events, not just on DTM
181
- def attach_properties; end
182
-
183
153
  def build_events events, event
184
154
  return unless event
185
155
 
@@ -196,7 +166,7 @@ module Contrast
196
166
  #
197
167
  # @return [Boolean]
198
168
  def event_based?
199
- !property_based? && !config_based?
169
+ !property_based? && !config_based? && !hardcoded?
200
170
  end
201
171
 
202
172
  # Rules which are property based must have a property to be sent to TeamServer. Eventually, each rule may own
@@ -100,6 +100,10 @@ module Contrast
100
100
  end
101
101
  end
102
102
 
103
+ def initialize
104
+ @event_sources = []
105
+ end
106
+
103
107
  # Parse the data from a Contrast::Agent::Assess::ContrastEvent to attach what is required for reporting to
104
108
  # TeamServer to this Contrast::Agent::Reporting::FindingEvent
105
109
  #
@@ -208,11 +212,9 @@ module Contrast
208
212
  #
209
213
  # @param event [Contrast::Agent::Assess::ContrastEvent]
210
214
  def event_sources! event
211
- @event_sources = []
212
215
  return unless event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
213
216
 
214
- source = Contrast::Agent::Reporting::FindingEventSource.convert(event)
215
- event_sources << source if source
217
+ event_sources << event.event_source if event.event_source
216
218
  end
217
219
 
218
220
  # Convert the parent id's of the given ContrastEvent to the reportable form for this FindingEvent.
@@ -237,12 +239,13 @@ module Contrast
237
239
  #
238
240
  # @param event [Contrast::Agent::Assess::ContrastEvent]
239
241
  def stack! event
240
- @stack = []
241
- event.stack_trace.each do |stack_event|
242
- if (report = Contrast::Agent::Reporting::FindingEventStack.convert(stack_event))
243
- stack << report
244
- end
245
- end
242
+ @stack = if event.stack_trace
243
+ event.stack_trace.compact.map! do |stack_event|
244
+ Contrast::Agent::Reporting::FindingEventStack.new(stack_event)
245
+ end
246
+ else
247
+ Contrast::Utils::ObjectShare::EMPTY_ARRAY
248
+ end
246
249
  end
247
250
 
248
251
  # Convert the taint ranges of the given ContrastEvent to the reportable form for this FindingEvent.
@@ -61,7 +61,7 @@ module Contrast
61
61
  # 8 is STATIC in Java... we have to placate them for now it has been requested that flags be removed since it
62
62
  # isn't used
63
63
  @flags = 8 unless node.instance_method?
64
- @method_name = node.method_name
64
+ @method_name = node.method_name.to_s
65
65
  @return_type = type_name(event.ret)
66
66
  # if there's a ret, then this method isn't nil. not 100% full proof since you can return nil, but this is the
67
67
  # best we've got currently.
@@ -2,8 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'base64'
5
- require 'contrast/agent/assess/contrast_event'
6
- require 'contrast/agent/assess/events/source_event'
7
5
  require 'contrast/components/logger'
8
6
 
9
7
  module Contrast
@@ -21,25 +19,11 @@ module Contrast
21
19
  # @return [String] the type of the source
22
20
  attr_reader :type
23
21
 
24
- class << self
25
- # @param event [Contrast::Agent::Assess::Events::ContrastEvent] the event to pull the source off of
26
- # @return [Contrast::Agent::Reporting::FindingEventSource]
27
- def convert event
28
- return unless event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
29
-
30
- report = new
31
- report.attach_data(event)
32
- report
33
- end
34
- end
35
-
36
- # Parse the data from a Contrast::Agent::Assess::Events::SourceEvent to attach what is required for reporting
37
- # to TeamServer to this Contrast::Agent::Reporting::FindingEventSource
38
- #
39
- # @param event [Contrast::Agent::Assess::Events::SourceEvent] the event to pull the source off of
40
- def attach_data event
41
- @name = event.source_name
42
- @type = event.source_type
22
+ # @param type [String]
23
+ # @param name [String]
24
+ def initialize type, name
25
+ @type = type
26
+ @name = name
43
27
  end
44
28
 
45
29
  # Convert the instance variables on the class, and other information, into the identifiers required for
@@ -61,6 +45,24 @@ module Contrast
61
45
  }
62
46
  end
63
47
 
48
+ # Convert this EventSource into the format expected for route observation
49
+ #
50
+ # @return [Hash]
51
+ # @raise [ArgumentError]
52
+ def to_controlled_observation_hash
53
+ begin
54
+ validate
55
+ rescue ArgumentError => e
56
+ logger.error('FindingEventSource observation validation failed with: ', e)
57
+ return
58
+ end
59
+
60
+ {
61
+ name: name, # rubocop:disable Security/Module/Name
62
+ type: type
63
+ }
64
+ end
65
+
64
66
  # @raise [ArgumentError]
65
67
  def validate
66
68
  raise(ArgumentError, "#{ self } did not have a proper type. Unable to continue.") unless type && !type.empty?
@@ -28,25 +28,12 @@ module Contrast
28
28
 
29
29
  AGENT_CLASS_MARKER = '/lib/contrast/'
30
30
 
31
- class << self
32
- # @param stack [String]
33
- # @return [Contrast::Agent::Reporting::FindingEventStack,nil]
34
- def convert stack
35
- return unless stack
36
- return if stack.include?(AGENT_CLASS_MARKER)
37
-
38
- report = new
39
- report.attach_data(stack)
40
- report
41
- end
42
- end
43
-
44
- # Parse the data from a Contrast::Agent::Assess::Tag to attach what is required for reporting to TeamServer to
45
- # this Contrast::Agent::Reporting::FindingEventTaintRange
31
+ # To play nice with the way that TeamServer is rendering these values, we only populate the file_name field with
32
+ # exactly what we want them to display.
46
33
  #
47
- # @param stack [String]
48
- def attach_data stack
49
- @file = stack
34
+ # @param file_name [String] the caller location this stack frame represents.
35
+ def initialize file_name
36
+ @file = file_name
50
37
  end
51
38
 
52
39
  # Convert the instance variables on the class, and other information, into the identifiers required for
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'contrast/agent/assess/tag'
5
+ require 'contrast/agent/reporting/reporting_events/finding_event_taint_range_tags'
5
6
  require 'contrast/components/logger'
6
7
 
7
8
  module Contrast
@@ -2,13 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Contrast
5
- module Api
6
- module Decorators
7
- # A holder for the valid tags that can be sent to the Service, and
8
- # ultimately TS, that we have to honor. Placed here so as not to clutter
9
- # other code.
10
- module TraceTaintRangeTags
5
+ module Agent
6
+ module Reporting
7
+ # A holder for the valid tags that can be sent to TeamServer that we have to honor. Placed here so as not to
8
+ # clutter other code.
9
+ module FindingEventTaintRangeTags
11
10
  # EventTagTypeDTM
11
+ # @return [Array<Symbol>]
12
12
  VALID_TAGS = %w[
13
13
  XML_ENCODED
14
14
  XML_DECODED
@@ -97,6 +97,7 @@ module Contrast
97
97
  DATABASE_WRITE
98
98
  ].cs__freeze
99
99
 
100
+ # @return [Array<Symbol>]
100
101
  VALID_SOURCE_TAGS = %w[NO_NEWLINES UNTRUSTED CROSS_SITE LIMITED_CHARS].cs__freeze
101
102
  end
102
103
  end
@@ -40,7 +40,7 @@ module Contrast
40
40
  # @return [Hash]
41
41
  attr_reader :cookies
42
42
  # REMOVE_DTM_REQUEST
43
- # @return [Contrast::Api::Dtm::RawRequest]
43
+ # @return [Contrast::Api::Dtm::HttpRequest]
44
44
  attr_reader :dtm
45
45
 
46
46
  class << self
@@ -11,7 +11,7 @@ module Contrast
11
11
  include Contrast::Components::Logger::InstanceMethods
12
12
 
13
13
  # @param [String] Sha256Sum of library as identified by the agent
14
- attr_accessor :id
14
+ attr_reader :id
15
15
  # @param [Array<String>] List of file paths that have been loaded out of or executed by the library
16
16
  attr_reader :names
17
17
 
@@ -24,7 +24,7 @@ module Contrast
24
24
  attr_accessor :url
25
25
  # @param [String] the HTTP Verb used to access the method in the route.
26
26
  attr_accessor :verb
27
- # @param [Array<Contrast::Agent::Reporting::TraceEventSource>] the sources of user input accessed during this
27
+ # @param [Array<Contrast::Agent::Reporting::FindingEventSource>] the sources of user input accessed during this
28
28
  # request. Used for remediation determinations in TeamServer.
29
29
  attr_reader :sources
30
30
 
@@ -56,7 +56,7 @@ module Contrast
56
56
 
57
57
  {
58
58
  session_id: ::Contrast::ASSESS.session_id,
59
- sources: @sources.map(&:to_controlled_hash),
59
+ sources: @sources.map(&:to_controlled_observation_hash),
60
60
  signature: @signature,
61
61
  verb: @verb,
62
62
  url: @url