# Copyright (c) 2020 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/agent/protect/rule/cmd_injection' require 'contrast/agent/protect/policy/applies_deserialization_rule' require 'contrast/agent/protect/policy/rule_applicator' module Contrast module Agent module Protect module Policy # This Module is how we apply the Command Injection rule. It is called # from our patches of the targeted methods in which command execution # occurs. It is responsible for deciding if the infilter methods of the # rule should be invoked. # In addition, b/c of the nature of Deserialization's sand boxing # function, this Module's apply methods call through to the # {#apply_deserialization_command_check} method of the # Deserialization applicator. module AppliesCommandInjectionRule extend Contrast::Agent::Protect::Policy::RuleApplicator CS__SEMICOLON = '; ' class << self def invoke method, _exception, _properties, object, args return unless valid_command?(args) command = build_command(args) Contrast::Agent::Protect::Policy::AppliesDeserializationRule.apply_deserialization_command_check(command) return if skip_analysis? begin clazz = object.is_a?(Module) ? object : object.cs__class class_name = clazz.cs__name rule.infilter(Contrast::Agent::REQUEST_TRACKER.current, class_name, method, command) end end protected def name Contrast::Agent::Protect::Rule::CmdInjection::NAME end private def valid_command? command command && (command.is_a?(String) || command.is_a?(Array)) end def build_command command return command if command.is_a?(String) command = command.drop(1) if command.length > 1 command.join(CS__SEMICOLON) end end end end end end end