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

Returns a new instance of 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)

Returns the time, in ms, that this object was initialized.

Returns:

  • (Integer)

    the time, in ms, that this object was initialized



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

def created
  @created
end

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

Returns the events associated with this finding, if the finding is event (dataflow) based.

Returns:



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

def events
  @events
end

#hash_codeString

Returns the uniquely identifying hash of this finding.

Returns:

  • (String)

    the uniquely identifying hash of this finding



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

Returns:

  • (Hash<String,String>)

    properties that prove the violation of the rule for this finding



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

def properties
  @properties
end

#requestContrast::Agent::Reporting::FindingRequest

Returns the request associated with this finding, if the finding is request based.

Returns:



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

def request
  @request
end

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

Returns the routes associated with this finding, if the finding is request based.

Returns:



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

def routes
  @routes
end

#rule_idString (readonly)

Returns the ID of the rule associated with this finding.

Returns:

  • (String)

    the ID of the rule associated with this finding



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

Parameters:



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.

Parameters:

  • request (Net::HTTPRequest)


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

Returns the base of every finding, regardless of type.

Returns:

  • (Hash)

    the base of every finding, regardless of type



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.

Returns:

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