# Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/utils/object_share' require 'contrast/agent/reporting/input_analysis/input_type' require 'contrast/agent/protect/rule/sqli' require 'contrast/agent/reporting/input_analysis/score_level' require 'contrast/agent/protect/rule/sqli/sqli_worth_watching' require 'contrast/agent/protect/input_analyzer/input_analyzer' require 'contrast/utils/input_classification' require 'contrast/components/logger' module Contrast module Agent module Protect module Rule # This module will do the Input Classification stage of SQLI rule # as a result input would be marked as WORTHWATCHING or IGNORE, # to be analyzed at the sink level. module SqliInputClassification class << self include InputClassificationBase include Contrast::Agent::Protect::Rule::SqliWorthWatching include Contrast::Components::Logger::InstanceMethods WORTHWATCHING_MATCH = 'sqli-worth-watching-v2' SQLI_KEYS_NEEDED = [ COOKIE_VALUE, PARAMETER_VALUE, JSON_VALUE, MULTIPART_VALUE, XML_VALUE, DWR_VALUE ].cs__freeze # Input Classification stage is done to determine if an user input is # WORTHWATCHING or to be ignored. # # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input. # @param value [String, Array<String>] the value of the input. # @param input_analysis [Contrast::Agent::Reporting::InputAnalysis] Holds all the results from the # agent analysis from the current # Request. # @return ia [Contrast::Agent::Reporting::InputAnalysis] with updated results. def classify input_type, value, input_analysis return unless Contrast::Agent::Protect::Rule::Sqli::APPLICABLE_USER_INPUTS.include?(input_type) return unless super rule_id = Contrast::Agent::Protect::Rule::Sqli::NAME # double check the input to avoid calling match? on array Array(value).each do |val| Array(val).each do |v| input_analysis.results << sqli_create_new_input_result(input_analysis.request, rule_id, input_type, v) end end input_analysis rescue StandardError => e logger.debug('An Error was recorded in the input classification of the sqli.') logger.debug(e) end private # This methods checks if input is tagged WORTHWATCHING or IGNORE matches value with it's # key if needed and Creates new isntance of InputAnalysisResult. # # @param request [Contrast::Agent::Request] the current request context. # @param rule_id [String] The name of the Protect Rule. # @param input_type [Contrast::Agent::Reporting::InputType] The type of the user input. # @param value [String, Array<String>] the value of the input. # # @return res [Contrast::Agent::Reporting::InputAnalysisResult] def sqli_create_new_input_result request, rule_id, input_type, value ia_result = new_ia_result(rule_id, input_type, request.path, value) if sqli_worth_watching?(value) ia_result.ids << WORTHWATCHING_MATCH ia_result.score_level = WORTHWATCHING ia_result else ia_result.score_level = IGNORE end add_needed_key(request, ia_result, input_type, value) if SQLI_KEYS_NEEDED.include?(input_type) ia_result end end end end end end end