# Copyright (c) 2022 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' module Contrast module Utils # We use this class to provide hashes for our Request and Finding objects # based upon our definitions of uniqueness. # While the uniqueness of the request object is something internal to the # 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 module HashDigestExtend # Generates the hash checksum for the request. Converts the request method, uri, # param names and content length to CRC checksum and returns string representation # # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request. # @return checksum [String] String representation of CRC32 checksum 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[Contrast::Utils::HashDigest::CONTENT_LENGTH_HEADER] hash.update_on_content_length(cl) if cl hash.finish end # Generates the hash checksum for the event, either dataflow, # crypto(crypto-bad-ciphers, crypto-bad-mac) rules or trigger event # and returns string representation. # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @param source [Object] the source of the Trigger Event # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request. # @return checksum [String] String representation of CRC32 checksum 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 Contrast::Utils::HashDigest::CRYPTO_RULES.include?(id) generate_trigger_hash(finding, request) end # Generates the hash checksum for configurations. Converts the finding rule_id, session_id and configPath and # to CRC32 checksum and returns string representation to be appended to Contrast::Api::Dtm::Finding # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @return checksum [String] String representation of CRC32 checksum. def generate_config_hash finding hash = new hash.update(finding.rule_id) path = finding.properties[Contrast::Utils::HashDigest::CONFIG_PATH_KEY] hash.update(path) method = finding.properties[Contrast::Utils::HashDigest::CONFIG_SESSION_ID_KEY] hash.update(method) hash.finish end # Generates the hash checksum for class scanning. Converts the rule_id, finding.properties(source, name) # to CRC32 checksum and returns string representation. # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @return checksum [String] String representation of CRC32 checksum. def generate_class_scanning_hash finding hash = new hash.update(finding.rule_id) module_name = finding.properties[Contrast::Utils::HashDigest::CLASS_SOURCE_KEY] hash.update(module_name) # We're not currently collecting this. 30/7/19 HM line_no = finding.properties[Contrast::Utils::HashDigest::CLASS_LINE_NO_KEY] hash.update(line_no) field = finding.properties[Contrast::Utils::HashDigest::CLASS_CONSTANT_NAME_KEY] hash.update(field) hash.finish end private # Generates the hash checksum for crypto(crypto-bad-ciphers, crypto-bad-mac) rules. # used in #generate_event_hash. # # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @param algorithm [Object] the source of the Trigger Event # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request. # @return checksum [String] String representation of CRC32 checksum 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 # Generates the hash checksum for dataflow when the finding events are more than one # used in #generate_event_hash. # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request. # @return checksum [String] String representation of CRC32 checksum 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 # Generates the hash checksum for trigger # used in #generate_event_hash. # # @param finding [Contrast::Agent::Reporting::Finding] to be reported # @param request [Contrast::Agent::Request] our wrapper around the Rack::Request. # @return checksum [String] String representation of CRC32 checksum def generate_trigger_hash finding, request hash = new hash.update(finding.rule_id) hash.update_on_request(finding, request) hash.finish end end end end