lib/contrast/utils/hash_digest.rb in contrast-agent-4.13.1 vs lib/contrast/utils/hash_digest.rb in contrast-agent-4.14.0
- old
+ new
@@ -1,9 +1,10 @@
# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
# frozen_string_literal: true
require 'digest'
+require 'contrast/utils/hash_digest_extend'
module Contrast
module Utils
# We use this class to provide hashes for our Request and Finding objects
# based upon our definitions of uniqueness.
@@ -11,89 +12,20 @@
# Ruby agent, the uniqueness of the Finding hash is defined by a
# specification shared across all agent teams. The spec can be found here:
# https://bitbucket.org/contrastsecurity/assess-specifications/src/master/vulnerability/preflight.md
class HashDigest < Digest::Class
include Digest::Instance
+ extend Contrast::Utils::HashDigestExtend
CONTENT_LENGTH_HEADER = 'Content-Length'
CRYPTO_RULES = %w[crypto-bad-ciphers crypto-bad-mac].cs__freeze
CONFIG_PATH_KEY = 'path'
CONFIG_SESSION_ID_KEY = 'sessionId'
CLASS_SOURCE_KEY = 'source'
CLASS_CONSTANT_NAME_KEY = 'name'
CLASS_LINE_NO_KEY = 'lineNo'
- class << self
- def generate_request_hash request
- hash = new
- hash.update(request.request_method)
- hash.update(request.normalized_uri)
- request.parameters.each_key do |name|
- hash.update(name)
- end
- cl = request.headers[CONTENT_LENGTH_HEADER]
- hash.update_on_content_length(cl) if cl
- hash.finish
- end
- def generate_event_hash finding, source, request
- return generate_dataflow_hash(finding, request) if finding.events.length.to_i > 1
-
- id = finding.rule_id
- return generate_crypto_hash(finding, source, request) if CRYPTO_RULES.include?(id)
-
- generate_trigger_hash(finding, request)
- end
-
- def generate_config_hash finding
- hash = new
- hash.update(finding.rule_id)
- path = finding.properties[CONFIG_PATH_KEY]
- hash.update(path)
- method = finding.properties[CONFIG_SESSION_ID_KEY]
- hash.update(method)
- hash.finish
- end
-
- def generate_class_scanning_hash finding
- hash = new
- hash.update(finding.rule_id)
- module_name = finding.properties[CLASS_SOURCE_KEY]
- hash.update(module_name)
- # We're not currently collecting this. 30/7/19 HM
- line_no = finding.properties[CLASS_LINE_NO_KEY]
- hash.update(line_no)
- field = finding.properties[CLASS_CONSTANT_NAME_KEY]
- hash.update(field)
- hash.finish
- end
-
- private
-
- def generate_crypto_hash finding, algorithm, request
- hash = new
- hash.update(finding.rule_id)
- hash.update(algorithm)
- hash.update_on_request(finding, request)
- hash.finish
- end
-
- def generate_dataflow_hash finding, request
- hash = new
- hash.update(finding.rule_id)
- hash.update_on_sources(finding.events)
- hash.update_on_request(finding, request)
- hash.finish
- end
-
- def generate_trigger_hash finding, request
- hash = new
- hash.update(finding.rule_id)
- hash.update_on_request(finding, request)
- hash.finish
- end
- end
-
def update_on_request finding, request
if (route = finding.routes[0])
update(route.route)
update(route.verb)
elsif request ||= Contrast::Agent::REQUEST_TRACKER.current&.request
@@ -104,12 +36,17 @@
def update_on_sources events
return unless events&.any?
events.each do |event|
- event.event_sources.each do |source|
- update(source.type)
- update(source.name) # rubocop:disable Security/Module/Name -- API attribute.
+ if event.cs__is_a?(Contrast::Api::Dtm::TraceEvent)
+ event.event_sources&.each do |source|
+ update(source.type)
+ update(source.name) # rubocop:disable Security/Module/Name
+ end
+ elsif event.cs__is_a?(Contrast::Agent::Assess::Events::SourceEvent)
+ update(event.source_type)
+ update(event.source_name)
end
end
end
CHARS = %w[a b c d e f g].cs__freeze