Class: Contrast::Agent::Reporting::Finding

Inherits:
ApplicationReportingEvent show all
Defined in:
lib/contrast/agent/reporting/reporting_events/finding.rb

Overview

This is the new Finding class which will include all the needed information for the new reporting system to relay this information in the Finding/Trace messages. These findings are used by TeamServer to construct the vulnerability information for the assess feature. They represent those parts of the application, either through configuration, method invocation, or dataflow, which are determined to be insecure.

Constant Summary collapse

CONFIGURATION_RULES =
%w[rails-http-only-disabled secure-flag-missing session-timeout].cs__freeze
HARDCODED_RULES =
%w[hardcoded-key hardcoded-password].cs__freeze
PROPERTIES_RULES =
%w[
  autocomplete-missing
  cache-controls-missing
  clickjacking-control-missing
  csp-header-missing
  csp-header-insecure
  hsts-header-missing
  parameter-pollution
  xcontenttype-header-missing
  xxssprotection-header-disabled
].cs__freeze

Instance Attribute Summary collapse

Attributes inherited from ReportingEvent

#event_endpoint, #event_method

Instance Method Summary collapse

Methods inherited from ReportableHash

#event_json, #valid?

Methods included from Components::Logger::InstanceMethods

#cef_logger, #logger

Constructor Details

#initialize(rule_id) ⇒ Finding



54
55
56
57
58
59
60
61
62
63
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 54

def initialize rule_id
  @event_method = :PUT
  @event_endpoint = "#{ Contrast::API.api_url }/api/ng/traces"
  @events = []
  @routes = []
  @rule_id = Contrast::Utils::StringUtils.truncate(rule_id)
  @properties = {}
  @created = Contrast::Utils::Timer.now_ms
  super()
end

Instance Attribute Details

#createdInteger (readonly)



20
21
22
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 20

def created
  @created
end

#eventsArray<Contrast::Agent::Reporting::FindingEvent> (readonly)



28
29
30
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 28

def events
  @events
end

#hash_codeString



38
39
40
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 38

def hash_code
  @hash_code
end

#propertiesHash<String,String> (readonly)

@return [String] the evidence associated with this finding, if the finding is event based. deprecated in

favor of properties

attr_reader :evidence



33
34
35
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 33

def properties
  @properties
end

#requestContrast::Agent::Reporting::FindingRequest



36
37
38
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 36

def request
  @request
end

#routesArray<Contrast::Agent::Reporting::RouteDiscovery> (readonly)



25
26
27
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 25

def routes
  @routes
end

#rule_idString (readonly)



22
23
24
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 22

def rule_id
  @rule_id
end

Instance Method Details

#attach_data(trigger_node, source, object, ret, request, *args) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 84

def attach_data trigger_node, source, object, ret, request, *args
  event_messages = Contrast::Agent::Reporting::FindingEvent.from_source(source)
  events.concat(event_messages) if event_messages&.any?
  event_data = Contrast::Agent::Assess::Events::EventData.new(trigger_node, source, object, ret, args)
  contrast_event = Contrast::Agent::Reporting::FindingEvent.new(event_data)
  events << contrast_event
  return unless request

  @request = Contrast::Agent::Reporting::FindingRequest.convert(request)
  @routes << request.discovered_route if request.discovered_route
end

#attach_headers(request) ⇒ Object

Some reports require specific additional headers to be used. To that end, we'll attach them here, letting each handle their own.



73
74
75
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 73

def attach_headers request
  request['Report-Hash'] = hash_code
end

#base_hashHash



115
116
117
118
119
120
121
122
123
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 115

def base_hash
  {
      created: created,
      hash: hash_code.to_s,
      ruleId: rule_id,
      session_id: ::Contrast::ASSESS.session_id,
      version: 4
  }.compact
end

#file_nameObject



65
66
67
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 65

def file_name
  'traces'
end

#to_controlled_hashHash

Convert the instance variables on the class, and other information, into the identifiers required for TeamServer to process the JSON form of this message.

Raises:

  • (ArgumentError)


101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 101

def to_controlled_hash
  validate
  hsh = base_hash
  hsh[:events] = events.map(&:to_controlled_hash) if events.any?
  hsh[:properties] = properties if properties.any?
  hsh[:tags] = Contrast::ASSESS.tags if Contrast::ASSESS.tags
  return hsh unless request_based?

  hsh[:request] = request.to_controlled_hash
  hsh[:routes] = routes.map(&:to_controlled_hash)
  hsh
end

#validateObject

Raises:

  • (ArgumentError)


126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/contrast/agent/reporting/reporting_events/finding.rb', line 126

def validate
  raise(ArgumentError, "#{ self } did not have a proper rule. Unable to continue.") unless @rule_id
  if event_based? && events.empty?
    raise(ArgumentError, "#{ self } did not have proper events for #{ @rule_id }. Unable to continue.")
  end
  if property_based? && properties.empty?
    raise(ArgumentError, "#{ self } did not have proper properties for #{ @rule_id }. Unable to continue.")
  end
  return unless request_based? && request.nil?

  raise(ArgumentError, "#{ self } did not have a proper request for #{ @rule_id }. Unable to continue.")
end