Class: Contrast::Agent::Protect::Rule::Base Abstract

Inherits:
Object
  • Object
show all
Includes:
Components::Interface
Defined in:
lib/contrast/agent/protect/rule/base.rb

Overview

This class is abstract.

Subclass and override #prefilter, #infilter, #find_attacker, #postfilter and #build_details to implement

This is a basic rule for Protect. It’s the abstract class which all other protect rules extend in order to function.

Direct Known Subclasses

BaseService, Deserialization, Xxe

Constant Summary collapse

UNKNOWN_USER_INPUT =
Contrast::Api::Dtm::UserInput.new.tap do |user_input|
  user_input.input_type = :UNKNOWN
end
BLOCKING_MODES =
Set.new([Contrast::Api::Settings::ProtectionRule::Mode::BLOCK,
Contrast::Api::Settings::ProtectionRule::Mode::BLOCK_AT_PERIMETER]).cs__freeze
POSTFILTER_MODES =
Set.new([Contrast::Api::Settings::ProtectionRule::Mode::BLOCK,
Contrast::Api::Settings::ProtectionRule::Mode::PERMIT,
Contrast::Api::Settings::ProtectionRule::Mode::MONITOR]).cs__freeze
STACK_COLLECTION_RESULTS =
Set.new([Contrast::Api::Dtm::AttackResult::ResponseType::BLOCKED,
Contrast::Api::Dtm::AttackResult::ResponseType::MONITORED]).cs__freeze
OFF =
'off'

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Components::Interface

included

Constructor Details

#initialize(default_mode = Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION) ⇒ Base

Returns a new instance of Base.



33
34
35
36
# File 'lib/contrast/agent/protect/rule/base.rb', line 33

def initialize default_mode = Contrast::Api::Settings::ProtectionRule::Mode::NO_ACTION
  PROTECT.rules[name] = self
  @mode = mode_from_settings || default_mode
end

Instance Attribute Details

#modeObject (readonly)

Returns the value of attribute mode.



31
32
33
# File 'lib/contrast/agent/protect/rule/base.rb', line 31

def mode
  @mode
end

Instance Method Details

#append_to_activity(context, result) ⇒ Object



135
136
137
# File 'lib/contrast/agent/protect/rule/base.rb', line 135

def append_to_activity context, result
  context.activity.results << result if result
end

#build_attack_with_match(context, ia_result, result, candidate_string, **kwargs) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/contrast/agent/protect/rule/base.rb', line 119

def build_attack_with_match context, ia_result, result, candidate_string, **kwargs
  result ||= build_attack_result(context)
  update_successful_attack_response(context, ia_result, result, candidate_string)
  append_sample(context, ia_result, result, candidate_string, **kwargs)

  result
end

#build_attack_without_match(context, ia_result, result, **kwargs) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/contrast/agent/protect/rule/base.rb', line 127

def build_attack_without_match context, ia_result, result, **kwargs
  result ||= build_attack_result(context)
  update_perimeter_attack_response(context, ia_result, result)
  append_sample(context, ia_result, result, nil, **kwargs)

  result
end

#enabled?Boolean

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/contrast/agent/protect/rule/base.rb', line 45

def enabled?
  # 1. it is not enabled because protect is not enabled
  return false unless AGENT.enabled?
  return false unless PROTECT.enabled?

  rule_configs = PROTECT.rule_config
  unless rule_configs.nil?
    # 2. it is not enabled because it is in the list of disabled protect rules
    disabled_rules = rule_configs.disabled_rules
    return false if disabled_rules&.include?(name)

    # 3. it is not enabled because it has been turned "off" explicitly
    rule_config = rule_configs.send(name)

    return rule_config.mode != OFF unless rule_config.mode.nil?
  end

  # 4. it is not enabled because it's mode is :NO_ACTION
  @mode != :NO_ACTION
end

#excluded?(exclusions) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
# File 'lib/contrast/agent/protect/rule/base.rb', line 66

def excluded? exclusions
  Array(exclusions).any? do |ex|
    ex.protection_rule?(name)
  end
end

#infilter(_context, _match_string, **_kwargs) ⇒ Object

This should only ever be called directly from patched code and will have a different implementation based on the rule. As such, there is not parent implementation.

Parameters:

  • _context (Contrast::Agent::RequestContext)

    the context for the current request

  • _match_string (String)

    the input that violated the rule and matched the attack detection logic

  • _kwargs (Hash)

    key-value pairs used by the rule to build a report.



106
# File 'lib/contrast/agent/protect/rule/base.rb', line 106

def infilter _context, _match_string, **_kwargs; end

#infilter?(_context) ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/contrast/agent/protect/rule/base.rb', line 72

def infilter? _context
  false
end

#nameObject

Should return the name as it is known to Teamserver; defaults to class



39
40
41
# File 'lib/contrast/agent/protect/rule/base.rb', line 39

def name
  cs__class.name
end

#postfilter(_context) ⇒ Object

Actions required for the rules that have to happen after the application has completed its processing of the request.

Any implementation here needs to account for the fact that responses may be streaming and, as such, transformations of the response itself may not be permissible.

Parameters:



117
# File 'lib/contrast/agent/protect/rule/base.rb', line 117

def postfilter _context; end

#prefilter(_context) ⇒ Object

Actions required for the rules that have to happen before the application has completed its processing of the request.

For most rules, these actions are performed within the analysis engine and communicated as an input analysis result. Those that require specific action need to provide that action.

Parameters:



94
# File 'lib/contrast/agent/protect/rule/base.rb', line 94

def prefilter _context; end

#stream_safe?Boolean

return false for rules that modify or inspect the response body during postfilter

Returns:

  • (Boolean)

    if the rule can safely be evaluated in streaming requests



81
82
83
# File 'lib/contrast/agent/protect/rule/base.rb', line 81

def stream_safe?
  true
end