# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true cs__scoped_require 'contrast/components/interface' cs__scoped_require 'contrast/utils/data_store_util' module Contrast module CoreExtensions module Protect # This Module is how we apply the SQL Injection rule. It is called from # our patches of the targeted methods in which the execution of String # based SQL queries occur. It is responsible for deciding if the infilter # methods of the rule should be invoked. module AppliesSqliRule DATABASE_MYSQL = 'MySQL' DATABASE_SQLITE = 'SQLite3' DATABASE_PG = 'PostgreSQL' class << self include Contrast::Components::Interface access_component :logging, :analysis def apply_sql_rule method, _exception, properties, object, args database = properties['database'] return unless database index = properties[Contrast::Utils::ObjectShare::INDEX] return unless valid_input?(index, args) return if skip_analysis? sql = args[index] logger.debug(nil, "applying sqli rule on #{ object } for #{ method }") rule.infilter(Contrast::Agent::REQUEST_TRACKER.current, database, sql) rescue Contrast::SecurityException => e raise e rescue StandardError => e logger.error(e, "Error running SQLi rule in #{ object }") end private def rule PROTECT.rule Contrast::Agent::Protect::Rule::Sqli::NAME end def valid_input? index, args return false unless args && args.length > index sql = args[index] sql && !sql.empty? end def skip_analysis? context = Contrast::Agent::REQUEST_TRACKER.current return true unless context&.app_loaded? return true unless rule&.enabled? false end end end end end end